Closed Bug 686035 Opened 13 years ago Closed 10 years ago

It is awkward to get the active tab's worker

Categories

(Add-on SDK Graveyard :: General, enhancement, P2)

enhancement

Tracking

(Not tracked)

RESOLVED WONTFIX

People

(Reporter: canuckistani, Unassigned)

References

Details

(Whiteboard: [good first bug])

If you attach workers to tabs using page-mod, it is difficult ( but not impossible! ) to then get access to a give tab's worker and arbitrarily call worker.port.emit('some-event', function(payload) { /*...*/ }); A working implementation of this uses an array of workers and loops through them until it a successful comparison of tab objects is made: https://builder.addons.mozilla.org/addon/1016315/revision/10/ Warner suggested possibly using WeakMaps to track workers by their tab instance but this does not currently work: https://builder.addons.mozilla.org/addon/1016282/revision/71/ One possibility might be to add something to the tab object that reliably returns an associated worker ( if there is one ): let worker = tabs.activeTab.getWorker(); if (worker) { worker.port.emit("someEvent"); }
What if a tab has multiple workers? Would it return a collection of all workers for the tab?
Good question, now that I think about it there no stopping multiple page-mods per tab in the same extension. Yeesh. What I'm trying to solve is some simpler way of pushing events into a content script from the main add-on code, the communication currently is most convenient when it is from content script -> add-on code..
[probablynothelpfulanswer]: In one of my addons, I have the pagemod emit something back to the addon first, which then lets me send stuff back into that contentscript with that specific worker. This only works if it's something that you know the contentScript is going to want/need, of course.
Severity: normal → enhancement
OS: Mac OS X → All
Priority: -- → P2
Hardware: x86 → All
Unique id's on the Tab object would make this /much/ easier: just maintain a map of tab.id -> worker, or to list of worker, depending on what workers you want. It would also be fantastic to be able to lookup tabs based on an id for hashing vs. direct equality for maintaining per-tab state anyway.
Whiteboard: [good first bug]
Finding that the tab matches isn't good enough to find the correct worker. Issuing page navigation messes up the comparison, it is still the same tab, but both the history page's worker and current page's worker have the same tab. Historic workers are needed for fastback. I tried solving this by comparing worker.url however both the worker in tab history fastback and the worker at the current URL report the same URL (as if they simply report worker.tab.url even though that's not the url the worker was injected into). Comparing tab objects or even comparing if the tab object url matches the workers url is not sufficient to determine which worker is correct. The only way I can think of that would work is to worker.port.emit something and catch the Frozen error to see if it's the frozen worker or the active one. This solution I did not consider to be fast enough. I had to implement a way to detect if the tab was frozen by exposing it via a public assessor. Unfortunately this lead to my addon being rejected, now I feel it a race to find a work-around within the SDK but I don't see a great way (a try catch block inside a loop and emitting extraneous requests). frozen worker detection: addon-sdk-1.14/lib/sdk/content/worker.js https://github.com/qufighter/ColorPick/commit/56aa34134e62d5dc4cb2ecd76b5623024940cd19 I may post an issue about the worker reporting a URL other than the one it was injected at, however if one were to navigate 3 times returning to the same page, the URL test would be once-more useless in determining which worker was not frozen. Here is my detection function findWorkerForCurrentTab which uses the changes to the SDK above, along with the familiar detach function var workers = []; var curWorker = false; function detachWorker(worker) { var index = workers.indexOf(worker); if(index != -1) { workers.splice(index, 1); } } function findWorkerForCurrentTab(){ if(curWorker.unfrozen && curWorker.tab == tabs.activeTab ) return curWorker; for(var i=0,l=workers.length;i<l;i++){ if(workers[i].unfrozen && workers[i].tab == tabs.activeTab){ curWorker=workers[i]; return curWorker; } } return false; } //active tabs that are frozen are in the tab history and are not the current worker, //otherwise if the active tab matches the worker's tab then it is the correct worker I don't know about the "unfrozen" naming convention but I can vouch for this approach working In case anyone is interested this is my work-around code, it is pretty ugly. Let me know if there is a better way! Let me know if the unfrozen approach is something that would be accepted and I'll make a branch of the sdk with the changes, or otherwise go ahead and take em. I am under the impression this approach is pretty slow, especially when there are many tabs or a lot of fastback states. function findWorkerForCurrentTab(){ if(curWorker.tab == tabs.activeTab ){ try{ curWorker.port.emit('are-you-frozen'); return curWorker; }catch(e){} } for(var i=0,l=workers.length;i<l;i++){ if(workers[i].tab == tabs.activeTab){ try{ workers[i].port.emit('are-you-frozen'); }catch(e){ continue; } curWorker=workers[i]; return curWorker; } } return false; }
A solution to the above issue, seems to be to listen to the worker's pageshow and pagehide events and add and remove them from the workers array accordingly: http://stackoverflow.com/questions/15502043/addon-sdk-context-menu-and-page-mod-workers
a 3rd party module can handle this use case, so I think we'd better publish the work there.
Status: NEW → RESOLVED
Closed: 10 years ago
Resolution: --- → WONTFIX
You need to log in before you can comment on or make changes to this bug.