chrome.tabs problems with chrome.tabs.update and chrome.tabs.executeScript - google-chrome

I want to write a small chrome extension which shall take an information from webpage A (current webpage), update the tab to webpage B and then inject code into webpage B. unfortunaetelly the following code is updating the webpage to B but injecting the code to webpage A. The code in background.html is:
chrome.tabs.update(tab.id,{url: "http://B.com"});
chrome.tabs.executeScript(tab.id, {file: "inject_into_B.com.js"}); /* injections goes misleadingly to webpage A*/

You want something like this:
chrome.tabs.update(tab.id, {url: request.url, active: true}, function(tab1) {
// add listener so callback executes only if page loaded. otherwise calls instantly
var listener = function(tabId, changeInfo, tab) {
if (tabId == tab1.id && changeInfo.status === 'complete') {
// remove listener, so only run once
chrome.tabs.onUpdated.removeListener(listener);
// do stuff
}
}
chrome.tabs.onUpdated.addListener(listener);
});

chrome.tabs.update is asynchronous call (like pretty much all others), so if you want to run those commands in order you need to use a callback function:
chrome.tabs.update(tab.id,{url: "http://B.com"}, function(tab) {
chrome.tabs.executeScript(tab.id, {file: "inject_into_B.com.js"});
});

Related

Communication between page and extension

i develop my first chrome extension.
I try to call the page from my default_popup.
I try with the chrome.runtime.onMessage.addListener and the chrome.runtime.sendMessage but that do not work.
I read this page https://developer.chrome.com/apps/messaging, but i can't figure out where to place correctly my Listiner.
I need when i open the "default popup", call an event in the page and return something to the "default_popup" came from the page.
More explication :
Actually i have a content.js in this content.js i am able to call the background.js by calling the chrome.runtime.sendMessage but it's call to fast.
The DOM of the page have not enought time to load. My content.js inject some .js file in the webpage to interact with the page.
It's there a way i can call the crhome.extension.sendMessage from the injected page ?
Any suggestion ?
Ok i found it.
We can register in the background.js an event
chrome.runtime.onMessageExternal.addListener(
function (request, sender, sendResponse) {
debugger;
if (sender.url == blacklistedWebsite)
return; // don't allow this web page access
if (request.openUrlInEditor)
openUrl(request.openUrlInEditor);
});
You need to put in the manifest the right rules
"externally_connectable": {
"matches": ["*://*.example.com/*"]
}
After that from your injected page :
chrome.runtime.sendMessage(extensionID, { openUrlInEditor: "test" },
function (response) {
debugger;
if (!response.success)
handleError("est");
});

chrome extension API for refreshing the page

Is there an API to programmatically refresh the current tab from inside a browser action button? I have background page configured, which attaches a listener via:
chrome.browserAction.onClicked.addListener(function(tab) { ... });
So the callback function retrieves a reference to the tab that it was clicked from, but I don't see an API anywhere to refresh/reload that tab.
I think what you're looking for is:
chrome.tabs.reload(integer tabId, object reloadProperties, function callback)
Check out tabs API() documentation for more information.
The API for chrome.tabs.getSelected(), which the accepted answer uses, has been deprecated. You should instead get the current tab and reload it using something like the following:
chrome.tabs.query({active: true, currentWindow: true}, function (arrayOfTabs) {
var code = 'window.location.reload();';
chrome.tabs.executeScript(arrayOfTabs[0].id, {code: code});
});
Or perhaps:
chrome.tabs.query({active: true, currentWindow: true}, function (arrayOfTabs) {
chrome.tabs.reload(arrayOfTabs[0].id);
});
I had no real luck with the second version, though other answers seem to suggest it should work. The API seems to suggest that, too.
I recommend using chrome.tabs.executeScript to inject javascript that calls window.location.reload() into the current tab. Something like:
chrome.tabs.getSelected(null, function(tab) {
var code = 'window.location.reload();';
chrome.tabs.executeScript(tab.id, {code: code});
});
Reference here
More specifically:
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.reload(tab.id);
});
You can also use this:
chrome.tabs.reload(function(){});
reload function params: integer tabId, object reloadProperties,
function callback
Reference: http://developer.chrome.com/extensions/tabs.html#method-reload
if you want to reload all the tabs which have loaded completely and are active in their window
chrome.tabs.query({status:'complete'}, (tabs)=>{
tabs.forEach((tab)=>{
if(tab.url){
chrome.tabs.update(tab.id,{url: tab.url});
}
});
});
you can change the parameter object to fetch only active tabs as {status:'complete', active: true} refer to query api of chrome extensions
Reason for not using chrome.tabs.reload :
If the tab properties especially the tab.url have not changed, tab does not reload. If you want to force reload every time, it is better to update the tab URL with its own tab.url which sends the event of the change in property and tab automatically reloads.

