chrome extension popup and background ajax - google-chrome

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.

Related

Changing chrome extension html using chrome storage event listener

With this code I want to create an event listener for whenever chrome storage updates.
I want 2 things to happen when the event listener is triggered:
The code will console log the updated values. This part works.
I want the HTML for the extension (the document that opens in the corner when you click the icon) to update and render the data value that is in chrome storage. This is that part I need help with.
chrome.storage.onChanged.addListener(function(changes, namespace) {
//part 1
console.log('New data type is %s. New value is %s',
changes['type'].newValue, changes['data'].newValue)
//part 2
document.getElementById('output').innerHTML =
changes['data'].newValue
});
I realize that calling "document" inside the function doesn't make sense, but I'm unsure how to move forward to get it to render in the extension's HTML.
I tried creating an event listener for when the context menu is accessed (users can update the chrome storage but clicking a button in the context menu) but I couldn't get it to work. Also the event should trigger when chrome storage is updated, not when the context menu is simply accessed.
Right now I get this error:
Error in event handler: TypeError: Cannot set property 'innerHTML' of null
(There is an element with id 'output', so that isn't the problem)
Thanks for your help!
The background script runs in a separate hidden background page. It's not related to the browserAction or pageAction popup page, it doesn't have any of the popup page elements, its DOM is empty except for the auto-generated script tags of the background scripts.
The popup is also a separate page and just like any normal page its environment/DOM exists only when the page is shown. You can't modify it when it's not shown. You can't show it from your code in general case either.
Solution 1
Put that onChanged listener in popup.js script that's loaded in your popup.html (declared as "browser_action": {"default_popup":"popup.html"} in your manifest.json) using the standard <script src="popup.js"></script> tag. It will update the popup page if it's shown, and to display the current values when the popup opens read them with chrome.storage.local.get or chrome.storage.sync.get depending on which storage you're using in your extension.
Solution 2
Use chrome.notifications API to show a small notification at the bottom of the screen, see also the official demo extensions.
Solution 3
Use chrome.browserAction.setBadgeText to display short text like a temperature right under the extension icon. Don't forget to declare at least "browser_action": {} in your manifest.json.

Chrome send data from background page to browser action

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.

Creating a notification from within a notification

I'm creating an extension for Chrome, and one of the functionalities included is the ability for the end user to add people as contacts.
Currently, the contact is saved to the database via AJAX, after which a desktop notification is displayed telling the user that the deed has been done.
However, I would want to first ask the user if he's sure he wants to do that. So I got the mad idea of wanting to create a new notification from within a notification.
So first, the confirmation HTML notification would be created from the background.html, and displayed. It contains a button, and upon clicking it, it should run the AJAX function and create a second notification, containing the feedback.
However, I seem to be unable to do this. I can't run createNotification() from the notification, sendRequest() doesn't seem to go through neither, and I can't use the onClose listener from background.html, because I want to differentiate between clicking the "Yes" button and the "No" button.
Is there any way I can do this? And if not, how should the confirmation dialog be implemented instead?
Have you tried using chrome.extension.getBackgroundPage()? This may provide the access to your background page's API that you require. For example, your first notification page calls the following when Yes is clicked;
function yesClicked() {
chrome.extension.getBackgroundPage().showSecondNotification();
}
The background page declares the showSecondNotification method as follows;
function showSecondNotification() {
webkitNotifications.createHTMLNotification(
chrome.extension.getURL('notification2.html')
).show();
}
Hopefully, this will cause the second notification to be displayed. I've used a similar method in my extensions before but only to retrieve information from the background page. However, I see no reason this shouldn't work.

show page action popup on click

I'm making a chrome extension that uses pageAction.
I can set when it shows whether I want it to have a popup or handle the click myself.
What I want to do is handle the click myself, but with certain scenarios I don't want to process the normal code, and want to show the user a message. Preferably with a popup.
But it seams I can either make the pageAction have a popup or have an onClick. But not both.
I can show an alert, but that is ugly.
Currently, there is no "neat" or official way to handle both. You can just do either. But there are some work arounds that some Google extension product have done.
First of all, set it up to show the popup. And within your pageAction popup, you can have the initialization code to be something like this:
Page Action Popup:
function init() {
if (getClickBehaviour() == 'popup')
handlePopup();
else
openPage();
}
function getClickBehaviour() {
return localStorage['CLICK_BEHAVIOR'] || 'popup';
}
function openPage() {
chrome.tabs.create({url: 'http://google.ca'});
window.close();
});
}
init();
Then you can let your options, set the click behavior. If you want different behaviors on each click, you can do that too.
As you noticed, we are closing the popup right after for the "default" behavior that we don't want the popup to show. That is currently the only way to implement different behaviors.
I haven't tested this myself yet, but have you tried setting the popup to the empty string when you want to handle the click (chrome.pageAction.setPopup('')) and to your popup when you want to show a message. I'm not perfectly sure if the onClicked event handler gets called in that case (where the popup is dynamically set to the empty string), but it's worth looking into.
As far as I know, there is generally no way to programmatically open a popup window for a page or browser action. (Which is too bad, I would love this functionality; but you can imagine some of the annoyances if this were possible.)

How to get the changed content in the page?

I wrote a user script for the latest Chrome browser. It seems the script can't get the changed content of the page after loaded (for example, after the page loaded, I clicked ¿sth? and an embedded window popped up).
Even if I used window.setTimeout(), I still can't the get updated content in the timer callback through document.getElementById(). I inspected the page and found that the popup element existed in the DOM.
Is this a limitation of user script? Or some other methods could be used to get the update in user script?
Update:
I tried DOMSubtreemodified event as suggested. But the behavior is still strange.
I added only one one line of JavaScript to the userscript for my.safaribooksonline.com,
document.addEventListener("DOMSubtreeModified", function () {
alert(eval('typeof OpenSignInPopup')); });
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup. But I can run the alert statement in the script console in the same page at the same time, and shows the result as "function".
This function was not loaded when the user script is running at first. So how can I use it in the user script?
You need to provide details, like the relevant code snippet(s) and the pages targeted.
In general, you can fire off the DOMSubtreeModified event in chrome. That should get you access to the changed DOM.
Also, are you sure the new content is not in an iframe?
Update for new OP info:
But the alert box shows "undefined" as the evaluate result of OpenSignInPopup.
In Chrome, Greasemonkey code cannot interact with the page's JS functions like that. You'll need to inject your code into the page. See this SO answer for more information.