In porting my extension to support the side panel I ran into a number of issues, I'm hoping someone can help with my final blocker.
The extension is a bookmarker/tabs-manager. The first click on its toolbar icon opens the 'Manager' window (currently in an independent panel window) subsequent clicks open the 'Bookmarker' component in the extensions popup.
My main problems have been navigating the intersection of:
- The side panel needing a 'user gesture' to open
- There being no way to query if the side panel is open or get an event when it closes
- My service worker being subject to going inactive at any point.
The side panel opens fine from a runtime.action.onClicked callback. From the sidepanel.js I open a port that my service worker listens on. When the port connects, indicating the 'Manager' panel is open, my worker sets the runtime.action to open popup.html (ie the Bookmarker). When it disconnects it sets the action back to re-open the Manager side panel, not to open the popup.
The above generally seemed to work except for the corner case when my worker suspended and the user subsequently closed the sidepanel. I couldn't get anything to happen on an onunload event or find any way to wake the worker from within the closing sidepanel.js or any event that would awaken the worker. This results in the user click opening the Bookmarker without any context, basically disabling the extension with no way to fix it.
The work around I found is to add code to the worker so that on startup it will do a runtime.sendMessage which the sidepanel.js will respond to, if its open. If its not open an error is thrown ('no receiving end') which I can catch and then reconfigure the extensions action button appropriately.
The final problem here is that if the worker is still suspended when the user clicks the action button, the action has been set to open the Bookmarker popup. The worker is restarted at the same time, so if the user closes the popup and tries again the side panel will open correctly with the next click. But thats pretty ugly!
In my attempt to close this last hole, I added code to my popup.js as below, to ask for permission to open the sidepanel. Unfortunately I'm finding that even with this explicit request I'm getting a permissions error: "Error: `sidePanel.open()` may only be called in response to a user gesture."
Am I missing something here that makes the side panel fully usable in when seems like a pretty common use case?
Thanks for any ideas!
PS From a usability perspective I have a couple of other sidepanel issues
- code running in the sidepanel often doesn't receive mouseout events so UI components continue to show their hovered state. Particularly on the side with the re-sizer it seems to grab 8 pixels or so.
- I can't control when the side panel gets focus. There's no way to give it focus like I can when running in a tab or panel window. So my keyboard commands don't work unless the user knows to click back in.
---
Popup.js excerpt
if (val['BTManagerHome' ] === 'SIDEPANEL') {
let sidePanelOpen = false;
try {
const rsp = await chrome.runtime.sendMessage({'function': 'reconnect'});
if (typeof rsp === 'object') sidePanelOpen = true;
console.log('sidepanel open');
}
catch (e) {
console.log('sidepanel not open');
}
if (!sidePanelOpen) {
if (confirm('BrainTool is not currently open. Click OK to open it now.')) {
chrome.sidePanel.open({});
} else {
window.close();
return;
}
}