I'm writing a simple Chrome extension that displays a JavaScript alert saying "Hello World". In this example I have specified that the extension will only run for google.com (by putting this in the permissions property within manifest.json).
Even after everything in the target page has loaded, the alert doesn't appear. Here is my script so far:
File: manifest.json
{
"name": "Hello",
"version": "1.0",
"description": "Says hello to Google",
"permissions": ["http://*.google.com/"]
"browser_action": {
"popup": "Hello.html"
}
}
File: Hello.html
<script language="Javascript">
alert("Hello World");
</script>
You are adding a browser action popup, which adds a button to the top-right of your browser. (It's probably invisible because you haven't specified an image for it. There should be some empty space to the right of your address bar; try clicking it to see your Hello.html in a popup.)
What you want is a content script. Content scripts can get injected into every page that Chrome loads. You can use the matches and exclude_matches sub-items in your manifest file to specify which pages get your injected script.
{
"name": "Hello",
"version": "1.0",
"description": "Says hello to Google",
"permissions": ["tabs", "*://*.google.com/*"],
"content_scripts": [
{
"matches": ["*://*.google.com/*"],
"js": ["hello.js"]
}
]
}
Make sure you rename Hello.html to hello.js (and get rid of the <script> tags).
Note also that I changed your http://*.google.com/ to *://*.google.com/* so that it will apply to Google over HTTP and HTTPS (and the trailing * ensures that it will apply to all pages on google.com, not just the main page).
I came across this answer trying to find a way to only enable the icon on certain pages this is how I did it. Docs
background.js
chrome.runtime.onInstalled.addListener(function() {
chrome.tabs.onActivated.addListener(async info => {
const tab = await chrome.tabs.get(info.tabId);
const isGithub = tab.url.startsWith('https://github.com/');
isGithub
? chrome.action.enable(tab.tabId)
: chrome.action.disable(tab.tabId);
});
});
make sure to add tabs permission in manifest
First of all there are 2 types of extensions:
1. Browser Action - which work for multiple websites or almost all websites
2. Page Action - which work for specific websites or webpages [which is needed
in our case]
Follow these steps to show your extension only on google:
Step 1: Go to manifest.json file and add the below code snippet
"background":{
"scripts":["background.js"],
"persistent":false
}
***also make sure you have page action not browser action**
"page_action" : { "default_popup":"your_popup.html" }
Step 2: Now add permissions in manifest:
"permissions":["declarativeContent"]
Step 3: Now create background.js in root folder of extension and add the
below code in it, this will let the extension to work only on
urls that contain google.com
// When the extension is installed or upgraded ...
chrome.runtime.onInstalled.addListener(function() {
// Replace all rules ...
chrome.declarativeContent.onPageChanged.removeRules(undefined,
function() {
// With a new rule ...
chrome.declarativeContent.onPageChanged.addRules([
{
// That fires when a page's URL contains a 'g' ...
conditions: [
new chrome.declarativeContent.PageStateMatcher({
pageUrl: { urlContains: 'google.com' },
})
],
// And shows the extension's page action.
actions: [ new chrome.declarativeContent.ShowPageAction() ]
}
]);
});
});
Step 4: Now reload your extension, you'll find that your extension will work
only for google.com
Hope this solved your query, If Yes, then Upvote the answer Thanks!
Related
I am new to chrome extensions, so I maybe using the wrong terms.
I have created a extension
manifest.json
{
"name": "Run code in page",
"version": "1.1",
"manifest_version": 2,
"content_scripts": [{
"js": ["contentscript.js"],
"matches": ["https://*/*"]
}],
"web_accessible_resources": ["*.js"],
"default_locale": "en"
}
contentscript.js
function injectScript(script) {
var s = document.createElement('script');
s.src = chrome.extension.getURL(script);
(document.head || document.documentElement).appendChild(s);
}
injectScript('script.js');
injectScript('otherscript.js');
script.js
console.log('script.js');
otherscript.js
console.log('otherscript.js');
This works, I see this in the output :
script.js
otherscript.js
All is good, both scripts are loading, I need jQuery to be added in the same way so that I can access jQuery from my script.
So, I
injectScript('jquery.js');
But now I get the following error
Denying load of chrome-extension://abdiolbenneaffeaedmfeeanlephlnoo/jquery.js. Resources must be listed in the web_accessible_resources manifest key in order to be loaded by pages outside the extension.
If I look at the DOM, I see this
<script src="chrome-extension://abdiolbenneaffeaedmfeeanlephlnoo/script.js"></script>
<script src="chrome-extension://abdiolbenneaffeaedmfeeanlephlnoo/otherscript.js"></script>
<script src="chrome-extension://abdiolbenneaffeaedmfeeanlephlnoo/jquery.js"></script>
If I put chrome-extension://abdiolbenneaffeaedmfeeanlephlnoo/jquery.js into the URL I can access it.
-- edit
If I load jquery externally it will load, so I guess I can just do that. eg
function injectExternalScript(script) {
var s = document.createElement('script');
s.src = script;
(document.head || document.documentElement).appendChild(s);
}
injectExternalScript('https://code.jquery.com/jquery-3.3.1.min.js');
If you want do inject jQuery into your extensions background page do in inside the manifest.json like so:
Example:
"background": {
"persistent": true,
"scripts": ["jquery-3.3.1.min.js", "background.js"]
},
Note: Make sure jQuery is first in the array so it loads before the actual background.js
But, in your case, you are not executing that code in the background nor are you injecting anything to it since you are mistaking a content script for a background page which you don't have.
I recommend you first read the official documentation regarding Chrome Extension Architecture before anything else.
You can also write code like so in your content.js to be injected directly into the DOM from your content script so you can avoid using multiple unnecessary .js files in your extension.
Content.js:
//Injects functions directly into the dom
function inject(fn) {
var script = document.createElement('script');
script.setAttribute("type", "application/javascript");
script.textContent = '(' + fn + ')();';
document.body.appendChild(script); // run the script
document.body.removeChild(script); // clean up
}
inject(function(){
// code that will be executed in the scope of the page
}
You can read more about this here.
This is really weird. You probably checked if the jquery.js file is in the root folder and with this name, right?
Well, in my case I wanted to add jQuery in all pages that match in content_scripts > matches so I just did something like this:
...
"content_scripts": [
{
"matches": [
"https://*/*"
],
"js": [
"assets/js/jquery.js",
"assets/js/contentscript.js"
]
}
],
...
So in this way I can use jQuery in contentscript.js file.
Good morning Masters ^^
Firstly, i just have a small problem what i cant solve o.o
I have a google chrome extension program which made those :
- If mouse event happening then open one other page (itself detectionclicks.js)
- If until 5 minutes not happening mouse event open back the before page (itself background.js)
My problem is that, when we reach the 5 minutes, the site cant apper when i use "_self" but apper if i use "_blank".... but in detectionclicks.js the "_self" is working properly. Maybe under the background.js i cant use "_self" parameters?
I use Google Chrome browsers - Version 63.0.3239.108 (Official Build) (64-bit) (under windows 10).
So everything is working perfectly (I mean the timer, and reset the timer also, and the detectionclicks.js open the site itself properly..) just under the background.js window.open "_self" wont want working, just if i use "_blank".
Manifest.json
{
"name": "Chrome-extension",
"version": "1.0",
"manifest_version": 2,
"permissions": [
"alarms", "cookies"
],
"background": {
"scripts": ["background.js"]
},
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["jquery1.7.2.js", "detectclicks.js", "background.js"]
}
],
"description": "Chrome-extension",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
}
}
Background.js
chrome.runtime.onMessage.addListener(function(msg, _, sendResponse) {
if (msg.setAlarm) {
chrome.alarms.create({delayInMinutes: 0.1});
} else if (msg.delayedResponse) {
setTimeout(function() {
sendResponse("Got your message.");
}, 300000);
return true;
} else if (msg.getCounters) {
sendResponse({counter: counter++,
persistentCounter: localStorage.counter++});
}
});
chrome.alarms.onAlarm.addListener(function() {
window.open("http://www.google.com","_blank"); //THIS IS WORK
// window.open("http://www.google.com","_self"); THIS ISN'T WORK
});
Detectionclicks.js
$('html').on('click', '*', function(event) {
window.open("http://gmail.com","_self");
});
$('html').on('mousemove','*', function(event) {
chrome.runtime.sendMessage({setAlarm: true});
});
Popup.html
<style>
div.content { width: 250px }
</style>
<!DOCTYPE html>
<html>
<body>
<div class="content">
<p>
Site information : This extension will open a new site
after 5 minutes if wont happening a mouse event. If mouse
event happening, the extension will open an other site.
</p>
</div>
</body>
</html>
Popup.js
chrome.extension.getBackgroundPage().timers[tabId] = new Date();
Thank you for your supporting ^^, even if you just read it :)
Please use this
chrome.tabs.create({ url: "http://gmail.com" });
instead of
window.open("http://gmail.com","_self");
more reference please visit https://developer.chrome.com/extensions/tabs#method-create
I can solve the problem in this way ^^'
I know this isn't the best solution, but its looks like made what i want.
(Close the site and open other one... its looks like change the active site ^^')
chrome.tabs.query({active:true,currentWindow:true},function(tabs){
chrome.tabs.remove(tabs[0].id);
});
window.open("http://www.gmail.com","_blank");
});
Thank you for your help, and as i read your solution the original way, but i don't know why open the new tab the site in my chrome browsers o.o ...
So even if i use other solution, i think i accept your answer ^^
Thank you for your help :)
As basic as it gets in background.js of a Chrome extension:
chrome.tabs.insertCSS(tab.id, {
file: "widget.css",
allFrames: true
}, function () {
if (chrome.runtime.lastError) {
console.error(chrome.runtime.lastError.message);
}
console.log("Inserted CSS in tab " + tab.id);
});
Take out the allFrames argument (or set it to false) and the console shows the expected message, Inserted CSS in tab 1234 and I can see the changes to formatting on the target page. Set it to true and... nothing. No errors, no timeouts, just silence and tumbleweeds in the console of the extension.
If I reload the page or navigate to a different URL in the same tab, I see the Inserted message suddenly pop into the console and then it continues with loading whatever new content was asked for.
Manifest permissions include:
"permissions": ["<all_urls>", "tabs", "activeTab"],
"web_accessible_resources": ["*.js","*.css"]
This bug was fixed in Chrome v50.
I created an extension for Google Chrome which runs a small userscript for designated web-page and makes some requests via background.js to the chrome APIs (such chrome.tabs and others).
now, I'm testing it locally in "Developer mode" like this:
I edit my userscript.js and background.js;
then I go to chrome://extensions tab in Google Chrome and manually reload (CTR+R) my extension from local D:\my-extension folder.
finally, I switch to the tab with designated web-page and reload it to see the changes.
the problem is:
since I'm a beginner, a lot of changes have to be done to my userscript.js and background.js before my extension and userscript start working as expected.
so, this process involves a lot of monotonous switching between extensions and page tabs while testing.
the idea is:
it would be nice to add a button or a shortcut key on the page where the userscript is being tested and attach a sort of 'update_extension_and_reload_page' function to it in my userscript, so that evey time when I click this button it will call extension update from the local folder D:\my-extension then followed by page reload. (another alternative would be to assign such 'update_extension_and_reload_page' function to extension's browser_action icon.)
now, I'm just interested:
is there any sort of 'chrome.extesion.update' method, so that I could make a request to it from my userscript.js via background.js and call automatic reload of the extension (in "Developer mode") without need to go to the chrome://extensions tab.
The extension can reload itself, by calling chrome.runtime.reload(), so it's a matter of triggering the extension to do it.
The code below attaches the following functionality to the browser-action button:
Keeps track of the active tab.
Reloads the extension.
Reloads the active tab.
manifest.json
...
"browser_action": {
"default_title": "Reload"
// "default_icon": {
// "19": "img/icon19.png",
// "38": "img/icon38.png"
// },
},
...
background.js
chrome.browserAction.onClicked.addListener(function (tab) {
localStorage.tabToReload = tab.id;
chrome.runtime.reload();
});
function reloadTab() {
var tabID = localStorage.tabToReload;
if (tabID) {
chrome.tabs.reload(parseInt(tabID));
delete(localStorage.tabToReload);
}
}
reloadTab();
...
See, also, this answer on how to automate the re-loading process.
is this what you are looking for?
https://chrome.google.com/webstore/detail/extensions-reloader/fimgfedafeadlieiabdeeaodndnlbhid
Credit goes go
How do I auto-reload a Chrome extension I'm developing?
slightly modified the ExpertSystem's code above to call reload of extension followed by reload of tab where the content script (userscript.js) is being performed, all triggered by #reload-btn button (in case the browser_action icon is occupied with popup.html).
manifest.json
...
"background":{ "scripts": ["background.js"]},
"content_scripts" : [{
"matches" : ["https://stackoverflow.com/*"],
"css": ["userscript.css"],
"js": ["jquery-latest.min.js", "userscript.js"],
"run_at":"document_end"
}],
"web_accessible_resources": ["jquery-latest.min.map"],
"permissions": ["tabs"],
"browser_action": {
"default_icon": "icon19.png",
"default_title": "My Extension Title",
"default_popup": "popup.html"
}
...
userscript.css
...
#reload-btn { position: fixed; top: 0; right: 0; } /* or any other position on the page */
...
userscript.js
...
$("body").prepend("<button id='reload-btn'>reload extension + page reload</button>"); // some shortcut key can be additionally assigned to this button
$("#reload-btn").on("click", function() {
chrome.runtime.sendMessage("please, reload me");
});
...
background.js
...
chrome.runtime.onMessage.addListener(
function(message, sender) {
if (message == "please, reload me"){
localStorage.tabToReload = sender.tab.id;
chrome.runtime.reload();
}
});
function reloadTab() {
var tabID = localStorage.tabToReload;
if (tabID) {
chrome.tabs.reload(parseInt(tabID));
delete(localStorage.tabToReload);
}
}
reloadTab();
...
I created a Chrome extension that works as expected except that it only executes when I load a page that matches the conditions in the manifest. I have tried for hours to make it execute by clicking on the extension icon to no avail.
The closest I have been able to what I want is that I have been able to make the extension icon click to run the code, but then it does not run it on the loaded page. It runs it on the extension's space instead of the page DOM.
In the current state my code only runs when a page in the specified domain opens. I want to run it only when it matches that rule, but only when I click the extension icon.
Here is my code:
manifest.json
{
"name": "Get Response URL",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"default_icon": "mkto_icon.png",
"name": "Click to get URL"
},
"content_scripts": [{
"js": ["contentscript.js"],
"matches": ["http://mydomain.com/*"]
}]
}
contentscript.js
if (document.getElementsByName("returnURL")){
alert("\nThe Response URL on this form is:\n\n" + document.getElementsByName("returnURL")[0].value);
}
As i see you want to run code when
User has clicked on Browser Action ICON and
URL pattern is a match
If so, you have use
Background pages in conjunction with Tabs API.
Demonstration
This is a sample demonstration of your use case and you can put all your code and assign permissions for all match URL(s).
manifest.json
Registered Background Page, Browser Action and Permissions for Target Pages.
{
"name": "Get Response URL",
"version": "1.0",
"manifest_version": 2,
"browser_action": {
"name": "Click to get URL"
},
"background":{
"scripts":["background.js"]
},
"permissions":["https://www.google.co.in/*"] //Put All your URL here
}
background.js
Put all Your Target Matching URL in a series of if conditions here
chrome.browserAction.onClicked.addListener(function (tab) { //Fired when User Clicks ICON
if (tab.url.indexOf("https://www.google.co.in/") != -1) { // Inspect whether the place where user clicked matches with our list of URL
chrome.tabs.executeScript(tab.id, {
"file": "contentscript.js"
}, function () { // Execute your code
console.log("Script Executed .. "); // Notification on Completion
});
}
});
contentscript.js
alert("Code Executed ... ");
Output
When you browse to https://www.google.co.in/ and after click of browser action you see Alert in the page.
References
Tabs API
Background Pages
use browserAction API ,see here
the onClick events may help you. also see these exsamples from google :