Get url on page change - google-chrome-extension

I am trying to get the URL of the current page in the foreground tab from a Chrome extension.
I am able to do it, but it keeps displaying the alert over and over again. I just want it to show once each time a new page is loaded.
This is what I have right now, but it fires a bunch of times for each page load. I set the status to "complete" but that didn't seem to help.
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
chrome.tabs.query({'active': true, 'lastFocusedWindow': true, 'status': "complete"}, function (tabs) {
var url = tabs[0].url;
alert(url);
});
});
I don't know of any way to know when a new page was loaded without putting it into a tabs.onUpdated which fires constantly.

Related

chrome.tabs.onupdated.addlistener doesn't work on cached pages

chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (tab.url.indexOf('http') == '0' && changeInfo.status == 'complete') {
alert(JSON.stringify(changeInfo));
}
});
i have such background.js it nearly works always %99 but not %100
whenever i restart my browser and enter an already accessed web page when browser loads all contents from cache it doesn't fire this chrome.tabs event
but the interesting part is when i click same website from dial speed it doesn't load from cache and calls the "tabs." action
According to the docs https://developer.chrome.com/extensions/webNavigation
Not all navigating tabs correspond to actual tabs in Chrome's UI,
e.g., a tab that is being pre-rendered. Such tabs are not accessible
via the tabs API nor can you request information about them via
webNavigation.getFrame or webNavigation.getAllFrames. Once such a tab
is swapped in, an onTabReplaced event is fired and they become
accessible via these APIs.
and
If a navigation was triggered via Chrome Instant or Instant Pages, a
completely loaded page is swapped into the current tab. In that case,
an onTabReplaced event is fired.
Try using the chrome.webNavigation.onTabReplaced event to catch this:
chrome.webNavigation.onTabReplaced.addListener(function (details) {
chrome.tabs.get(details.tabId, function(tab) {
console.log(tab.url);
});
});
Note: You'll need the "webNavigation" permission in the chrome extension manifest:
{
"name": "My extension",
...
"permissions": [
"webNavigation"
],
...
}
I tested this with 25 open tabs using:
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab){
console.log("update: "+JSON.stringify(changeInfo));
});
On restarting my browser I received 25 "loading" events, but only 23 "completes".
On restarting my browser a second time I received 25 "loading" events, but only 22 "completes".
I don't think changeInfo.status == 'complete' will always follow a pageload, especially after restarting.
consider using chrome.tabs.query() right after your extension loads instead.
chrome.tabs.query({}, function(tabs) {
for(var i=0;i<tabs.length;i++){
if (tabs[i].url.indexOf('http') == '0') {
dostuff();
}
}
});

chrome extension message passing between extension-inner page and background script

