open extension popup when click on context menu

2023-11-28
#browser-extension #javascript

Recently, I've been working on a browser extension and hoping to implement a feature where a popup can be displayed when the user clicks the context menu. After researching this, i'm do conscious of this feature can't be implemented programmatically from inside the handler for a user action. Although there's an API called browser.browserAction.openPopup, currently, it's only available in the Firefox browser and the Chrome dev channel.
To make it work on all browser platforms, I'm considering dynamically injecting HTML and JavaScript into the page.

Inject html and javascript

Of course, we can inject HTML using an HTML string directly, but if our feature is complicated, it's better to split it into multiple files. For example, one for HTML (popup.html) and another for JavaScript (popup.js). Once you do this, you should add these files to the manifest.json.

    "web_accessible_resources": [
      {
        "resources": ["inject/popup.html","inject/popup.js"],
        "matches": ["<all_urls>"]
      }
    ]

after that, we can inject all the content into page in content.js

  fetch(chrome.runtime.getURL('inject/popup.html'))
    .then(response => response.text())
    .then(html => {
      document.body.insertAdjacentHTML('beforeend', html);
    }).catch(err => {
      console.log(err)
    });
  
  
  var s = document.createElement('script');
  s.src = chrome.runtime.getURL('inject/popup.js');
  s.onload = function() {
    this.remove();
  };
  (document.head || document.documentElement).appendChild(s);

context menus

use chrome.contextMenus.create to create context menu in background.js

      chrome.contextMenus.create({
        id: "1", # id 
        title: "menu name", # menu name
        contexts: ["page"],  // ContextType
      });

context menus send messages to content.js

we won't be able to operate element in background.js directly, so we should send message to content.js and let it handle the work.

  // backgroud.js
    chrome.contextMenus.onClicked.addListener(function (_) {
      chrome.tabs.query({
        "active": true,
        "currentWindow": true
    }, function (tabs) {
        chrome.tabs.sendMessage(tabs[0].id, {
            "action": "popup"
        });
    });
    })
  
  // content.js
  // listent to the message comes from backgrond.js
  chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    if (message.action === 'popup') {
     // do something
    }
  });

Reference

open extension popup when click on context menu