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

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.

Related

load last viewed page on chrome extension startup

I'm developing my first chrome extension and I'm stuck with a "session restore" problem. At the begging of the developement when a user log in to my extension and close the popup, when he open the plugin again he had to login again.
I've used chrome.storage.sync to be able to save the session infomation to make the user to be still logged in and if he close the plugin, and his session is still active he will be redirected to the welcome page. But how can I check at the extension's startup in what page of the plugin the user was and bring him back to that page?
For example, if a user is logged and was on the "choose a book" section, how can i make the plugin open at "choose a book" section and not in "welcome" section?
Angular 2 for client side
NodeJs for server side
Consider that the session object is something like:
{
logged: true,
last_section: 'books'
}
When the user visits the books section, save it.
// this code goes inside some listener for visiting a section
chrome.storage.sync.get('session', function (items) {
const session = items.session || {}
session.last_section = 'books'
chrome.storage.sync.set({ session })
})
At the beginning of the popup script, you can simply call chrome.storage.sync.get to get the last session object state.
chrome.storage.sync.get('session', function (items) {
const session = items.session
if (session && session.logged) {
if (session.last_section === 'books') {
// render books section
}
if (session.last_section === 'welcome') {
// render welcome section
}
}
})

Get url on page change

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.

chrome.tabs.executeScript bug on F5?

Background page:
chrome.tabs.create({ url: 'http://google.com' }, tab => {
chrome.tabs.executeScript({ code: '2+2;' }, (r) => {
console.log(`url: ${tab.url}, result: ${r[0]}`);
});
});
I open background page to see output:
url: http://google.com/, result: 4
Looks good, but now I press F5 or Ctrl+F5:
Unchecked runtime.lastError while running tabs.executeScript: Cannot access contents of url "chrome-devtools://devtools/bundled/inspector.html?&remoteBase=https://chrom…om/serve_file/#e8926f681fbb840b4f389e7e692343d4505722ce/&dockSide=undocked". Extension manifest must request permission to access this host.
at Object.callback (chrome-extension://laaoiaaacchfpefjhklpmnfjbeamjfli/background.js:2:15)
In 'manifest.json' I have <all_urls> permission.
When the first parameter, tabId, of chrome.tabs.executeScript is omitted the code is injected into the active tab of the active window. In your case the active window is the devtools debugger of the background page and it doesn't allow injection of code.
Specify tabId explicitly: chrome.tabs.executeScript(tab.id, { code: .......

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.

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