I use a extension inner page(chrome-extension://) to request permission, and send result to background.
in extension inner page:
btn.addEventListener('click', function(event) {
event.preventDefault();
chrome.permissions.request({
permissions: permissions,
origins: origin
}, function(granted) {
chrome.runtime.sendMessage({route: '/permissionRequest', data: {command: 'Response', result: granted}}, function(){});
});
}, false);
It looks well.But when I click the button, it open a new tab, url like chrome-extension://.../authorizehtml?undefined. The message send.
I don't know why it open a new tab like that.
And the, I found, if I change the key name 'data' to other name, it never open new tab.The official document don't talk about it.
I hava no idea about it.

Content script programatically injected by Chrome extension background page got injected multiple times

I have a chrome extension, say it injects content script a.js into urls matching 'http://example.com/*'. Then when I click some page elements in example.com page, a.js would ask background to create a new tab with defined url, and programatically inject a content script b.js into the new tab, you can check the code down:
chrome.tabs.create({
url: 'http://example.com'
}, function (tab) {
var taskTab = tab.id;
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (tabId === taskTab) {
chrome.tabs.executeScript(taskTab, {
file: 'scripts/b.js'
});
}
});
});
The problem is, the content script b.js would get injected into the new tab for a lot times. I also tried the chrome.webNavigation, the result is the same.
So if I want the b.js got injected into the new tab for only one time? how can i make it?
By the way, the b.js is actually a remote file, I load it into page by jQuery, here to simplify the question I make it a local file.
Thanks very much.
update
I had figure out what's going on with my code.
First, it's wrong for me to wrap the onUpdated event listener inside the create callback, every time I create a new tab, close it, create it again, the event listener would got bind one more time. The more, the more.
Second, #Xan was right, I could do it by checking changeInfo.status. So the code would be:
var taskTab;
chrome.tabs.create({
url: 'http://example.com'
}, function (tab) {
taskTab = tab.id;
});
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
if (changeInfo.status === 'complete'){
if (tabId === taskTab) {
chrome.tabs.executeScript(taskTab, {
file: 'scripts/b.js'
});
}
}
});
And that b.js would only be injected for once, no matter it's a local file or a remote file loaded by jQuery.
onUpdated event can fire for a lot of reasons:
object changeInfo:
Lists the changes to the state of the tab that was updated.
string (optional) status: The status of the tab. Can be either loading or complete.
string (optional) url: The tab's URL if it has changed.
boolean (optional) pinned: The tab's new pinned state.
string (optional) favIconUrl: The tab's new favicon URL.
You might want to filter onUpdated events by those properties of changeInfo
Failsafe method: when you inject a second script, set some guard variable that is checked for undefined before you execute the rest of the script. Any other attempts to inject the script will be in the same context and will see the variable set. Kind of like C's #ifndef includes.

Fetching Canvas based graph in Chrome extension

I want to fetch HTML of this graph but I don't see how to do it? Is there anyway to fetch it or do I need to use iFrame to load this page?
If you are on the page, and have the chrome extension loaded, you can use a content script like so:
Background.js:
chrome.tabs.query({'active': true, 'windowId': chrome.windows.WINDOW_ID_CURRENT},function(tabs){
var tab = tabs[0];
if(tab.url === "your url"){
chrome.tabs.executeScript(null,{file:"contentscript.js"});
}
});
contentscript.js
window.addEventListener("DOMContentLoaded",function(){
var graph = document.getElementsByTagName("canvas")[0];
//do stuff
});
You can either do stuff with graph in the content script, or pass it back to the background page with message passing

Message isn't passed between background.html and popup.html

I'm trying to pass data that is saved in sessionStorage from background.html to popup.html
background.html:
chrome.extension.onRequest.addListener(function(request, sender, sendResponse) {
data = sessionStorage.getItem(request.tabId);
alert(data);
sendResponse({ data: data });
});
and in popup.html:
chrome.tabs.getSelected(null, function(tab) {
chrome.extension.sendRequest({ tabId: tab.id }, function(response) {
alert(response.data);
});
});
The popup is opened by a pageAction button, when I click the button I get an alert box with "null" on the popup and then an alert box with the data that I stored in sessionStorage on the background!
Any ideas how to fix this?
You don't need to use message/request APIs. I think this response may help you.
You also don't need sessionStorage, just store your data in a global variable of the background page. It will persist until the browser is closed or until the extension is restarted.
So, here is how I would rewrite your code:
background.html:
var data = {}; // Object storing data indexed by tab id
and in popup.html:
chrome.tabs.getSelected(null, function(tab) {
alert(chrome.extension.getBackgroundPage().data[tab.id]);
});
Note that chrome.tabs.getSelected is deprecated since Chrome 16, so popup code should be:
chrome.windows.getCurrent(function(win) {
chrome.tabs.query({'windowId': win.id, 'active': true}, function(tabArray) {
alert(chrome.extension.getBackgroundPage().data[tabArray[0].id]);
});
});
Well, I've done something dumb.
I inspected the background page by opening chrome-extension://[extension-id]/background.html in a tab instead of clicking on "inspect active views: background.html" in the extensions management page. This caused the tab to catch the request and call sendResponse, but the popup expected the REAL background page to call sendResponse (and if I understand Google's documentation regarding message passing, the fact that sendResponse was called twice is root of the problem, because the first call clears the request object)

Resources