I've been tasked with creating a Google Chrome extension. So far, everything works fine. However, I would like to be able to use multiple background scripts (what I mean is
"background" : {"scripts" : ["background.js"]}, if what I'm talking about is unclear) rather than creating multiple extensions. Is this possible?
Regards,
According to the documentation:
A background page will be generated by the extension system that includes each of the files listed in the scripts property.
So yes, it should work. Simply declare multiple scripts:
...
"background": {
"scripts": [
"background.js",
"backgroundone.js",
"backgroundtwo.js"
]
},
...
All of these scripts would work as if loaded into the same page; they will all share the same context.
In manifest version3:
---------manifest.json
"background": {
"service_worker": "bg-wrapper.js"
}
---------bg-wrapper.js
try {
importScripts('background.js');
} catch (error) {
console.error(error);
}
Related
This question already has an answer here:
How do I import scripts into a service worker using Chrome extension manifest version 3?
(1 answer)
Closed 1 year ago.
In Google Chrome extensions before manifest v3 I could divide background.js into multiple scripts. And to load all scripts to be visible in background.js I only need to to put them in array in manifest like this:
"background": {
"scripts": ["helpers/countHelper.js", "helpers/networkHelper.js", "background/main.js"],
}
With this above sintax, all scripts will be merged into one file.
Now in documentation how to use manifest v3, they wrote:
Replace background.page or background.scripts with
background.service_worker in manifest.json. Note that the
service_worker field takes a string, not an array of string.
Cause background in manifest can't take multiple scripts, how to divide background script into multiple scripts.
Also import syntax is not allowed as I know.
With this above sintax, all scripts will be merged into one file.
It is not true, but let's fly over...
You can use importScript but not in manifest.
Look at this template:
/* V3 manifest.json */
"background": {
"service_worker": "worker_wrapper.js"
},
/* worker_wrapper.js */
try {
importScripts("helpers/countHelper.js", "helpers/networkHelper.js", "background/main.js");
} catch (e) {
console.log(e);
}
Bear in mind that SW file must be placed in root folder, whereas other scripts could be placed in other folders
I'm writing a Chrome extension that will redirect me to a URL when clicking on the browser action icon.
I'm trying to use:
chrome.browserAction.onClicked.addListener
but I get
Uncaught TypeError: Cannot read property 'onClicked' of undefined
This is my manifest file:
{
"name": "first extension",
"version": "2.2.12",
"description": "redirct to a link icon",
"browser_action": {
"default_icon": "icontest.png",
"default_title": "Do action"
},
"permissions": ["tabs", "http://*/*"],
"content_scripts": [{
"matches": ["http://*.twitter.com/*", "https://*.twitter.com/*"],
"js": ["twterland.js"]
}],
"icons": {
"16": "icontest.png",
"48": "icontest.png",
"128": "icontest.png"
}
}
This is my js file:
chrome.browserAction.onClicked.addListener(function(tab) { alert("hi"); });
ManifestV3
manifest.json: use action not browser_action, see also the migration guide.
"action": {},
"background": {"service_worker": "background.js"},
background.js: use chrome.action not chrome.browserAction.
Classic ManifestV2
For those who already have added something like
"background": {
"scripts": ["background.js"]
}
and still gets Cannot read property 'onClicked' of undefined - just add
"browser_action": {}
into your manifest.json
It seems like the code is in your twterland.js file, which is your content script. browserAction can only be used in extension pages, so you can not use it in content scripts.
Document: https://developer.chrome.com/extensions/content_scripts
However, content scripts have some limitations. They cannot:
- Use chrome.* APIs (except for parts of chrome.extension)
- Use variables or functions defined by their extension's pages
- Use variables or functions defined by web pages or by other content scripts
Put it on the background page instead.
If you do not have a "browser_action" property defined in your manifest.json then this error may occur. #Kirill's answer works but you also have to add a blank icon.png file else chrome will throw an error that it cannot find such a file.
Adding this to the manifest.json file should suppress this is error:
"browser_action": {}
Be sure to read the documentation for further reference on how to use the "browser_action" setting.
The same problem may appear if you are using manifest_version 3.
In this case
"background.scripts" should be replaced with "background.service_worker"
"browser_action" should be replaced with "action"
in js code chrome.browserAction should be replaced with chrome.action
detailed information could be found here: Manifest version 3 migration documentation
I was also getting this, adding
"persistent": true
to my background declaration in manifest.json solved it.
Please notice that you can heave only one of app, browser_action, page_actions present in your manifest.json file.
For example, to use the chrome.browserAction.setBadgeText you should have the browser_action field in your manifest.json.
Make sure we don't have jquery.js before background.js in the scripts array of background in manifest.json.
"background": {
"scripts": ["background.js","jquery.js"]
}
I'm writing a Chrome Extension in Javascript and I want to get the current time for the playing video on youtube.com. I tried using the answer from question Getting Current YouTube Video Time , e.g.:
ytplayer = document.getElementById("movie_player");
ytplayer.getCurrentTime();
However I do get following error: "Uncaught TypeError: Cannot read property 'getCurrentTime' of null";
What I am doing wrong? I tried different values for the ElementId - movie_player, player....
Any help is appreciated. Thanks in advance.
Cheers.
edit:
Here is my manifest:
{
"manifest_version": 2,
"name": "",
"description": "",
"version": "1.0",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "basic.html"
},
"permissions": [
"tabs",
"activeTab", "http://*/*", "https://*/*"
]
}
Another thing is:
If I execute this code:
ytplayer = document.getElementById("movie_player");
ytplayer.getCurrentTime();
In the Javascript console on a Youtube Page it works fine and returns the current time.
If, however I execute this value from the extension or the console of the extension, the first line return value null.
So, as Ben assumed below, the issue seems to be that my extension doesn't even access the Youtube page.
Any help is appreciated, so thanks in advance.
Cheers
Use the following code works for chrome extension:
video = document.getElementsByClassName('video-stream')[0];
console.log(video);
console.log(video.currentTime);
In 2020, it seems we should use: player.playerInfo.currentTime.
full code on codepen
As Ben correctly assumed, you're executing the code in the context of your background page, which is wrong.
To interact with other pages, you need to inject a content script in them. See overview of that here. You'll probably need to learn how Messaging works so you can gather data in a content script and communicate it to the background page.
To make a minimal example, you can have a file inject.js
// WARNING: This example is out of date
// For the current HTML5 player, see other answers' code snippets
ytplayer = document.getElementById("movie_player");
ytplayer.getCurrentTime();
And in your background page script, you can inject that into the current page as follows (when the button is clicked, for instance)
chrome.browserAction.onClicked.addListener(function(tab) {
chrome.tabs.executeScript({
file: 'inject.js'
});
});
Then, you'll see the result of the execution in the console of the currently open page. To report the result back, you'll need to use chrome.runtime.sendMessage
you can only use getElementById when you´r referencing to the correct page. You´r using the right id. if you´r trying to access the play form another page you can use the jquery .load() function
---------EDIT----------
in the sample they do it like so:
function getCurrentTime() {
var currentTime = player.getCurrentTime();
return roundNumber(currentTime, 3);
}
I am trying to write a Chrome extension which detects process crashes.
First i went to about:flags page of Chrome and enabled "Experimental Extension APIs".
This is the extension I wrote:
manifest.json:
{
"manifest_version": 2,
"name": "CrashDetect",
"description": "Detects crashes in processes.",
"version": "1.0",
"permissions": [
"experimental","tabs"
],
"background": {
"scripts": ["background.js"]
}
}
backround.js:
chrome.experimental.processes.onExited.addListener(function(integer processId, integer exitType, integerexitCode) {
chrome.tabs.getCurrent(function(Tab tab) {
chrome.tabs.update(tab.id, {url:"http:\\127.0.0.1\""});
};)
});
Then I visited about://crash page of Chrome. But onExited listener does not execute.
Have I done anything wrong in manifest.json or background.js?
There a couple errors in your code. First you have the types of the parameters in the function declaration, change it to:
function(processId, exitType, integerexitCode){
Second, you put };) instead of });. Try inspecting the background page to see syntax errors.
Alright, after playing around with it some as I was unfamiliar with this particular API, I found that none of the events fired if I didn't include a handler for onUpdated. I really doubt that this is the intended behavior and I will check to see if there is a bug report on it. For now just do something like this to get it working:
chrome.experimental.processes.onUpdated.addListener(function(process){});
chrome.experimental.processes.onExited.addListener(function(processId, exitType, integerexitCode){
chrome.tabs.query({active:true, currentWindow:true},function(tabs){
chrome.tabs.update(tabs[0].id, {url:"http:\\127.0.0.1"});
});
});
Notice that I did swap out your getCurrent for a chrome.tabs.query as the former would have given you an error. This does lead to the behavior of if you close a tab, the next tab will be redirected. Perhaps you could try to filter by exitType and not include normal exits.
Well I have a list of domains (about 10) which my chrome extension is going to interact with.
As I studied the chrome extensions documentation this needs to use content_scripts
I have included these lines in the manifest.json
"content_scripts": [ {
"all_frames": true,
"js": [ "js/main.js" ],
"matches": [ "http://domain1.com/*",
"http://domain2.com/*",
"http://domain3.com/*",
"http://domain4.com/*",
"http://domain5.com/*",
"http://domain6.com/*",
"http://domain7.com/*",
"http://domain8.com/*",
"http://domain9.com/*",
"http://domain10.com/*"
],
"run_at": "document_start"
}],
This means that during loading every page that the url matches the defined url's in the manifest file, then the main.js will be injected to the page. Am I right? yes.
So I want to do some UI when the script is injected through page action
I included these lines to the manifest:
"page_action": {
"default_icon": "images/pa.png",
"default_title": "This in one of that 10 domains, that is why I showed up!"
},
It seems that it is not enough. and I have to manually trigger the page action.
but where ?
I realized that for this purpose I would need a background.html file.
but Why I can not include the trigger at the same main.js file?
answer:
However, content scripts have some limitations. They **cannot**:
- Use chrome.* APIs (except for parts of chrome.extension)
- Use variables or functions defined by their extension's pages
- Use variables or functions defined by web pages or by other content scripts
So included it in the manifest:
"background_page": "background.html"
and this is the content:
<html>
<head>
<script>
function check (tab_id , data , tab){
//test just one domain to be simple
if (tab.url.indexOf('domain1.com') > -1){
chrome.pageAction.show(tab_id);
};
};
chrome.tabs.onUpdated.addListener(check);
</script>
</head>
</html>
Fair enough until here,
What I want and I don't know is how to add the ability of toggle on/off the extension.
User clicks on the page action icon -> the icon changes and turns off/on (the main.js would act different)
Instead of adding the content script through the manifest, you can also use the chrome.tabs.onUpdated in conjunction with chrome.tabs.executeScript:
// Example:
var url_pattern = /^http:\/\/(domain1|domain2|domain3|etc)\//i;
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (url_pattern.test(tab.url)) {
if (changeInfo.status === 'complete') { // Or 'loading'
chrome.tabs.executeScript(tabId, {'file':'main.js'});
chrome.pageAction.show(tabId);
}
} else {
chrome.pageAction.hide(tabId);
}
});
Do not forget to check for the value changeInfo.status, because otherwise, the content script will be executed twice.
In one of these if-statements, you can incorporate a check whether the extension is active or not, and act upon it:
if (changeInfo.status === 'complete' && am_I_active_questionmark) ...
Side not: Instead of using background_page, you can also use "background": {"scripts":["bg.js"]}, and place the background script in bg.js.