Reloading a Chrome extension content script execution environment - javascript

I’d like to mimic the effect of window.location.reload(), but only for the “isolated world” which my content script is running in. That is, remove all existing JS, particularly callbacks and event bindings. Is there a nice way to do this?
Note: chrome.runtime.reload() doesn’t work for this; it has the effect of reloading the extension and the background script, but it does not reload existing content scripts until the user refreshes.

As far as I can tell, there's no automatic way to re-inject content scripts, for example during an extension update. What you can do is to find all tabs whose url matches the pattern you need, and programmatically re-inject the content scripts using chrome.tabs.executeScript.
Note that this method requires to add a permission for the same URL pattern as the one used by your content script.
Manifest.json:
"content_scripts":
[
{
"matches": [ "http://*.google.com/*" ],
"js": [ "content_script.js" ]
}
],
"permissions":
[
"tabs", "http://*.google.com/*"
]
Background.js:
chrome.runtime.reload();
chrome.tabs.query({ url: "http://*.google.com/*" }, function(tabs)
{
for(var i = 0; i < tabs.length; i++)
{
chrome.tabs.executeScript(tabs[i].id, { file: "content_script.js" }, function() {});
}
});

Related

Run JS with "matches" even if the page doesnt refresh

I am working on a school project/ Chrome extension that assists the Checkout progress of a Website,
i declared in my mainfest.json that a content.js file should run if it matches a certain URL.
"content_scripts": [
{
"matches": [
"https://www.solebox.com/de_DE/checkout?stage=payment*"
],
"js": ["payment.js"]
},
{
"matches": [
"https://www.solebox.com/de_DE/checkout?stage=placeOrder*"
],
"js": ["placeorder.js"]
as you can see in the link, there are different stages. So from stage "payment" to stage "place order" the page won't refresh, ergo the script won´t notice that the URL changed so the js cant be executed.
Is there any way the chrome extension can always check the URL?
You could use try using webNavigation. Just check the tab-url and inject your desired script based on that.
chrome.webNavigation.onBeforeNavigate.addListener(function (tab) {
chrome.tabs.get(tab.tabId, function (results) {
if (results.url.match("some URL")) {
chrome.tabs.executeScript(tabId, {
file: "someScript.js"
});
}
});
});
You can read about the webNavigation API here

Chrome Extension: Run Content Script before any Embedded Scripts run on Page

I'm trying to change some behavior of the YouTube player, by changing some variables inside of the player_api script that is embedded into the html watch page of videos.
Problem is, whatever i try, the embedded script of the player always runs before my extension adds modifications to it. Thus keeping the behavior of the player the same.
I tried setting the run_at property in my manifest to document-start, but then the script didn't run at all.
What can i do to halt the execution of that script until i make changes to it?
PS: I tried changing the script by intercepting the html call and editing the body with Charles Proxy and the behavior of the player changed as i wanted. So it know it should work, if done at the right time.
.
manifest.json
{
"manifest_version": 2,
"name": "YouFit For YouTube",
"version": "1",
"content_scripts": [{
"js": ["content.js"],
"matches": ["https://*.youtube.com/watch?*",
"https://*.youtube.com/watch?*"],
}],
"browser_action": {
"default_icon": "icon.png"
}
}
content.js
function changeBehavior() {
var scriptElements = document.getElementsByTagName('script');
for (var i = 14; i < scriptElements.length; i++) {
var curScriptBody = scriptElements[i].outerHTML;
// Find the script i'm interested in
if (curScriptBody.indexOf("var ytplayer") != -1) {
scriptElements[i].outerHTML = scriptElements[i].outerHTML.replace("<text>", "<replacement text>");
alert("Replaced");
break;
}
}
}
changeBehavior();
Did you try something like this?
content.js
var script = document.createElement('script');
script.textContent = "/* What you have in content.js right now */";
(document.head||document.documentElement).prepend(script);
Add "run_at": "document_start" to the manifest file for the content script then modify your content script such that changeBehavior is called after the current call stack is exhausted using setTimeout(fn, 0). It will run just after the HTML document is rendered but before any embedded scripts.
This solution also avoids potential issues with running unsafe inline scripts when the content security policy is set.
Content.js
function changeBehavior() {
...
}
setTimeout(() => {
changeBehavior();
}, 0);

Content script not executing in new window

I am trying to create a Chrome extension that, when clicked, opens a new incognito window and performs some DOM action on it. These are the files I'm using:
manifest.json
{
"manifest_version": 2,
"name": "SampleExtension",
"description": "",
"version": "1.0",
"incognito": "spanning",
"browser_action": {
"default_icon": "icon.png",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["http://www.google.com"],
"js": ["myscript.js"]
}
],
"permissions": [
"tabs",
"activeTab",
"http://www.google.com"
]
}
popup.js
chrome.windows.create({
"url": "http://www.google.com",
"focused": true,
"incognito": true
});
chrome.tabs.executeScript(null, {
"file": "myscript.js",
"run_at": "document_end",
"all_frames": true
});
myscript.js
document.querySelector('a[target]').click();
The extension opens the new window, but my content script doesn't seem to be executing. Any thoughts?
Edit: Added "incognito": "spanning" to the manifest. Still doesn't work, however.
First of all, I understand that you have enabled to run in Incognito Mode. Extensions are disabled by default and, hence, it would not run otherwise.
Secondly, your match pattern needs to end with a slash:
"matches": ["http://www.google.com/"],
Thirdly, Google will redirect you to its https version, hence I would improve the match pattern like this:
"matches": ["*://www.google.com/"],
Still, it didn't work for me as I was redirected to my local Google domain. Hence, I had to do add more:
"matches": [
"*://www.google.com/*",
"*://www.google.com.sg/*"
],
Also, I added the final wildcard, because Google was adding some ?urlParams that I had to match too. And this made it work. Note that I tried with other pages like "*://www.stackoverflow.com/*", and it was easier than Google :)
In case your Google page was just a test, I'd advise to use some less redirected pages to test with.
A final note: I do not think it's possible to use the wildcard for the domain (I tried). However, you can request all the main domains, or request all_pages and then add the logic for Google only on my_script.js to decide whether to execute the action or not. (However, this last piece is not ideal).
Edit post comments:
It seems your function fails because the element is not loaded yet. An easy way to solve this is by doing an interval which checks whether the element is on the page. When it finds it, clicks it and removes the interval.
// Function which clicks element if existing and clears interval after doing it.
var clickLink = function() {
if (document.querySelectorAll('a[target]').length > 0) {
clearInterval(waitAndClick); // stop interval
document.querySelector('a[target]').click(); // click element.
}
}
// Run click function every second, until it clicks it.
var waitAndClick = setInterval(clickLink, 1000);

