Chrome send data from background page to browser action - google-chrome

So I have a background page that listens in on tab changes
var tabHandler={
onTabUpdate:function(tabId, changeInfo, tab){
},
tabChanged:function(activeInfo) {
function tabChanged(tab){
var parser = document.createElement('a');//To extract the hostname, we create dom element
parser.href = tab.url;
var regex=/^(www\.)?([^\.]+)/
var matches=regex.exec(parser.hostname)//This gives us the hostname, we extract the website name
var website=matches[2];
var data=getDataForWebsite(website);//Data is a json array
//TRANSFER 'data' to Browser popup so that it can be displayed.
}
chrome.tabs.get(activeInfo.tabId,tabChanged);
},
init:function(){
chrome.tabs.onActivated.addListener(this.tabChanged);
}
}
tabHandler.init();
This piece of code gets the nam of the website and fetches a list of parameters based on the website. Now that I have the data, I am wondering how to show this data in the browser action popup. I want to pass this data to the browser Action adn then parse it there to replace existing content. How do I do that?

One thing you need to remember is that popup pages don't live while the popup is closed (unlike background pages). That means that you can't just transfer the data to the popup page since it doesn't exist anywhere at all time. Instead, whenever the popup is opened, the first thing you need to do is request the info from storage and display it however you want.
In your background page, when you receive the data for the current domain, you should save it somewhere: that could be in localStorage, or sessionStorage, or chrome.storage (check the documentation to see which one would make more sense in your use-case). You would want to save it indexed on the domain most likely, so that you can have the info saved from all the open tabs if needed.
Then whenever the popup is open, get the data for the current tab from the storage you used, and display the data in whichever way you want.

You can directly access background window from popup by chrome.extension.getBackgroundPage().
You can also directly access popup's window from background when it is open by chrome.extension.getViews({type:'popup'})[0].
Using these methods you can implement a messaging between popup and background.

Related

Check if a new if a new tab was opened with puppeteer

I am using Puppeteer to gather a list of companies that hire remotely. The page I am trying to collect the data from has a call to action that is not an <a href="" blank"_tab", but a <button></button>. The button doesn't have any data attribute either, that gives a hint as to what the URL of the page that gets opened in a new tab, when I click the button, is. I am now trying to find a way to catch the opening of the new tab, by clicking the said button, to then fetch the URL of the newly opened tab. Is this possible with puppeteer?
The solution is to extract all pages of the browser via the browser.pages() method call.
In your puppeteer project you always start by initialising the browser. The puppeteer virtual browser does contain the method pages(). Usage of pages().
What you have to do now: At first get the current url of the current page you are on. Then stream the result of the browser.pages() method. While streaming the array you can just get the index of your current tab. The tab you just opened using the button is the page with that index + 1 (the next element in the array)...
How to handle multiple tabs
Puppeteer Documentation about pages()

Is there a certain page I should be fetching my API data from within my Chrome Extension Project?

I am making a chrome extension that fetched JSON data from CoinMarketCap.com API and currently I have it running in the background script. I'm not 100% sure what the purpose of the page is really. I was wondering if I could simply fetch the data from the popup script after I click a button within my popup?
Each button represents a different coin. I basically want to get the price of a chosen coin and display it on whatever page the user is on when they double click the coin in a text article. Eventually I want to make it so you can double click any coin and have it show a live price conversion while you're on the web-page.
The point of a background page is to be always available (running if persistent: true, woken up / recreated for registered events if persistent: false).
A popup's lifetime is determined by its visibility. The moment the user clicks away and closes it, the page is closed (as if the tab with it was closed), so it can no longer process any events and its state is lost.
As long as:
The data you need fetched is to be received/processed while the popup is open
Any state you need to persist between popups being shown can be stored in chrome.storage
Then you don't need the background page to do the fetching. Popup page has the same level of access to Chrome APIs.
However, consider this scenario: suppose you want the data to be ready as soon as popup is opened (at least, you want it to be fresher than "since last time"). You may want to do periodic updates even while the popup is closed to refresh the data. You can only do that reliably with a background page (and, say, chrome.alarms API). Then you can cache the latest available data in chrome.storage and use that in the popup.
Background pages have their uses as some code that can run periodically regardless of user actions, and to be able to always react to events.
According to Changes to Cross-Origin Requests in Chrome Extension Content Scripts now you have to do your fetches in Background Script. Not in Content Script.

How can I open my extension's pop-up with JavaScript?