Chrome extension: how to constantly check URLs on new tabs and then respond with an action for certain URLs?

Hi—I'm not a student or a programmer by trade, but I'm trying to knock up a quick prototype to get an idea across. I've cobbled together some code from other StackOverflow questions, and I've almost got what I need, but I'm having trouble with one thing: the extension will run exactly once, but no more, until I refresh the extension via chrome://extensions. I'm guessing there's something wrong with the element of this program that listens for a new URL, but I can't figure out how to keep that element listening constantly. This code runs in background.js right now, though I've also tried it in background.html.
Basically, I'd like the extension to check the URL of a tab any time the user visits a new page (either by typing the URL herself or clicking through to one), and, if the URL appears in the plugin's internal URL list, to pop up a short notification. I have this so far:
// Called when the url of a tab changes.
// So we can notify users
var notification = webkitNotifications.createNotification(
'48.png',
'Alert!'
);
// Called when the url of a tab changes.
function checkForValidUrl(tab) {
// Compare with a the URL
if (tab.url.match(/google/)) {
//then
notification.show();
}
};
// Listen for any changes to the URL of any tab.
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status == "loading") {
checkForValidUrl(tab);
}
});
chrome.tabs.onSelectionChanged.addListener(function(tabId, selectInfo){
chrome.tabs.getSelected(null, function(tab){
checkForValidUrl(tab);
});
});
I fixed this after hacking it around a little bit -- I don't really have the vocabulary to explain what I did but I thought I'd post the code in case someone else has the same (simple) problem later.
function checkForValidUrl(tabId, changeInfo, tab) {
var notification = webkitNotifications.createNotification(
'48.png',
'Alert!',
'Watch out for your privacy!'
);
// Compare with the URL
if (tab.url.match(/google/)) {
//then
notification.show();
}
};
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
if(changeInfo.status == "loading") {
checkForValidUrl(tabId, changeInfo, tab);
}
});

Open a "Help" page after Chrome extension is installed first time