javascript in extension not working

I am trying to make a chrome extension that blocks iframes. I have a content.js file that has the javascript code in it but it does not execute.
Here is my manifest.json:
{
"manifest_version":2,
"name":"Ad Killer",
"description":"A Basic program for blocking ads",
"version":"0.1",
"background":{
"scripts":[
"background.js"
]
},
"content_scripts":[
{
"matches":[
"<all_urls>"
],
"js":[
"jquery.js"
]
}
],
"browser_action":{
"default_icon":"ad128.png",
"default_title":"Ad Killer"
}
}
Cotent.js:
var elems = document.getElementsByTagName("iframe");
for (var i = 0, max = elems.length; i < max; i++) {
elems[i].hidden = true;
My question is that is there any way to make the javascript in content.js work? Any help would be appreciated.
Your manifest is currently adding jquery.js to every page you visit. You just need to add content.js to your "content_scripts" array. Assuming content.js is in the same location as your manifest.json:
"content_scripts":[
{
"matches":[
"<all_urls>"
],
"js":[
"jquery.js",
"content.js"
]
}
],
Additionally, you'll want to make sure the code runs when the DOM is ready. Since you're using jQuery:
$(document).ready(function() {
//your code here
})
There are options for the manifest that define when the scripts run, but I've never had much success with them, you can explore them here: https://developer.chrome.com/extensions/content_scripts see the run_at attribute.
And you may even want to set up a timeout or poll to query for iframes since some of them may be created asynchronously, that is, after the ad content is loaded.

Develop a chrome extension to count <input> tags of currently accessed webpage

Hey I'm new to javascript and chrome extension developing. I'm trying to develop a chrome extension which use browser action to count the number of tags in currently active tab of the Google Chrome browser.I can use getElementsByTagName.lenght method to calculate the number of tags and I know that I can use console API to access the DOM of a webpage. But I have no idea how to call that API from my javascript file.Do you guys know anything regarding this ?
To get access to the current page DOM you need to write a content script.
1. Specify the content script in manifest.json
"content_scripts": [
{
"matches": ["http://www.google.com/*"],
"css": ["mystyles.css"],
"js": ["jquery.js", "myscript.js"]
}
]
If you need to inject the script sometimes use Programmatic Injection by specifying permissions field:
{
"name": "My extension",
...
"permissions": [
"activeTab"
],
...
}
2.I would prefer the latter in this case.In popup.js add the code:
function printResult(result){
//or You can print the result using innerHTML
console.log(result);
}
chrome.tabs.executeScript(null, { file: 'content.js' },function(result){
printResult(result);
});
3.In content script u have access to current page/active tab DOM.
var result=document.getElementsByTagName("input").length;

Categories

Resources