How can I modify popup page DOM from any listener from background script?
Two approaches.
1) Send a message to the popup script with instruction on how to update the view.
// background.js
chrome.runtime.sendMessage({updatePopup: true, update: "this", data: "that"});
// popup.js
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if(message.updatePopup) {
switch(message.update) {
/* ... */
case "this":
document.getElementById("this").value = message.data;
/* ... */
break;
/* ... */
}
}
});
Has an added benefit of not caring whether the popup is actually opened: the message will be sent out, and worst case no-one will act on it.
2) Obtain direct access to the window object.
// background.js
// A rare case of a synchronous API..
var windows = chrome.extension.getViews({type : "popup"});
if(windows) { // If popup is actually open
var popup = windows[0]; // This is the window object for the popup page
popup.document.getElementById("this").value = "that";
/* ... */
}
Related
My Chrome extension has a page that is seen in a popup or as a separate tab. When it seen as a separate tab, I need to show a small button at the corner of the page. But I couldn't find a way to detect when a page is loaded in its own tab.
Use chrome.extension.getViews, which returns an array of window objects.
var tabs = chrome.extension.getViews({ type: "tab"})
if(tabs[0]) {
console.log("inside tab")
}
var popups = chrome.extension.getViews({ type: "popup"})
if(popups[0]) {
console.log("inside popup")
}
Or chrome.tabs.getCurrent, which returns a tab object in the callback.
chrome.tabs.getCurrent(function(tab) {
if(tab) {
console.log("inside tab")
} else {
console.log("inside popup")
}
})
What is the proper way to send a message (and get a response) to background.js from popup.js in a Chrome extension? Every method I try ends up with an error that:
"Port: Could not establish connection. Receiving end does not exist."
I would prefer to use chrome.extension.sendMessage() over chrome.extension.connect() with port.postMessage(), but neither method seems to have worked.
What I am trying to do is wire a button in the popup.html to call into some javascript in popup.js which calls back to background.js in an effort to get info about the currentTab() that was topMost (ie:to get the current URL string to show in the popup.html)
Right now in popup.js (wired to the action of the button) I have:
function getURL()
{
chrome.extension.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });
$("#tabURL").text(tabURL);
}
In background.js I have:
chrome.extension.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting == "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
});
sendResponse( {navURL:tabURL} );
}
}
Any ideas?
Just to clarify, we talking about communication between popup page from browserAction and background script?
Anyway you have quite a few errors in your code.
First your totally ignore the fact that all callbacks in chrome api are asynchronous.
In background page
var tabURL = "Not set yet";
chrome.tabs.getCurrent(function(tab){
tabURL = tab.url;
}); //this will be invoked somewhere in the future
sendResponse( {navURL:tabURL} );
//navUrl will be always Not set yet because callback of getCurrent hasn't been called yet
Same in popup.js
chrome.runtime.sendMessage({greeting: "GetURL"},
function(response) { tabURL = response.navURL });//callback will be invoked somewhere in the future
$("#tabURL").text(tabURL)//tabURL will display something totally different from what you have been expected
Second error is that chrome.tabs.getCurrent doesn't give you the current tab selected by user in main window. The docs says:
Gets the tab that this script call is being made from. May be
undefined if called from a non-tab context (for example: a background
page or popup view).
So you will get undefined for all of your requests, because you call it in background page. What you need to do is to use method chrome.tabs.query to obtain currently active tabs.
So after fixing all problems new code should look something like this:
background.js
chrome.runtime.onMessage.addListener( function(request,sender,sendResponse)
{
if( request.greeting === "GetURL" )
{
var tabURL = "Not set yet";
chrome.tabs.query({active:true},function(tabs){
if(tabs.length === 0) {
sendResponse({});
return;
}
tabURL = tabs[0].url;
sendResponse( {navURL:tabURL} );
});
}
}
popup.js
function getURL() {
chrome.runtime.sendMessage({greeting: "GetURL"},
function (response) {
tabURL = response.navURL;
$("#tabURL").text(tabURL);
});
}
I'm trying to pass the active dom element when the contextmenu is clicked from my background script to a script that is being called through chrome.tabs.executeScript. I can pass booleans and strings just fine, but i always get an error when i pass dom elements. I'm starting to think it's not possible.
//doScripts function called from browser action
chrome.browserAction.onClicked.addListener(function(tab) {
doScripts(true, null);
});
//doScripts function called from context menu click
function getClickHandler(info, tab) {
var currTarg = document.activeElement;
console.log("currTarg = " + currTarg);
doScripts(false, currTarg);
}
//i reference doingBrowserAction and contextTarg in myscript.js
function doScripts(context, targ){
chrome.tabs.executeScript(null, {code: "var doingBrowserAction = "+context+"; var contextTarg = "+targ+";"}, function(){
chrome.tabs.executeScript(null, {file: "js/myscript.js"}, function(){
//all injected
});
});
}
//setup context menu
chrome.contextMenus.create({
"title" : "DESTROY!",
"type" : "normal",
"contexts" : ["page","selection","link","editable","image","video","audio"],
"onclick" : getClickHandler
});
i reference doingBrowserAction and contextTarg in myscript.js. I know what i'm trying to do is possible because the adblock extension does it, but having a hard time figuring out how. thanks in advance.
You cannot get a direct reference to a content script's DOM element from the background page, because the background page runs in the extension's process, and the content script runs in the tab's process. See also https://code.google.com/p/chromium/issues/detail?id=39507.
The document.activeElement property in the background page refers to the active element in the background page's document. As you can imagine, this value is quite useless.
If you query the state of the currently right-clicked element, bind an event in the content script. In the next example, I've chosen the contextmenu event, because context menus can also be opened through the keyboard.
This example adds a context menu option that removes the last active element from the document.
// content script
var lastElementContext;
document.addEventListener('contextmenu', function(event) {
lastElementContext = event.target;
}, true);
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
if (lastElementContext && lastElementContext.parentNode) {
lastElementContext.parentNode.removeChild(lastElementContext);
lastElementContext = null;
}
});
Background script:
chrome.contextMenus.create({
title: 'DESTROY!',
contexts: ['page', 'link', 'editable', 'image', 'video', 'audio'],
onclick: function(info, tab) {
chrome.tabs.sendMessage(tab.id, 'doDestroy');
}
});
I am using titanium to make a small app where i can click on a 'gallery' button located in a window and it opens photogallery. On selecting the photo it should move to next window. But what it does is, it closes the photogallery first, after that i can see my first(button) screen and then it opens the next window.
I dont want it to show the previous window. Is there a way to do it??
I am adding windows to tabs . Below is my code .
cameraButton.addEventListener('click',function(e){
chooseImageFromGallery();
});
function chooseImageFromGallery(){
var capturedImg;
//TODO Titanium.Media.showCamera({
Titanium.Media.openPhotoGallery({
success : function(event) {
capturedImg = event.media;
/* Condition to check the selected media */
if (event.mediaType == Ti.Media.MEDIA_TYPE_PHOTO) {
var window1 = MyWindows.init(capturedImg, docImgModel, previous_win);
MyCommon.addWindowToTabGroup(window1);
win.close();
}
},
cancel : function() {
//While cancellation of the process
activityInd.hide();
win.remove(activityInd);
},
error : function(error) {
/* called when there's an error */
var a = Titanium.UI.createAlertDialog({
titleid : 'camera'
});
if (error.code == Titanium.Media.NO_CAMERA) {
a.setMessage(L('camera_not_available'));
} else {
a.setMessage('Unexpected error: ' + error.message);
}
a.show();
activityInd.hide();
win.remove(activityInd);
}
});
}
The init method just creates a new window and returns it .
The addWindowToTabGroup method adds it to the current tab
addWindowToTabGroup(window){
// tabGroup is a tab at global level declared in app.js
// activeTab returns the current tab
tabGroup.activeTab.open(window, {
animated : true
});
}
Thanks a lot ....
You can do it this way:
1- on button click fire a global event which will open your photo gallery and then close your current window.
2- Now in success call back of photo gallery (when photo is selected) write you code of opening the new window you want to show your user ...
I need send message on page from notification window.
How to do it
I have following page
var shownotif=0;
Set notification permissions for this page Show HTML Notification /* * Common code */ document.querySelector('#request_permission').addEventListener('click', function() {
window.webkitNotifications.requestPermission(); }, false);
// see the HTML section to see the button var url = 'index212.html'; document.querySelector('#show_html_notification').addEventListener('click', function() {
if (window.webkitNotifications.checkPermission() == 0) {
// you can pass any url as a parameter
notif=window.webkitNotifications.createHTMLNotification(url);
notif.addEventListener('display', function() {
///alert(111);
// notif.cancel();
}
);
notif.addEventListener('click', function(g, g2) {
setTimeout("tkfnm",1000);
alert(jQuery.cookie("ca2"));
// notif.cancel();
}
);
notif.show(); // note the show()
} else {
alert("This page doesn't have permission to show notifications yet.");
} }, false);
I want to be that when user click in notification window, on "parent" send my message with my information.