I am new to Chrome extension. I have a question about how to make the extension to open a "Help" page automatically after installation. Currently, I am able to check whether the extension is running the first time or not by saving a value into localStorage. But this checking is only carried out when using click the icon on the tool bar. Just wondering if there is a way that likes FF extension which uses the javascript in to open a help page after the installation. Thanks.
Edit:
Thanks for the answer from davgothic. I have solved this problem.
I have another question about the popup. My extension checks the url of current tab,
if OK(url){
//open a tab and do something
}
else{
//display popup
}
Is it possible to show the popup in this way?
Check this updated and most reliable solution provided by Chrome: chrome.runtime Event
chrome.runtime.onInstalled.addListener(function (object) {
let externalUrl = "http://yoursite.com/";
let internalUrl = chrome.runtime.getURL("views/onboarding.html");
if (object.reason === chrome.runtime.OnInstalledReason.INSTALL) {
chrome.tabs.create({ url: externalUrl }, function (tab) {
console.log("New tab launched with http://yoursite.com/");
});
}
});
Add this to your background.js I mean the the page you defined on manifest like following,
....
"background": {
"scripts": ["background.js"],
"persistent": false
}
...
UPDATE: This method is no longer recommended. Please see Nuhil's more recent answer below.
I believe what you need to do is put something like this into a script in the <head> section of your extension's background page, e.g. background.html
function install_notice() {
if (localStorage.getItem('install_time'))
return;
var now = new Date().getTime();
localStorage.setItem('install_time', now);
chrome.tabs.create({url: "installed.html"});
}
install_notice();
As of now (Aug 2022) the right way to execute code on first install or update of an extension using Manifest V3 is by using the runtime.onInstalled event.
This event is documented here: https://developer.chrome.com/extensions/runtime#event-onInstalled
There is one example for this exact case in the docs now:
https://developer.chrome.com/docs/extensions/reference/tabs/#opening-an-extension-page-in-a-new-tab
Note: This example above is wrong as the callback function parameter is Object with the key reason and not reason directly.
And another example here (this one is correct but does not open a tab):
https://developer.chrome.com/docs/extensions/reference/runtime/#example-uninstall-url
chrome.runtime.onInstalled.addListener((details) => {
if (details.reason === chrome.runtime.OnInstalledReason.INSTALL) {
// Code to be executed on first install
// eg. open a tab with a url
chrome.tabs.create({
url: "https://google.com"
});
} else if (details.reason === chrome.runtime.OnInstalledReason.UPDATE) {
// When extension is updated
} else if (details.reason === chrome.runtime.OnInstalledReason.CHROME_UPDATE) {
// When browser is updated
} else if (details.reason === chrome.runtime.OnInstalledReason.SHARED_MODULE_UPDATE) {
// When a shared module is updated
}
});
This code can be added to a background service worker: https://developer.chrome.com/docs/extensions/mv3/migrating_to_service_workers/
It would be better to place a "version" number so you can know when an extension is updated or installed.
It has been answered here:
Detect Chrome extension first run / update
All you need to do is adding the snippet below to your background.js file
chrome.runtime.onInstalled.addListener(function (object) {
chrome.tabs.create({url: `chrome-extension://${chrome.runtime.id}/options.html`}, function (tab) {
console.log("options page opened");
});
});

about sending messages among bg.html, popup.html and contentscript.js

In my extension, when a button named mybuttonl in popup.html is
clicked, it sends a message "getvar" to contentscript.js, which in turn sends a message "I want var1" to background.html to get an object named var1. (A button named mybutton2 is set up likewise, except it gets the var2 object when clicked).
How should I implement this?
What's more, I am a little confused about the chrome.extension.onRequest.addListener and chrome.extension.sendRequest methods. Could someone please explain?
onRequest.addListener and sendRequest is part of Chrome's extension Messaging. Which is located here http://developer.chrome.com/extensions/messaging.html
Basically, you listen for a request using "onRequest.addListener" that someone sent from triggering a "sendRequest".
In your case, you put a "onRequest.addListener" in your content script to listen for requests coming from the Popup (using sendRequest). And from your content script, you can return a response back to your popup to handle what is happening. In your popup, you have direct access to the background page using chrome.extension.getBackgroundPage().
If you want your content script to communicate to your background page as well (which is not needed since your making stuff more complicated), you can add a "onRequest.addListener" to your background page which only listens for requests coming from the content script. To do that, Message Passing explains it perfectly. "sender.tab" if true, is a content script.
The example below (untested) shows what I mean about message passing. Remember, try to keep stuff simple, not complex.
Example
Popup.html
chrome.tabs.getSelected(null, function(tab) {
chrome.tabs.sendRequest(tab.id, {method: "fromPopup", tabid: tab.id}, function(response) {
console.log(response.data);
});
});
ContentScript.js
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
if (request.method == "fromPopup") {
// Send JSON data back to Popup.
sendResponse({data: "from Content Script to Popup"});
// Send JSON data to background page.
chrome.extension.sendRequest({method: "fromContentScript"}, function(response) {
console.log(response.data);
});
} else {
sendResponse({}); // snub them.
}
});
BackgroundPage.html
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
// From content script.
if (sender.tab) {
if (request.method == "fromContentScript")
sendResponse({data: "Response from Background Page"});
else
sendResponse({}); // snub them.
}
});