why the active tabs was undefined when send message from backend to content script in google chrome extension v3 - google-chrome-extension

I am tried to send message from background in google chrome extension v3, this is the background message send code looks like:
export function sendMessageToContent(message: MessageBase) {
debugger
chrome.tabs.query({active:true,currentWindow:true},function(tabs){
var activeTab = tabs[0];
if(activeTab && activeTab.id !== undefined){
chrome.tabs.sendMessage(activeTab.id, {"message": "clicked_browser_action"});
}
});
}
when I get the current active tab, the tabs was return undefined, why did this happen? I am sure there contains active tabs in google chrome broswer, what should I do to fix this problem? This is the debug view:

Related

Chrome Extension not working after Chrome 73 but only if loaded from the store

I have a Chrome extension (https://chrome.google.com/webstore/detail/apsic-xbench-extension-fo/nhadbgflnognogbicnbeepnbpehlocgc) that suddenly stopped working right after the Chrome 73 update.
The symptom is that if I go to the page where the extension is designed to work (https://translate.google.com/toolkit) and I click on the extension icon, instead of running the background page code, the pop-up menu for the extension appears (as if I had right-clicked the icon).
However, if I load the exact same code locally (not from the store), the Chrome extension runs fine.
The background page console for the extension loaded from the store does not seem to issue any error. If I place a breakpoint for the first line in the onClicked listener for the page action, it does not stop there for the Chrome store extension (and the breakpoint works fine for the extension loaded locally).
Why do I get different behaviors if I load the extension from the Chrome store or I load it locally?
In Chrome 72, the extension worked fine.
Answering own question: I tracked down the issue. It turned out that if the Chrome extension was installed from the Chrome store using Chrome 72, then it did not work right after the update to Chrome 73.
However, if after Chrome 73 is updated, you remove the extension and add it again from the Chrome store, then the Chrome extension works again. Strange but true.
Chrome 73 inject some new security. Just try to move your xHTTP requests to your background script with chrome.runtime.sendMessage and get response with SendResponse callback.
In content or popup script replace ajax with :
chrome.runtime.sendMessage(
{ action: "check", data: {/* params for url */}},
// callback with url response
function(response) {
if( response.success ) {
var myDataFromUrl = response.data;
...
} else {
console.log('Error with `check`,', response.data);
}
}
);
From background script:
chrome.runtime.onMessage.addListener(
function(request, sender, sendResponse) {
var url = 'https://mysyte.com/';
if(request.action === 'check' ) {
url = url + 'check'
ajax( url, request.data,
success: function( d ) {
sendResponse({success: true, data: d});
},
error : function( d ) {
sendResponse({success: false, data: d});
}
);
}
});
function ajax( url, params, cbSuccess, cbError ) { ... }

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
}
}
})

Chrome extension detect Google search refresh

How can my content script detect a refresh of Google's search?
I believe it is an AJAX reload of the page and not a "real" refresh, so my events won't detect the refresh.
Is it possible to detect it somehow in both a Google Chrome extension and a Firefox WebExtensions add-on?
Google search is a dynamically updated page. Several well-known methods exist to detect an update: MutationObserver, timer-based approach (see waitForKeyElements wrapper), and an event used by the site like pjax:end on GitHub.
Luckily, Google Search in Chrome browser uses message event, so here's our content script:
window.addEventListener('message', function onMessage(e) {
// console.log(e);
if (typeof e.data === 'object' && e.data.type === 'sr') {
onSearchUpdated();
}
});
function onSearchUpdated() {
document.getElementById('resultStats').style.backgroundColor = 'yellow';
}
This method relies on an undocumented site feature which doesn't work in Firefox, for example.
A more reliable crossbrowser method available to Chrome extensions and WebExtensions is to monitor page url changes because Google Search results page always updates its URL hash part. We'll need a background/event page, chrome.tabs.onUpdated listener, and messaging:
background.js
var rxGoogleSearch = /^https?:\/\/(www\.)?google\.(com|\w\w(\.\w\w)?)\/.*?[?#&]q=/;
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (rxGoogleSearch.test(changeInfo.url)) {
chrome.tabs.sendMessage(tabId, 'url-update');
}
});
content.js
chrome.runtime.onMessage.addListener(function(msg, sender, sendResponse) {
if (msg === 'url-update') {
onSearchUpdated();
}
});
function onSearchUpdated() {
document.getElementById('resultStats').style.backgroundColor = 'yellow';
}
manifest.json: background/event page and content script declarations, "tabs" permission.

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