I am trying to make a chrome extension that alerts you in the tab that you are currently moving or highlighting. I have tried reading the chrome migrating to V.3 documentation and have come up with the following code, however, the alerts never appear. Does anybody know what I need to change or add?
// manifest.json
{
"manifest_version": 3,
"name": "Alert",
"version": "0.1",
"description": "alerts you when doing tab functions",
"permissions": ["tabs", "activeTab"],
"host_permissions": ["<all_urls>"],
"background": {
"service_worker": "background.js"
}
}
//background.js
chrome.tabs.onMoved.addListener(function () {
alert("You moved this tab");
});
chrome.tabs.onHighlighted.addListener(function () {
alert("You highlighted this tab");
});
Working directory:
.
├── background.js
├── manifest.json
alert() method cannot be used outside of the browser environment, you can use console.warn() or console.error() instead. But is not a good solution if you want to show an error message to the extension user, as they would never open the console.
If you would like a more user friendly approach use the following:
chrome.notifications.create({
type: 'basic',
iconUrl: '/images/image_if_any.png',
title: `Notification title`,
message: "Your message",
priority: 1
});
Also add "notifications" to "permissions" in your manifest.json file:
"permissions": [..., "notifications"]
alert is not defined in a service worker per specification so we'll have to use console.log
Also, I was looking in the wrong place for the alert messages. I needed to look at the service worker link in my unpacked extension page.
Related
I'm developing a chrome extension with MV3.
I've encountered an issue in which when I open the popup when clicking on the extension's icon the service worker background script stops receiving the chrome.tabs.onUpdated events, even after I close the popup. The only way I can make it work again is by reloading the extension.
I will mention that the popup that I'm rendering is a react app, not sure if it has to do with the issue, but when I swap the popup content to a normal HTML with just a button or something it is working as expected
Basically what I'm trying to do in the extension is listen to chrome.tabs.onUpdated event to detect URL changes in the background script, and send a message to a content script in order to save some data to the chrome local storage.
This is the manifest.json -
{
"name": "My Extension",
"description": "Extension POC",
"version": "0.0.0.1",
"manifest_version": 3,
"background": {
"service_worker": "background.js"
},
"permissions": ["tabs", "storage", "activeTab"],
"action": {
"default_popup": "build\\index.html",
"default_title": "Open Pane",
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["content.js"]
}
]
}
And this is the background.js -
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (!isPageDoneLoading(changeInfo)) {
return;
}
const url = tab.url;
const ticketId = url.substring(url.lastIndexOf("/") + 1);
if (isTargetURL(url) && !isNaN(ticketId)) {
// Update the ID only if it doesn't equal to the previous one or if null
if (!CURRENT_TICKET_ID || CURRENT_TICKET_ID !== ticketId) {
CURRENT_TICKET_ID = ticketId;
const props = getProperties(ticketId);
chrome.tabs.sendMessage(tabId, { action: {ticketId, props: props} });
}
}
})
Any idea what may be the root cause or how can I resolve the issue?
What React version are you using? In the older React version, part of the create-react-app script creates a file called serviceWorker.js. and a call to it in index.js. When I created a new project with a newer React version, 18.X.X it didn't create this file. I suppose there is some conflict with the service worker of the chrome extension and the one react app created.
I'm trying to get the userInfo object from chrome.identity.getProfileUserInfo in my popup.js (which is a script used for popup.html) but I am getting the following error:
Uncaught TypeError: Cannot read property 'getProfileUserInfo' of undefined at onload
popup.js
onload = function(){
chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) {
var url = tabs[0].url;
console.log(url);
});
chrome.identity.getProfileUserInfo(function(userInfo)
{
console.log(userInfo)
});
}
manifest.json
{
"manifest_version": 2,
"name": "QuickLink",
"description": "This extension allows you to quickly shorten and/or customize your url",
"version": "1.0",
"browser_action":
{
"default_icon": "icon.png",
"default_popup": "popup.html",
"default_title": "QuickLink"
},
"permissions":
[
"background",
"activeTab",
"clipboardWrite",
"tabs",
"notifications",
"identity",
"runtime"
]
}
I believe I have all the right permissions, and my tabs query works just fine, but for some reason, I don't have access to chrome.identity...any ideas why this might be or any work arounds so I can get the userInfo?
Would appreciate any help, thanks!
As answered in this thread you can only access it with a background script, not a content script.
It may require providing a "key" value in your manifest as well (if you're trying to get it working locally and it's not working). You can either use the same key as the one you get when you upload your extension to the webstore or try packing an extension to generate a new one (though I couldn't get this second approach working myself).
I know about both common problems that people are having:
If you change the command keys in the manifest file you need to
remove and reinstall it for the changes to take effect.
Even if you do this, you may also need to scroll down on the
extensions page, click the keyboard shortcuts link, and set the
commands manually.
About six months ago, I successfully implemented global keyboard commands with a Chrome Extension on the Chrome OS platform, it seems as though one of their updates has broken this feature... perhaps someone knows of a workaround? With the code below, if you load as an unpacked extension, then scroll down the chrome://extensions page to manually click the "Keyboard Shortcuts" and assign the command, you will see that you have the option to set it to run in either Chrome or Global... Chrome works, but if you assign Global, nothing happens (both inside Chrome and outside when using the file system or apps)... any ideas?
background.js
chrome.commands.onCommand.addListener(function(command) {
if (command == "toggleHighContrast") {
chrome.accessibilityFeatures.highContrast.get({},function (callback){
var value = true;
if (callback.value) value = false;
chrome.accessibilityFeatures.highContrast.set({value:value});
});
}//Ctrl+Shift+A
});
manifest.json
{
"manifest_version": 2,
"name": "High Contrast",
"short_name": "contrast",
"description": "",
"version": "0.0.1",
"minimum_chrome_version": "38",
"offline_enabled": true,
"commands": {
"toggleHighContrast": {
"global":true,
"description": "Toggle High Contrast Mode"
}
},
"background": {
"scripts": ["background.js"],
"persistent": true
},
"permissions": [
"accessibilityFeatures.read",
"accessibilityFeatures.modify"
]
}
I'm trying to build my first Chrome extension but I found problems with debugging.
I'm able to console.log() but in the Developer Tools console (I'm working on the background.js; no UI) there's no report about syntax errors.
Is that normal? Or it depends on some settings of the page I'm creating the extension for? (www.google.com)
I've read maybe there could be a window.onerror set somewhere but I'm not able to find it. I tried a
window.onerror = null;
at the beginning of the background.js but nothing has changed.
What would you do to get the errors back?
UPDATE (Adding code)
This is the manifest.json:
{
"name": "Name",
"description": "Description",
"version": "0.1",
"manifest_version": 2,
"background": {
"persistent": false,
"scripts": ["js/background.js"]
},
"permissions" : [
"tabs",
"*://www.google.com/*",
"*://www.google.de/*"
],
"commands": {
"changeSearch": {
"suggested_key": {
"default": "Ctrl+Shift+A",
"mac": "Command+Shift+A"
},
"description": "Change."
}
}
}
The background.js start like this:
console.log("Start");
chrome.commands.onCommand.addListener(function(command) {
consTYPOTYPOTYPOTYPOTYPOTYPOle.log("catched");
...
I just discovered that errors are thrown if the TYPO is otuside of function(command) code, if I have TYPOs on the 1st or 2nd line.
The 3rd line is totally silent. No error. It just doesn't work.
That's weird to me!
The problem was a conflicting extension that was overriding mine.
Trying to disable all extensions and then re-enabling them, starting from mine, solved the problem.
Probably I made it to have higher priority respect to the conflicting extension (that has been enabled after).
I hope you can help me.
I am trying to create an extension in Chrome which would load a source of the active tab into a variable.
So far I have:
manifest.json
{
"name": "My Extension",
"manifest_version": 2,
"version": "0.1",
"description": "Does some simple stuff",
"browser_action": {
"default_icon": "logo.png"
},
"background": {
"scripts": ["main.js"]}}
main.js
chrome.browserAction.onClicked.addListener(
function(tab) {
var ps1 = document.getElementsByTagName('html')[0].innerHTML;
window.alert(ps1);
});
but that loads the page source of the blank page. What do I need to do to get the source of the active page.
I have done some reading and I think I need to use content script whit some listening functions, I have been searching but all answers seem to me very complicated. Would any of you be so kind to give me some easy example?
Highly appreciate your feedback!
Regards
UPDATE after AdrianCooney answer:
I changed my manifest to contain
"permissions": [
"tabs"
]
Then in main.js I did
chrome.browserAction.onClicked.addListener(function(activeTab) {
chrome.tabs.query({ currentWindow: true, active: true },
function (tabs) {
var ps1=document.getElementsByTagName('html')[0].innerHTML;
window.alert(ps1);
})
});
When I press the Extension button I get something like that
<html></html>
<body><script src="main.js"></script>
</body>
...no matter what tab I have active.
Another try with chrome.tabs.getCurrent
chrome.browserAction.onClicked.addListener(function(activeTab) {
chrome.tabs.getCurrent(
function (tabs) {
var ps1=document.getElementsByTagName('html')[0].innerHTML;
window.alert(ps1);
})
});
The above version of main.js give exact same output as the one before, no matter what page I have active.
Background scripts are isolated from the current page because they're designed to be persistant regardless of the content of the page. You need to use the chrome.tabs API, specifically chrome.tabs.getCurrent. Once you have the current tab, you can inject code into the window. That's where your snippet above comes in.
You will need to add "tab" to your permissions in the manifest file.
As was pointed out, you need to run code in the context of the active tab. One way to do it is using chrome.tabs.executeScript:
chrome.browserAction.onClicked.addListener( function() {
chrome.tabs.executeScript(
{
code: "document.getElementsByTagName('html')[0].innerHTML;"
},
function (ps1) {
window.alert(ps1);
}
);
});
This code under main.js works!!! Thank you guys for your hints they saved me a lot of time!
chrome.browserAction.onClicked.addListener(
function(tab) {
chrome.tabs.executeScript(
null,{
code:"var ps1 = document.getElementsByTagName('html')[0].innerHTML;
window.alert(ps1);"});
}
);
In Chrome 47 you need to add "activeTab" to permissions, otherwise it doesn't work. With "tabs" it doesn't work.
manifest.json:
{
"name": "Rafi extension",
"manifest_version": 2,
"version": "7",
"description": "Open something",
"browser_action": {
"default_icon": "logo.png"
},
"permissions": [
"activeTab"
],
"background": {
"scripts": ["main.js"]}
}
For anyone looking to do this with Manifest V3, things are much simpler. Let's say you have a script parse_page.js in the root of your extension, that contains whatever code you want to execute:
var ps1 = document.getElementsByTagName('html')[0].innerHTML;
window.alert(ps1);
From the docs, there are two ways to have it execute:
(1) Inject with static declarations: use this method for scripts that that need to run automatically. Simply add the following to your manifest.json:
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["parse_page.js"]
}
],
The script will run whenever you visit a new page. You can adjust the matches above if you only want it to execute on certain URLs.
(2) Inject programmatically: use this method for scripts that need to run in response to events or on specific occasions. Add the following to your manifest.json:
"permissions": ["activeTab", "scripting"],
"background": {
"service_worker": "background.js"
},
"action": { }
Next, in background.js, add the following:
chrome.action.onClicked.addListener((tab) => {
chrome.scripting.executeScript({
target: { tabId: tab.id },
files: ['parse_page.js']
});
});
In this example, the script will run whenever you click on your extension's icon.