How do extensions like Lastpass and Traitsniper update the extension notification count when the extension is closed? Are there any extension processes that are running even when the extension is closed? I am currently updating this with events in background.js with manifest v3, which does not run when the extension is not open.
extensions notifications example
Manifest.json:
{
"short_name": "test",
"name": "test",
"version": "1.3",
"manifest_version": 3,
"action": {
"default_popup": "index.html",
"default_title": "Open the popup"
},
"permissions": ["contextMenus", "notifications", "storage", "tabs"],
"icons": {
"512": "logo512.png"
},
"background": {
"service_worker": "./static/js/background.js"
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["./static/js/content.js"]
}
],
"devtools_page": "index.html"
}
Snippet from background.js which currently is updating the notification count in the extension toolbar:
switch (unreadCount) {
case 0:
chrome.action.setBadgeBackgroundColor({
color: [110, 140, 180, 255],
})
chrome.action.setTitle({ title: 'No unread messages' })
chrome.action.setBadgeText({ text: '' })
break
case 1:
chrome.action.setBadgeBackgroundColor({
color: '#F00',
})
chrome.action.setTitle({
title: unreadCount + ' unread message',
})
chrome.action.setBadgeText({ text: unreadCount.toString() })
break
default:
chrome.action.setBadgeBackgroundColor({
color: '#F00',
})
chrome.action.setTitle({
title: unreadCount + ' unread messages',
})
chrome.action.setBadgeText({ text: unreadCount.toString() })
break
}
Just wanted to close this out - its actually an issue with Metamasks's extension provider to get access to window.ethereum. https://github.com/MetaMask/extension-provider/
Everything works fine with alarms and badge text updates, even with the extension closed, until I declare the Metamask provider:
let provider = createMetaMaskProvider()
Then, alarms only work when the app is open/visible. Its a bit wild to me why this is the case, I cannot see any errors when debugging.
Related
I am trying to create a Chrome extension that automatically generates a small pop up on the side when the user navigates to a particular site.
I went through the documentation on Chrome's developer page & followed the tutorial but I am not sure how to inject a script when the user visits a particular site. I want the popup to show up only on that particular site. In fact I don't see any console logs inside the addListener section of my background.json
manifest.json
{
"name": "Google helper",
"version": "1.0",
"manifest_version": 3,
"description": "Shows you additional information on google",
"icons": {
"128": "icon128.png"
},
"action": {
"default_icon": {
"128": "icon128.png"
},
"default_title": "Google helper",
"default_popup": "popup.html"
},
"background": {
"service_worker": "background.js"
},
"permissions": [
"tabs",
"activeTab",
"scripting"
// ,
// "https://google.com/"
]
}
background.js
// Register the service worker
console.log("Here in background.js before anything starts"); // Able to see this log in service worker view
// Called when the user clicks on the action.
chrome.action.onClicked.addListener(function(tab) {
// No tabs or host permissions needed!
console.log('Turning ' + tab.url + ' red!'); // Don't see this in logs
chrome.scripting.executeScript({
code: 'document.body.style.backgroundColor="red"'
});
});
I know the answer for manifest v2: Add contextmenu items to a Chrome extension's browser action button
It's been working fine until migrating manifest from v2 to v3.
My current manifest.json:
{
"manifest_version": 3,
"version": "0.1.1",
"background": {
"service_worker": "background.js"
},
"action": {
"default_popup": "popup.html"
},
"content_scripts": [
{
"all_frames": false,
"matches": ["http://*/*", "https://*/*"],
"js": ["content.js"]
}
],
"permissions": ["contextMenus"],
...
}
And now this doesn't add a context menu item to my extension's browser action button:
chrome.contextMenus.create({
id: 'foo',
title: 'first',
contexts: ['browser_action'],
onclick: function () {
alert('first')
}
})
I checked that 'selection' context properly adds a context menu to the selected text on a web page.
Is there something I have to do to migrate from v2 to v3?
Found a solution myself. The context should be 'action' instead of 'browser_action'. And it looks like onclick property has been deprecated.
So, it should be something like:
chrome.contextMenus.create({
id: 'foo',
title: 'first',
contexts: ['action']
})
function contextClick(info, tab) {
const { menuItemId } = info
if (menuItemId === 'foo') {
// do something
}
}
chrome.contextMenus.onClicked.addListener(contextClick)
I found this answer on how to grab the page source of current tab:
Getting the source HTML of the current page from chrome extension
However, this answer requires user to press the extension popup.
I would like to know how I can access the page source upon loading of page (without having to invoke the popup).
In my background.js I've tired this:
chrome.tabs.onUpdated.addListener(function (tabId , info) {
console.log(info)
chrome.tabs.executeScript(null, {
file: "getPagesSource.js"
}, function() {
if (chrome.runtime.lastError) {
message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
}
});
});
but this results in the following error:
There was an error injecting script : Cannot access contents of the
page. Extension manifest must request permission to access the
respective host.
My manifest.js:
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"permissions": ["declarativeContent",
"https://www.example.com/*",
"storage",
"activeTab"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": [
"<all_urls>"
],
"js": ["content.js"]
}
],
"options_page": "options.html",
"manifest_version": 2,
"page_action": {
"default_popup": "popup.html",
"default_icon": {
"16": "images/get_started16.png",
"32": "images/get_started32.png",
"48": "images/get_started48.png",
"128": "images/get_started128.png"
}
},
"icons": {
"16": "images/get_started16.png",
"32": "images/get_started32.png",
"48": "images/get_started48.png",
"128": "images/get_started128.png"
}
}
I don't think the issue is really with permissions because I am able to get the page source from the popup.html (which is page_action script). But I am not able to get it via "background" or "content_scripts". Why is that and what is the proper way to accomplish this?
It is about the permissions.
Your example a bit insufficient, but as I can see you are using "activeTab" permission.
According to the activeTab docs, the extension will get access (e.g. sources) to current tab after any of these actions will be performed:
Executing a browser action
Executing a page action
Executing a context menu item
Executing a keyboard shortcut from the commands API
Accepting a suggestion from the omnibox API
That's why you can get sources after opening the popup.
In order to get access to tabs without those actions, you need to ask for the following permissions:
tabs
<all_urls>
Be noted, it allows you to run content-script on every tab, not only the active one.
Here is the simplest example:
manifest.json
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"permissions": ["tabs", "<all_urls>"],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"manifest_version": 2
}
background.js
chrome.tabs.onUpdated.addListener(function (tabId, info) {
if(info.status === 'complete') {
chrome.tabs.executeScript({
code: "document.documentElement.innerHTML" // or 'file: "getPagesSource.js"'
}, function(result) {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
} else {
console.log(result)
}
});
}
});
I've been trying to develop a chrome extension that creates notifications after certain periods of time. I've been using both chrome.alarms and chrome.notifications to accomplish this, but I cannot get notifications to appear, even when creating them from the console. I also don't get any errors from runtime.lastError in the callback. I do know for certain that the alarm listener and callback are being executed.
manifest.json
{
"manifest_version": 2,
"name": "notifications",
"version": "0.0",
"browser_action": {
"default_popup": "popup.html"
},
"background": {
"scripts": ["notifications.js"],
"persistent": false
},
"permissions": [
"alarms",
"storage",
"notifications"
],
"web_accessible_resources": [
"mascot48.png"
]
}
notifications.js
function resetTimer(id, minutes) {
chrome.alarms.create(id,{delayInMinutes: minutes});
}
chrome.alarms.onAlarm.addListener((alarm) => {
console.log('alarm!');
chrome.notifications.create('reminder', {
type: 'basic',
iconUrl: 'mascot48.png',
title: 'Dont forget!',
message: 'You have things to do'
}, function(notificationId) {
console.log(chrome.runtime.lastError);
});
});
Is there anything clear that I'm getting wrong?
EDIT: For clarity, notifications.js is my events page, the popup page is the one that runs the code to start the alarms.
I'm using chrome messaging feature to send the filename and link to the background page
chrome.runtime.sendMessage({link: thelink, name:filename}, function(response) {});
The background.js
chrome.runtime.onMessage.addListener(function (message, sender, sendResponse) {
console.log(message.name);
chrome.downloads.download({
url: message.link,
filename: message.name,
conflictAction: 'prompt'
});
});
My manifest.json
{
"manifest_version": 2,
"name": "4ch",
"description": "This extension shows a Google Image search result for the current page",
"version": "1.0",
"icons": {
"16": "4ch-icon-16.png", "48": "4ch-icon-48.png", "128": "4ch-icon-48.png"
}
,
"permissions": ["downloads",
"<all_urls>",
"contextMenus"],
"content_scripts": [{
"js": ["script/jquery.js", "script/reddit.js"],
"matches": ["*://*.reddit.com/*"]
}
],
"background": {
"scripts": ["script/jquery.js","script/eventpage.js"], "persistent": false
}
}
the download only starts after a few seconds and doesn't change the file name
I have ofund a solution. The 'download master' extension was in conflict with my own,hence it doesn't replace the original filename.I have disabled it