How can I run this script when the tab reloads (chrome extension)? - javascript

So i'd like to run a script when the tab reloads in a specified URL. It almost works, but actually id doesn't :)
This is my manifest file:
{
"manifest_version": 2,
"name": "Sample Extension",
"description": "Sample Chrome Extension",
"version": "1.0",
"content_scripts":
[
{
"matches": ["http://translate.google.hu/*"],
"js": ["run.js"]
}
],
"permissions":
[
"activeTab",
"tabs"
],
"browser_action":
{
"default_title": "Sample",
"default_icon": "icon.png"
}
}
and this is run.js:
chrome.tabs.onUpdated.addListener(
function ( tabId, changeInfo, tab )
{
if ( changeInfo.status === "complete" )
{
chrome.tabs.executeScript( null, {file: "program.js"} );
}
}
);
The programs.js just alerts some text (yet). When I put an alert to the first line of the run.js, it alerts, but when I put it in the if, it doesn't. I can't find the problem. Did I type something wrong?

Assuming that http://translate.google.hu/* pages are the ones you wish to inject code into on reload, you would have to go about it in a slightly different way. Currently you are always injecting code into those pages (without the permission to do so, no less) and then trying to use the chrome.tabs api inside that content script, which you can't do. Instead, we will put the listener in a background page and inject the code only on a page refresh, like you want. First the manifest:
{
"manifest_version": 2,
"name": "Sample Extension",
"description": "Sample Chrome Extension",
"version": "1.0",
"background": {
"scripts": ["background.js"]
},
"permissions":[
"http://translate.google.hu/*", "tabs"
]
}
background.js
chrome.tabs.onUpdated.addListener(function(tabId,changeInfo,tab){
if (tab.url.indexOf("http://translate.google.hu/") > -1 &&
changeInfo.url === undefined){
chrome.tabs.executeScript(tabId, {file: "program.js"} );
}
});
This will listen for the onUpdated event, checks if it is one of the url's that we want to inject into, and then it checks if the page was reloaded. That last step is accomplished by checking if changeInfo.url exists. If it does, then that means that the url was changed and thus not a refresh. Conversely, if it doesn't exist, then the page must have only been refreshed.

2021
If you want to detect reload from background.js in manifest 3 (maybe also 2), chrome.tabs.onUpdated approach didn't work for me :/ It was invoked too many times.
That what worked for me in the end!
// --- On Reloading or Entering example.com ---
chrome.webNavigation.onCommitted.addListener((details) => {
if (["reload", "link", "typed", "generated"].includes(details.transitionType) &&
details.url === "http://example.com/") {
codeAfterReload();
// If you want to run only when the reload finished (at least the DOM was loaded)
chrome.webNavigation.onCompleted.addListener(function onComplete() {
codeAfterReloadAndFinishSomeLoading();
chrome.webNavigation.onCompleted.removeListener(onComplete);
});
}
});
For more transition types: https://developer.chrome.com/docs/extensions/reference/history/#transition_types
good luck :)

content_scripts are run at every page (re)load, so it's best to just use those to detect it.
This way you also don't risk running any code in the background before your content_script is ready to receive any message.

Related

Can't access content of page when attempting to add Dom to chrome-extension:// URL

My chrome extension spawns a temp .html page. I want to manipulate the DOM of the sample.html page that was created, but can't. I can manipulate the DOM for any other page without issue. The problem seems to be with the fact my temp .html page resides within chrome-extension://
Error Message:
Unchecked runtime.lastError while running tabs.executeScript: Cannot access contents of url "chrome-extension://123/sample.html?id=100". Extension manifest must request permission to access this host.
Note: for simplicity sake I provided sample code that exhibits the same Error. Once loaded I can use the key combo to inject a div and some text into any webpage (Mac-> Cmd+Shift+P or PC Ctrl+Shift+P)
I've tried adding all possible permissions and even web_accessible_resources to the manifest.json. (I don't believe this to be the issue). I've tried different ways to inject the code into the sample.html by calling out the specific tabId, activeTab or even setting the tabId to null within the background file. I've read through stackoverflow, googled and looked around but came up short.
manifest.json
{
"manifest_version": 2,
"name": "sample1",
"description": "sample1",
"version": "0.0.1",
"browser_action":
{
"default_title": "sample"
},
"commands":
{
"saveImageCommand":
{
"suggested_key":
{
"default": "Ctrl+Shift+Z",
"mac": "Command+Shift+Z"
},
"description": "Toggle Save Image"
},
"playback":
{
"suggested_key":
{
"default": "Ctrl+Shift+P",
"mac": "Command+Shift+P"
},
"description": "load player Image"
}
},
"permissions": [
"tabs",
"activeTab",
"storage",
"<all_urls>",
"*://*/*"
],
"background":
{
"persistent": false,
"scripts": ["background.js"]
}
,
"web_accessible_resources": [
"chrome-extension://*/sample.html?id=*"
]
}
background.js
chrome.commands.onCommand.addListener(function(command) {
if (command === 'saveImageCommand') {
capturecurrent();
}
if (command === 'playback') {
chrome.tabs.executeScript(null, {
code: 'var divNode = document.createElement("div");divNode.setAttribute("id", "video1Div");var instructions = document.createTextNode("testing");divNode.appendChild(instructions);document.body.appendChild(divNode)'
});
}
});
chrome.browserAction.onClicked.addListener(function() {
chrome.tabs.captureVisibleTab(function(screenshotUrl) {
var viewTabUrl = chrome.extension.getURL('sample.html')
chrome.tabs.create({ url: viewTabUrl });
});
});
sample.html
<html>
<head></head>
<body>
<div id="firstDiv">firstDiv</div>
</body>
</html>
Expected Results:
For me to interact directly with the DOM on the temp sample.html page.
Note:
I don't want to build out buttons for DOM manipulation directly within the sample.html page. That defeats the purpose of this exercise. Esp since I want to use shortcut key combos to call this DOM manipulation (Mac-> Cmd+Shift+P or PC Ctrl+Shift+P)
Actual Results:
I am able to interact with the DOM on any normal website using the shortcut key combo but not the sample.html that URL starts with chrome-extension://