I am trying to write a JavaScript function that will open my extension like when the extension icon is clicked. I know how to open my extension in a new tab:
var url = "chrome-extension://kelodmiboakdjlbcdfoceeiafckgojel/login.html";
window.open(url);
But I want to open a pop-up in the upper right corner of the browser, like when the extension icon is clicked.
The Chromium dev team has explicitly said they will not enable this functionality. See Feature request: open extension popup bubble programmatically :
The philosophy for browser and page action popups is that they must be triggered by user action. Our suggestion is to use the new html notifications feature...
Desktop notifications can be used progammatically to present the user with a small HTML page much like your popup. It's not a perfect substitution, but it might provide the type of functionality you need.
Chrome team did create a method to open the popup programmatically, but it's only enabled as a private API, and plans to make it generally available have stalled due to security concerns.
So, as of March 2018 as of now, you still can't do it.
Short answer is that you cannot open browserAction programmatically. But you can create a dialog with your content script which emulates your browserAction and display that isntead (programmatically). However you won't be able to access your extension's background page from this popup directly as you can from your popup.html. You will have to pass message instead to your extension.
As mentioned there is no public API for this.
One workaround I have come up with is launching the extension as an iframe inside a content script with a button click. Whereby the background script emits the extension URL to the content script to be set as the iframe's src, something like below.
background.js
browser.runtime.onMessage.addListener((request) => {
if (request.open) {
return new Promise(resolve => {
chrome.browserAction.getPopup({}, (popup) => {
return resolve(popup)
})
})
}
})
content-scipt.js
const i = document.createElement('iframe')
const b = document.createElement('button')
const p = document.getElementById('some-id')
b.innerHTML = 'Open'
b.addEventListener('click', (evt) => {
evt.preventDefault()
chrome.runtime.sendMessage({ open: true }, (response) => {
i.src = response
p.appendChild(i)
})
})
p.appendChild(b)
This opens the extension in the DOM of the page the script is running on. You will also need to add the below to the manifest.
manifest.json
....
"web_accessible_resources": [
"popup.html"
]
....
You could emulate the popup by displaying a fixed html element on the page in the same location the popup would be and style it to look like the popup.
I had the same requirement: When the user clicks on the extension icon a small popup should open. In my case, I was writing an extension which will give updates on selective stocks whenever the icon is clicked. This is how my popup looked.
If you were having the same requirement then please read the answer below.
This is how my manifest.json file looked.
All the heavy lifting was handled by manifest.json file only. There is a section browser_action inside which there is a key called default_popup, just put the name of the HTML file that you want the popup to display.
I wanted my extension to work on all the pages that's why I added the attribute matches under content_scripts. I really didn't need to put the jquery file jquery-3.2.1.js inside the js array but the extension manager was not allowing me to keep that array empty.
Hope this helps, do comment if you have any doubt regarding the answer.

Chrome Extension Local Storage: Background.html doesn't have access to localstorage?

Writing and reading from LocalStorage is working fine from my popup and tab. However, when I attempt to add a value from my background page, it doesn't seem to write at all. I'm viewing local storage in Chrome Developer Tools by refreshing and looking for the value to show.
In the following example code for background.html 'lastId' is displayed correctly in the alert when a new bookmark is added. However, the value is not stored. Additionally, the request for a known value appears to fail with no alert displaying. (Results are the same attempting both syntaxes shown below.)
<html>
<script>
// Grab the id of newly created bookmarks
chrome.bookmarks.onCreated.addListener(function(id) {
var lastId = id;
alert(lastId);
localStorage['lastId'] = lastId;
var testvalue = localStorage['309'];
alert(testvalue);
localStorage.setItem('lastId', lastId);
var testvalue2 = localStorage.getItem('309');
alert(testvalue2);
});
</script>
</html>
I keep thinking I must just be missing some small syntax issue or something but can't see anything. If my manifest declaration was incorrect I don't think the alert would work for the id. Stumped...
UPDATE: Turns out that you have to force reload of the extension on updates to background pages since they are persistent in browser memory when opened. That is why my saved code appeared not to work. It wasn't refreshed and I am duly embarrassed.
Hm, I can think about couple things.
You say that it works in a tab and a popup. This is very strange because it shouldn't (if by tab you mean content script). Content scripts are able to access only localStorage that belongs to a site they are injected. Popup, background, option pages, and any othe page from extension's folder can only access extension's own localStorage. Those two local storages and completely separated. So maybe you are inspecting wrong localStorage?
To see extension's own localStorage you need to inspect background or popup page and check resources tab in the inspector. To inspect site or content script localStorage you need to open regular inspector on the page.
Second moment is your localStorage assignment might be not what you are expecting.
If you run:
var lastId = 5;
localStorage['lastId'] = lastId;
you will get value 5 assigned to lastId property. So to read written value you need to run:
alert(localStorage['lastId']); //not localStorage['5']
If you want to store arrays then you would need to serialize/unserialize them through JSON as localStorage can store only strings.

chrome extension popup and background ajax

I have a requirement where the background.html continous to update every 10 minutes and when I click on the popup it should trigger the background to update immediately and show the result in the popup.
I have the background updating using ajax working and I have the popup trigger the background to make an immediate update using ajax working as well. However, I am stuck on how to display the latest result in the popup...how can I tell when the background ajax call is complete and show the latest result in the popup?
thanks
Well, if you want to listen for changes on the Background Page, you have two ways to do what you want.
In your Popup, you can register chrome.extension.onRequest.addListener in your Popup page, and in your background page you can chrome.extension.sendRequest when you get stuff updated.
You have direct access to the Popup DOM, you can get an instance from chrome.extension.getViews({type:'popup'}), and once you get that, you can just call a method in that DOM. From the popup, you can access the background page easily too with chrome.extension.getBackgroundPage(). For both cases, you get a DOMWindow returned.
I personally would use #2 because you belong in the same extension process, you do not need to communicate to an injected Content Script.
var popups = chrome.extension.getViews({type: "popup"});
if (popups.length != 0) {
var popup = popups[0];
popup.doSomething();
}
Hope this helps.