I posted several questions concerning issues with the sidebar on Stackoverflow

I’d be most grateful if somebody could help with my questions on Stackoverflow.

Here are the links to each question on Stackoverflow:

It sounds like you didn’t even try the approach for your first question. Yes, you can swap the loaded extension page, and yes, you just define the one it will load by default in the manifest.

I thought setting the property ‘open_at_install’ to false would prevent the sidebar from opening at launch, but this isn’t working!

If the sidebar was open when the user closed the browser, it will be opened again when they launch the browser again.

You’d use browser.runtime.sendMessage to communicate with anything that isn’t a content script, as I think your example may be using browser.tabs.sendMessage but I don’t think it actually shows what it’s using.

Lastly, you can’t chose where the sidebar is opened as extension.

Thanks for your quick reply, Martin.

  1. I did try using a search_results.html panel (set as default in manifest) and another exif_tags.html panel, but I couldn’t get it to work.
    My code is on github under the two_panels branch here:
    https://github.com/odebroqueville/contextSearch/tree/two_panels
    if you’d care to have a look.
  2. I see!
  3. I tried that and couldn’t get it to work. The only solution I found was to first send a message from the sidebar script and then return a response from the background script. I think you were the one who suggested that solution somewhere!
  4. Shame, cause it shouldn’t be difficult to set given that there already is such an option in the dropdown menu.

What exactly didn’t work? Did it not set the panels you expected? Did you want to have both panels open at the same time?

In general messaging should work in both directions, but only if both sides are actually loaded/available.

It’s about user expectation. The user controls where their sidebar opens.

The sidebar is always blank, as if the script associated with the panel wasn’t being loaded.

This is what I have in the background script:

if (contextsearch_openSearchResultsInSidebar) {
            if (logToConsole) console.log(targetUrl);
            browser.sidebarAction.open()
                .then(()=>{
                    let url = browser.runtime.getURL('/sidebar/search_results.html');
                    browser.sidebarAction.setPanel({panel: url});
                    browser.sidebarAction.setTitle({title: "Search results"});
                })
                .catch((err)=>{
                    if (logToConsole) console.error(err);
                });
            return;
        }

the other panel gets set this way:

browser.sidebarAction.open()
                .then(()=>{
                    let url = browser.runtime.getURL('/sidebar/exif_tags.html');
                    browser.sidebarAction.setPanel({panel: url});
                    browser.sidebarAction.setTitle({title: "EXIF tags"});
                })
                .catch((err)=>{
                    if (logToConsole) console.error(err);
                });

The script associated with the first panel is as follows:

Window.onload = function(){
    if (logToConsole) console.log(`Requesting search results..`);
    requestSearchResults();
}
function requestSearchResults(){
    browser.runtime.sendMessage({action: "returnSearchResults"})
        .then(handleResponse)
        .catch((err)=>{
            if (logToConsole) {
                console.error(err);
                console.log("Failed to retrieve image EXIF tags.");
            }
        });
}
function handleResponse(response) {
    let content = document.getElementById("content");
    content.appenChild(response);
}

I’m not sure why you only set the panel after the sidebar is opened, you should be able to set the panel whenever. I assume you’re not seeing any page being loaded in the sidebar if you use the appropriate dev tools?

Nothing appears in the debug console and the content remains “undefined” as if no message is being sent to the bg script!

I used to have the panel set before opening but it wouldn’t work!

I’ve made some progress! The exif_tags.html panel now works and displays exif tags. However, the search_results.html panel fails. Its script which should handle a response from the background script says the response is undefined before the bg script has had a chance to send it back a response after having performed an XMLHTTPrequest! The reason I’m doing the XHR request is to set the header to a mobile user agent so that the search results look good in the sidebar.

This is the code in the background script that should send a response back:

case "returnSearchResults":
            if (logToConsole) console.log(`Target url: ${targetUrl}\n`);
            if (targetUrl != "") {
                fetchMobileWebPage(targetUrl)
                    .then((response)=>{
                        if (logToConsole) console.log(`Response:\n\n${response}`);
                        let content = getBody(response);
                        if (logToConsole) console.log(`Response:\n\n${content}`);
                        sendResponse({content: content});
                    })
                    .catch((err)=>{
                        if (logToConsole) console.error(err);
                    });
            }
            break;

And this is the code in search_results.js that should handle the response returned from the bg script:

const logToConsole = true;
(function(){
    if (logToConsole) console.log(`Requesting search results..`);
    requestSearchResults();
}())
function requestSearchResults(){
    browser.runtime.sendMessage({action: "returnSearchResults"})
        .then(handleResponse)
        .catch((err)=>{
            if (logToConsole) {
                console.error(err);
                console.log("Failed to retrieve search results.");
            }
        });
}
function handleResponse(response) {
    let content = response.content;
    if (logToConsole) console.log(content);
    if (content === undefined || content === null || content === "") return; 
    let results = document.getElementById("results");
    results.innerHTML =  content;
}

Is it again because I’m calling a promise before sending back a response. If so, how could I solve this problem? Any ideas?

How are your responding to the request from your background script? Are you returning a promise? Do you have multiple onMessage listener that may try to reply to messages?

There’s only 1 messaage listener in the bg script:

browser.runtime.onMessage.addListener((message, sender, sendResponse) => {…}

I’m not returning a promise, but I am returning the result of a promise.

Does it return true then, as documented at https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage

return true from the event listener. This keeps the sendResponse function valid after the listener returns, so you can call it later. See an example.

You nailed it, Martin! Spot on!

Thank you so much.