Event handler when site doesn't match manifest.json 'matches' - google-chrome-extension

My manifest.json contains this block:
"content_scripts": [
{
"all_frames": true,
"matches": [
"*://www.google.com/*",
"*://www.cnn.com/*",
"*://*.foxnews.com/*"
],
"js": ["js/main.js"]
}
],
I need an event to fire (either in my content js or background.js, doesn't matter) whenever the user visits a website that does not match one of the sites in my matches setting.
How is it done?

In your background.js you could add a listener for tab load. In this you could fetch the URL of the current tab and match with a list.
chrome.tabs.onUpdated.addListener(function(tabId, info, tab) {
if (info.status == "complete") {
var url = tab.url.replace(/.*?:\/\//g, "").replace(/\/$/, ""); //removes the protocol
var allowedURLS = ["www.google.com", "www.cnn.com", "foxnews.com"];
for(var i in allowedURLs) {
if(allowedURLs[i].indexOf(url) == -1) {
//URL does not match
break;
}
}
}
});

You need to use exclude_matches in your content script , that says that the script under it will not inject.
From the google documentation:
Excludes pages that this content script would otherwise be injected into. See Match Patterns for more details on the syntax of these strings and Match patterns and globs for information on how to exclude URLs.
For your case:
"content_scripts": [
{
"all_frames": true,
"matches": ["<all_urls>"],
"js": ["js/main.js"],
"exclude_matches": [
"*://www.google.com/*",
"*://www.cnn.com/*",
"*://*.foxnews.com/*",
]
}
]

Related

Chrome Extension Manifest matches not working for clicking into that url

I have the following manifest
{
"manifest_version":2,
"name": "HelloWorld",
"version": "0.1",
"content_scripts": [
{
"matches": [
"*://www.mywebsite.com/"
],
"js": ["home.js"],
"run_at": "document_start"
}
]
}
It works perfectly when I enter www.mywebsite.com through browser url bar. But when I route to the same url www.mywebsite.com through hyperlinks in another url, the script does not trigger. Why is that? I do not see this in
I just figured out a temporary method, you can do
<some_dom_object>.addEventListener("click", function() {
// do the thing you want happen.
})
on that "button element" or "anchor element" or whatever that you clicked to that website, so the code will get executed also when you "click" to the url.

Browser action to activate only on "content_script" matches

I thought this would be a regularly asked question, but I can not find the answer for it.
Is there a way for a chrome extension to have it's browser action popup available only on content_scripts matching pages?
Eg: I make an extension for a site. I want the popup to only be available when browsing the site (on the current tab). How do I do?
For me the browser action is always enabled by default, whatever page I'm browsing, and page action never enabled.
Thanks for your help
EDIT: Here is part of the manifest, I changed with pageAction with No success. I want my icon to activate only on tabs browsing LDLC.
{
"content_scripts": [
{
"js": [ "jquery.min.js", "scrooge.js" ],
"matches": [ "*://www.ldlc.com/fiche/*", "*://ldlc.com/fiche/*" ]
}],
"manifest_version": 2,
"permissions": [ "storage", "activeTab","*://ldlc.com/*", "*://scroogealpha.esy.es/*" ],
"page_action": {
"default_title": "Worth buying?", // optional; shown in tooltip
"default_popup": "popup.html" // optional
},
"web_accessible_resources": [
],
"background":{
"scripts" : ["eventPage.js"],
"persistent": false
}
}
Use a page action and in your background script listen for tab changes. When a tab url changes, check if you want to show the page action.
In your background script do something like this:
let matches = ["://www.ldlc.com/fiche/", "://ldlc.com/fiche/" ]
chrome.tabs.onUpdated.addListener((tabId, changeInfo, tab) => {
for (let i in matches) {
if (tab.url.includes(matches[i])) {
chrome.pageAction.show(tabId)
break
}
}
})
Also add the tabs permission in your manifest.

Chrome extension: Content script matching URL pattern for Gmail message

For my Chrome extension, I need a matching pattern for any valid Gmail message URL. Example:
https://mail.google.com/mail/u/0/?shva=1#inbox/140acd877b64109b
What I tried in manifest.json is the following:
"content_scripts": [ {
"matches": ["*://*.mail.google.com/mail/u/0/?shva=1#inbox/*"],
"css": ["default.css"]
} ]
However, my custom stylesheet is not applied when I access a Gmail message with the URL pattern above.
Any ideas why it is not applied?
If I only use "matches": ["*://*.mail.google.com"], then it works. Yet I do not want the stylesheet to be applied to my inbox page too. Thus I am looking for a pattern to only catch single message pages.
The location fragment (#...) is always ignored in the match pattern. Last time I checked, the query string is also ignored for the "css" field.
To get the desired effect, just insert the stylesheet on "*://*.mail.google.com/*", and use a content script to detect URL changes. For example:
Fragment of manifest.json:
"content_scripts": [ {
"matches": ["*://*.mail.google.com/*"],
"css": ["default.css"],
"js": ["style-toggler.js"]
} ]
Example of default.css:
.turn-on-my-style img {
visibility: hidden;
}
If prefixing your CSS selectors takes too much efforts, I suggest to use a CSS preprocessor like LESS.
style-toggler.js:
function hashCheck() {
if (/^#inbox\/.*/.test(location.hash)) {
document.documentElement.classList.add('turn-on-my-style');
} else {
document.documentElement.classList.remove('turn-on-my-style');
}
}
window.addEventListener('hashchange', hashCheck);
hashCheck();

Why does my Chrome extension's Action Icon shown on all pages in omnibox?

I have following manifest
"page_action": {
"default_icon": {
"19": "images/icon19.png",
"38": "images/icon38.png"
},
"default_title": "Helper for soiduplaan.tallinn.ee"
},
"content_scripts": [
{
"matches": [
"http://soiduplaan.tallinn.ee/*"
],
But I see icon of my app in all pages I visit:
What do I do wrong? =\
Your current code is:
chrome.tabs.onUpdated.addListener(function(a) {
chrome.pageAction.show(a);
});
This causes the page action to be shown whenever a page is loaded, ie for every tab.
If you want to restrict the page action to certain pages only, check the tab.url property:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (tab.url && tab.url.indexOf('http://soiduplaan.tallinn.ee/') === 0) {
chrome.pageAction.show(tabId);
}
});
For more info, read the docs for chrome.tabs.onUpdated.

Chrome extension content scripts are not injected in the first place, how to debug?

When I'm running the Chromium browser using:
chromium-browser --load-extension=/path/to/my/extension
--user-data-dir=/path/to/chrome/profile --app=http://localhost/somepage
some content scripts are not injected into the page. These scripts are defined as follows in the manifest file:
"content_scripts" : [{
"matches" : [ "http://*/*", "https://*/*" ],
"js" : [ "content/s1.js", "content/s2.js", "content/s3.js", "content/s4.js" ],
"run_at" : "document_end"
}]
When inspecting the page, I see that only s1.js and s4.js were injected successfully. After reloading the page all scripts are injected correctly, and my extension works as expected.
What can be the reason for that, and how to debug this?
Edit:
Those content scripts (that fail to inject sometimes) reference 'document' at the beginning. It seems like if I wrap them into something like:
setTimeout(function() { document. ... }, 5000);
They are always injected as expected. Is it possible that the document is not available, even though "run_at": "document_end" was specified in manifest?
Thanks!
You can better do this:
Create 1 content.js script:
/* inject script */
try {
var script1 = document.createElement("script");script1.type = "text/javascript";script1.src = chrome.extension.getURL("/js/injected1.js");document.getElementsByTagName("head")[0].appendChild(script1);
var script2 = document.createElement("script");script2.type = "text/javascript";script2.src = chrome.extension.getURL("/js/injected2.js");document.getElementsByTagName("head")[0].appendChild(script2);
var script3 = document.createElement("script");script3.type = "text/javascript";script3.src = chrome.extension.getURL("/js/injected3.js");document.getElementsByTagName("head")[0].appendChild(script3);
var script4 = document.createElement("script");script4.type = "text/javascript";script4.src = chrome.extension.getURL("/js/injected4.js");document.getElementsByTagName("head")[0].appendChild(script4);
} catch(e) {}
in the manifest.json:
"content_scripts" : [{
"matches" : [ "http://*/*", "https://*/*" ],
"js" : [ "content.js" ],
"run_at" : "document_end"
}]

Resources