-
Notifications
You must be signed in to change notification settings - Fork 4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Using exportInstance and importInstance goes against convention and causes issues #237
Comments
So, reading over this and the docs a bunch tonight, I think I understand what Here's an example explaining it a bit better: https://stackoverflow.com/questions/44804009/messages-intended-for-one-script-in-the-background-context-are-received-by-all What
Which sends a message like:
Which would be picked up only by the Alas, the way it does this is by that low-level JS, which has to be run in the content script using the background script as an argument. For example, this line is in
That's no good because So...I still think these have to go, even if they are a (pretty) elegant solution to this problem. In their place, I think we'll want to roll our own message/response system, as explained by the Stackoverflow question above. I'll try to do a survey of solutions folks have for this in the wild. I'd love not to roll our own. |
BACKGROUND ~~~~~~~~~~ This is a step in the direction of nuking importInstance and exportInstance, and towards doing things the "normal" way, via message passing and listening. As mentioned in freelawproject/recap#237, the way we're doing this now makes it difficult to use certain functions, because those functions can only be used in background scripts that are not *also* content scripts. Since I need one of those functions to support zip upload in freelawproject/recap#117, I'm working to get this fixed. The only alternative to this that I could think of was to create a new file called recap_background.js, which would be a background-only script and then put my code in there, but I didn't love that approach since it separated things arbitrarily. IMPLEMENTATION ~~~~~~~~~~~~~~ The way I've implemented this is to move the uploadDocument function out of Recap(), and to put it under a listener at the bottom of the file. This listener checks for a package name of "recap", and then uses an if statement to listen for a function mame of "uploadDocument". The idea here is that I will move *all* of the existing functions in the Recap() object into this listener, and it will use the package check and function name check to run the right code. I've done a bit of research on this approach, and it appears that there's no right way to do this. This approach feels fairly clean to me though, so I think I'm comfortable going with it. Other approaches I considered were: - Using one listener per function. I like how this would allow us to have a cleaner separation of the functions (they're not just separated by if statements, but I didn't like how this would mean a lot of repetition of the package/function filtering within the beginning of each listener. - Using a simpler approach to function/package filtering. Could the function name just be "recap.uploadDocument" for example instead of using to keys in the object that we pass to the listener? - A few other things that aren't coming to mind right now (it's late). BIG QUESTIONS ~~~~~~~~~~~~~ 1. Can I refactor all of the functions to this format without breaking things? This is a big refactor, and thus dangerous. Going to need test coverage. 2. Is there a way we can simplify sendMessage? We went from 4 lines and one function call to 12 lines and one function call. That's not great. 3. What about tests? How do we pull this apart so that it's easy to also refactor the tests. This seems painful.
One approach that (in my opinion) could be slightly cleaner than the approach outlined here would be to leave the overall Recap() function intact and just call those functions from a single listener below. For example:
Some benefits to this could be:
I realize that it's pretty much just a preference thing with no tangible difference in functionality. |
So Mike noted that our approaches should strive to be more general. Since recap.js is not the only file that needs to remove exportInstance and importInstance, we should attempt to minimize the amount of similar code across files. I may have found such a way (although it seems a little odd). I started by noticing that the problematic files/functions (Recap and Notifier) return a javascript object where the "keys" are the function names. Because of this, we should be able to pass this object as an argument to a general listener function as described below. First, I added a basic function to Recap() to facilitate easy testing (the other functions are hard for me to test with since I'm only vaguely aware of their overall purpose):
testListener is one of many functions returned in the Recap object. Next, I create the general listener class in a new file (listener.js):
Like before, we will add a listener at the bottom of a file like recap while keeping the overall Recap() object definition intact. However, instead of a bunch of switch statements to check for all possible function names, the only thing we must do to create the listener is the following:
Now, to send a message to this listener, we could do the following:
Using the above code, we have a relatively simple way to send a message to listeners. In this case, our listener would take the arguments and return 6. A few notes:
|
This looks pretty good and feels pretty simple. Definitely getting pretty warm, and it avoids repeating just about anything, which is really nice. Simplifying your explanation (and reiterating it in my own words so you can correct me if I misunderstand):
The only thing that seems weird to me is the callback as an argument bit, but I guess that's kind of where we're at already where it's always the final argument to each function. Seems nicer though to do:
Or:
Or something like that. That's still a bit wordier than what we've got now:
Though perhaps that's just the way it has to be. It's certainly more explicit and less magic, but we're going from one line to 6, at best. But regardless, it does make sense to me not to have the callback as the last argument to the args array. |
Yes, your understanding of (1) and (2) is correct. As for (3), I see what you are saying. It should be pretty trivial to change it so that the callback is no longer in the args array. I think I am partial toward changing it to look like this suggestion:
|
Sounds good! |
We should do this as part of Manifest V3 upgrades, not before. Labeling accordingly. |
I believe we can close this too, @ERosendo? |
Yes @mlissner, The |
Thank goodness. |
Way back in 2013, @zestyping added a kind of strange mechanism to the RECAP Extensions. In it, he created a system for background scripts to call functions in content scripts, and vice versa.
freelawproject/recap-chrome@afaee9a
This has served us well, but I think I'm going to overhaul it, or at least somebody should. Here's why:
This goes against convention. The convention is that content scripts can communicate with background scripts via message passing, and that's it. The reason for this is security, and I've always been vaguely concerned that the way we do this isn't great for security.
The mechanism used here required that our background scripts also be listed as content scripts. This isn't ideal in itself (security issue?), but it also means that using things like the
webRequest
API, which can only be used in background scripts, becomes...difficult. Right now I want to use that API, but the only way I can do so is to put it in background.js, which is our only background script that's not also a content script.I've always found this part of the code confusing. I think they're just above my JS knowledge, but they're doing some kind of magic that I've never really understood. I could probably figure it out, but wouldn't it be nice to just do it the normal way?
I'm not sure how hard this will be to rip out, and I'm also not sure it all has to happen at once. Right now, I'm focused on getting recap.js to be only a background script, so I can fix the issue with
webRequest
's above. That may provide a little sample of how hard this is, and whether we want to do roll out the fix extension-wide.The text was updated successfully, but these errors were encountered: