1

I'm trying to access a function in content script from my background script in that way -

content.js

window.DOsomething = function(){
    console.log('Works?');
}

background.js

var popups = chrome.extension.getViews();
if (popups.length != 0) {
            var popup = popups[0];
            popup.DOsomething();
}

But it's not working! It throws an error Uncaught TypeError: Object [object Window] has no method 'DOsomething', but when I do console.log(window) in my content script - it shows me, that such method (DOsomething) exists! But in popups[0] there is no such method in list, I really don't understand such result

Stan
  • 8,683
  • 9
  • 58
  • 102
lesha_89
  • 55
  • 2
  • 7

2 Answers2

3

This is a known feature of Chrome Extensions called isolated world. Content scripts are injected into a target page and can not be accessed from other parts of the extension directly. To interact you should use messaging.

Here is a bit outdated SO answer to a related question which may be helpful to make a whole picture. In the answer you should adapt the code to work with sendMessage instead of sendRequest, which was removed in favor of the first one.

For example, you place in the background page the following call (taken from the documentation):

chrome.tabs.getSelected(null, function(tab) {
  chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, // you can send "DoSomething" for example
  function(response) {
    console.log(response.farewell);
  });
});

In the content script you should listen to the message:

chrome.extension.onMessage.addListener(
  function(request, sender, sendResponse) {
    console.log(sender.tab ?
                "from a content script:" + sender.tab.url :
                "from the extension");
    if(request.greeting == "hello")
      sendResponse({farewell: "goodbye"});
    // else if(request.greeting == "DoSomething") DoSomething();
});

I don't think getViews method is what you want, because it returns your extension pages (background, popups, options), and not the pages where your content scripts are injected. I suppose you should either sendMessages from your content script to the background page, so that the later "knows" all scripts host pages, or you can use executeScript.

chrome.tabs.executeScript(tabId, {code: 'DOsomething();'})
Community
  • 1
  • 1
Stan
  • 8,683
  • 9
  • 58
  • 102
  • Thanks for answer, but how i can transmit some data from background sto content script? I'm trying and trying but no result :( – lesha_89 Jan 02 '13 at 13:16
  • tnx, i tryed but getting errors - "Port error: Could not establish connection. Receiving end does not exist." and "Error in event handler for 'undefined': Cannot read property 'farewell' of undefined TypeError: Cannot read property 'farewell' of undefined" :( – lesha_89 Jan 02 '13 at 13:49
  • You seems invoking "hello" `sendMessage` before the content script is injected (make sure you have updated target page after you modified your content script). To solve this you can send initial message in reverse direction (i.e. from the script to the background page, so the script will be guaranteed existing), as I suggested in the answer. Or, just to make sure it works, you can add browser action button and send the "hello" message from the background within a click listener of the button (hence you can make sure target page is open before an attempt to connect to it). – Stan Jan 02 '13 at 14:44
  • I really appreciate for help, but I don't understand, how to send initial message, because on stage of understanding chrome api I don't know how to send messages at all, can u show me working example? thanks Stan – lesha_89 Jan 03 '13 at 08:05
  • Try to start with a [basic example](http://developer.chrome.com/dev/extensions/examples/api/eventPage/basic.zip) provided by Google. – Stan Jan 03 '13 at 09:23
-1

background.js

var message = "What ever you want...";
var viewTabUrl = chrome.extension.getURL('main.html');
var views = chrome.extension.getViews();
for (var i = 0; view = views[i]; i++)
{
    if (view.location.href == viewTabUrl)
    {
        view.DOsomething (messages);
        break;
    }
}

content.js

function DOsomething (message)
{
// CODE
}

in above example I have considered that 'main.html' is your popup(html) and content.js is included.

Vivek
  • 4,786
  • 2
  • 18
  • 27