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
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 themanifest.json
.after that, we can inject all the content into page in
content.js
context menus
use chrome.contextMenus.create to create context menu in
background.js
context menus send messages to content.js
we won't be able to operate element in
background.js
directly, so we should send message tocontent.js
and let it handle the work.Reference
open extension popup when click on context menu