How to solve Chrome extension cannot find DOM event when fired on click?

I have a chrome extension that fires on a button click, the extension still can't access DOM elements, even though the page has clearly loaded.
I've seen other posts say it is because the elements are being created dynamically but not in my case.
The only thing that works is to wrap my debugTools.js in a timeout and fire it after 800 or so milliseconds.
The code inside debugTools.js is the part not working. I don't understand why is says "theWrapper" is undefined even if I wait 10 minutes before clicking my button which executes the code.
wrapper definitely exists on the page I navigate to before clicking my button. It is there in regular HMTL code. Not dynamically generated. I feel posting this page code would just confuse the question.
// manifest.json
{
"name": "Jams Dev Tools",
"version": "1.0",
"description": "Provides dev tools",
"background": {
"scripts": ["background.js"],
"persistent": true
},
... // icons are included here
"manifest_version": 2,
"web_accessible_resources": [
"debugTools.css",
"debugTools.js"
],
"permissions": [
"https://*/*",
"http://*/*",
"tabs",
"activeTab"
]
}
// debugTools.js
var theWrapper = document.getElementById("wrapper");
console.log(theWrapper.style.width);
// injectFiles.js
if(document.getElementById("debugJs") == undefined) {
// Inject Css
var debugJs = document.createElement('script');
var theSource = chrome.extension.getURL("debugTools.js");
debugJs.setAttribute( 'src', theSource );
debugJs.id = "debugJs";
document.body.appendChild(debugJs);
}
// background.js
chrome.browserAction.onClicked.addListener(function (tab) {
// for the current tab, inject the "inject.js" file & execute it
chrome.tabs.executeScript(tab.id, {
file: 'injectFiles.js'
});
});
Ok, so this was one of those times when you just can't see the wood for the trees. Thank you all for any help you have given. It turns out I'm an idiot. The problem can be summed up with the below snippet.
debug();
var theWrapper = document.getElementById("wrapper");
function debug() {
console.log(theWrapper.width);
}

chrome.storage between popup and browser action window

I'm writing a chrome extension and I want to manage all of the data/variables with chrome storage. From what I understand, I should be able to use chrome.storage across my extension.
I want to set something in browser_action script and then access it in the window created by the background script. The HTML and JS files all have corresponding names.
This is what I have tried with no luck:
//manifest.json
{
"manifest_version": 2,
"name": "extension",
"description": "my extension",
"version": "0.1",
"permissions": [
"tabs",
"storage"
],
"background": {
"scripts": ["background.js"],
"persistent": false
},
"browser_action": {
"default_icon": {
"38": "images/icon38.png"
},
"default_popup": "settings.html"
}
}
//background.js
chrome.windows.create({'url': chrome.extension.getURL("newPage.html"),'type': "detached_panel",'focused': true}, function(){
//created newPage.html which has newPage.js
});
//setting.js
document.addEventListener('DOMContentLoaded', function(){
chrome.storage.local.set({'enabled': 'TRUE'});
});
//newPage.js
chrome.storage.local.get('enabled', function(result){
document.getElementById("myId").innerHTML += "<br>script loaded... and status: " + result.enabled;
});
When I do this, newPage.html displays "script loaded... and status: undefined".
Even with it being asyncronous, the storage value should be populated on running the script a second time, right?
I may just be using this incorrectly. If that's the case, what's the correct way to set something with chrome storage to access in my new window?
Any help would be appreciated!
I think that your newPage.html is asking for the value of 'enabled' before it's been set by the event handler in settings.html, which only executes after you've actually opened the browser popup. So this is why it's undefined. Open the popup and you should see that it's defined.

