Chrome extension: Content script matching URL pattern for Gmail message - google-chrome-extension

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();

Related

Chrome extension simple script not being injected

I'm trying my first steps in writing a minimal Chrome extension, and I cannot figure out why it does not execute my clientScript.js.
This is my manifest.json:
{
"name": "Sit back, relax and enjoy",
"version": "0.1",
"description": "Finds and clicks the +extra channel points button when it is available",
"permissions": [ "activeTab" ],
"content_scripts": [
{
"matches": [ "https://twitch.tv/*" ],
"js": [ "contentScript.js" ],
"run_at": "document_idle"
}
],
"manifest_version": 2
}
And this is the the script that I want executed on pages that match https://twitch.tv/*:
let intervalTimer
function sibareaen() {
const btn = document.querySelector('.tw-button.tw-button--success.tw-interactive')
if (btn) {
btn.click()
console.log('At your service - clicked the button for you!')
}
}
function toggleSibareaen(on) {
switch (on) {
case true:
intervalTimer = setInterval(sibareaen, 750)
break
case false:
clearInterval(intervalTimer)
break
default:
clearInterval(intervalTimer)
}
}
console.log('At your service - ready to click for you!')
toggleSibareaen(true)
I have both files in the same folder:
Also, I have properly "installed" the extension:
The console shows no errors related to the extension.
What am I missing?
Assuming you did reload the tab (the content scripts are injected only on initial tab load, see this for more info and a workaround), you're probably a victim of the infamous Google's decision to hide www in the address bar: if you enter the edit mode and select/copy the entire text (or simply double-click the address) you will see the site's URL is actually https://www.twitch.tv/ so your manifest.json has an incorrect URL pattern that doesn't match the real site.
Simply use a generalized pattern like "https://*.twitch.tv/*" that will match both https://www.twitch.tv/ and https://twitch.tv/ and any other subdomain(s).
P.S. as a debugging step, you can check if the content script is even injected by looking at the context selector in devtools console toolbar or in devtools -> Sources -> Content scripts panel. And if you want to restore the classic address bar behavior, see https://superuser.com/a/1498561

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.

Event handler when site doesn't match manifest.json 'matches'

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/*",
]
}
]

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.

On page load event in Chrome extensions

I want to check some values in the content of chrome browser page when it completely loaded
like that
if(document.body.innerText.indexOf("Cat") !=-1)
Where and when can I make my check? please give me an clear example
I read some thing about "Background.html" and "Content script" but I can't do
Register a content script in the manifest file at "run_at": "document_idle" (which is the default) and put your code in the content script file. Then the script will be run when the page is ready.
If you want to detect from the background page whether a page is completely loaded, use the chrome.webNavigation.onCompleted event and do whatever you want, such as calling chrome.tabs.executeScript to execute a content script. This method could be useful over the previous method if the list of URLs is dynamic or if the URL patterns cannot be described using the match pattern syntax.
chrome.webNavigation.onCompleted.addListener(function(details) {
chrome.tabs.executeScript(details.tabId, {
code: ' if (document.body.innerText.indexOf("Cat") !=-1) {' +
' alert("Cat not found!");' +
' }'
});
}, {
url: [{
// Runs on example.com, example.net, but also example.foo.com
hostContains: '.example.'
}],
});
The webNavigation and host permissions have to be set in manifest.json, e.g.:
{
"name": "Test",
"version": "1.0",
"background": { "scripts": ["background.js"] },
"permissions": [ "webNavigation", "*://*/*" ],
"manifest_version": 2
}

Resources