Why does it seem that my Google Extension begins execution only when I'm observing background script console

I would like my Google Extension to start execution as soon as Google Chrome window is opened. I have the following code in my background.js :
if (window.Notification) {
setInterval( function() { callAutomate(); }, 60000 );
}
function callAutomate() {
// Code to automate hello-hello.com
}
The manifest file is as follows -
{
"name" : "Hello.co Extension",
"version" : "1.1",
"description" : "Say Hello",
"background" :
{
"scripts": ["background.js"],
"persistent": false
},
"page_action" :
{
"default_icon" : "hello-19.png",
"default_title": "Hello World",
"default_popup": "popup.html"
},
"content_scripts": [
{
"matches": ["https://www.hellohello.com/*"],
"js": [
"content.js",
"webDB.js"
]
}
],
"permissions": [
"tabs",
"storage",
"unlimitedStorage",
"webNavigation",
"notifications",
"https://www.hellohello.com/"
],
"options_page": "options.html",
"icons" : {
"48" : "hello-48.png",
"128" : "hello-128.png"
},
"manifest_version": 2,
"web_accessible_resources": [
"hello-48.png"
]
}
Here is my problem the callAutomate(); function seems to called only while I'm observing the console logs for background.js. However the expected behavior of the extension is to call the callAutomate(); function every one minute from the time Google Chrome window is opened.
Any help with explanatory code would be highly appreciated.
As explained in the Chrome extension documentation, there are 2 types of background pages:
persistent background page : always "opened"
event background page : "open and closed" as needed
You are using the second one, as specified with the "persistent": false in your manifest.json file,
so the background code will not execute itself when you normally load your page.
And I am pretty sure that when you are using the developer tool ("observing the console") on your background page, the page is "opened" and does not close while the console remains open.
By removing the "persistent": false your code will be executed.
But as suggested in the documentation, you should use event pages as much as possible so have a look at the lifetime documentation to see the different ways you can communicate with your background page and thus execute your desired code.
That is because of "persistent": false in the manifest.
This describes an Event page, that is, a page Chrome can unload at will if it is idle for more than a couple of seconds, only keeping track of registered event handlers.
Notes for Event pages explicitly mention:
If your extension uses window.setTimeout() or window.setInterval(), switch to using the alarms API instead. DOM-based timers won't be honored if the event page shuts down.
And if you open a Dev Tools window for the background page, it will NOT be unloaded, leading to your code executing properly.
You can switch to using chrome.alarms API, but before you do, carefully read the Event page documentation. You need to understand all the limitations: for instance, since the page is unloaded, all local state in variables is lost. If you need to persist state, you'll need to employ storage APIs.
If that is too complicated for your purposes, remove "persistent": false to revert to a normal Background page.

History search failing to execute in Chrome extension

I am in the process of writing an extension for Chrome to display the users 3 most visited sites. (Yes, I am aware that the "New Tab" page already does this) However, whenever I try to query the users history then it seems like the entire script shuts down.
My manifest files does contain:
{
"name": "Most Visited Sites Test",
"description": "Show your most visited sites",
"version": "1.0",
"background_page": "background.html",
"app": {
"launch": {
"web_url": "http://localhost/*"
}
},
"permissions": [
"tabs",
"history",
"unlimitedStorage",
"notifications"
],
"icons": {"128": "icon.png" },
"content_scripts": [
{
"matches": ["<all_urls>"],
"js": ["contentscript.js"]
}
]
}
So I believe this ought to give my background page the ability to use the history. However, my background page contains:
function onRequest(request, sender, sendResponse)
{
alert("Call 1");
var oneWeekAgo = //Code for getting last weeks date;
chrome.history.search({
'text': '',
'startTime': oneWeekAgo
},
function(historyItems)
{
// Do stuff...
});
alert("Call 2");
};
The request is sent from my contentscript.js
chrome.extension.sendRequest("foo");
When run, "Call 1" is shown but then nothing is done with the history and "Call 2" is never shown. What might be causing this? I apologize if this is a simple problem but this is my first attempt at a legitimate Chrome extension.
Opening console to see if there any errors is the first thing I always do (go to the Extensions tab and click on "background.html").
Your history call is correct, so maybe your last week calculation isn't? This is what works for me:
chrome.history.search({text: "", startTime:(new Date()).getTime()-7*24*3600*1000}, function(items) {
console.log(items);
});

Categories