'Gettting response from empty content.js script. What am I doing wrong?

I have an extension that uses the omnibox to go to a new URL, then runs a search action on the new URL.

So:

  1. I type 'm foo'
  2. omnibox recognizes my omnibox shortcut command ('m') and directs the current tab to go to 'myurl'
  3. then i need some way to have the extension go to an input search box on that page and submit a search for 'foo'. this is what the message passing is supposed to help achieve.
  4. and show the resulting page in that same tab.
  5. that's it.

Well, that's the intended behavior.

One problem I have is that a message I'm sending from my extension/background.js to my content.js is being responded to -- but there is literally nothing in my content.js doing the responding. I know this because there is literally nothing in my content.js.

What am I missing?

chrome.omnibox.onInputEntered.addListener((text, OnInputEnteredDisposition) => {

    console.log('mgmt is called with: ' + text);

    // first just try to go to the new tab
    //chrome.tabs.update({url: "http://www.baidu.com"});

    // then try to do a callback, after the new tab is loaded
    //chrome.tabs.update({url: "http://www.baidu.com"}, function(tab){console.log('test')});

    // then try to do callback that sends a message to content.js 
    chrome.tabs.update({url: "http://www.asknoam.com"},
        function(tab){
            console.log('in the update() callback...');

            console.log('tab is: ' + tab.id);
            chrome.tabs.sendMessage(tab.id, {greeting: "hello"}, function(response) {
                console.log('we got a response from the content tab!');
                if(response!=null){
                    console.log('and the response was:' + response);
                }
                else{
                    console.log('well, response was null. :-/');
                }
            });
        });
});

My output in the service worker console:

mgmt is called with: test
background.js:32 in the update() callback...
background.js:34 tab is: 670
background.js:36 we got a response from the content tab!
background.js:41 well, response was null. :-/

I'm also getting a cryptic error message in my main browser console for the tab I'm redirecting:

extensions.js:4363 Uncaught TypeError: Failed to construct 'URL': Invalid URL
    at ExtensionsErrorPageElement.onSelectedErrorChanged_ (extensions.js:4363:2872)
    at Object.runObserverEffect [as fn] (polymer_bundled.min.js:1:37568)
    at runEffectsForProperty (polymer_bundled.min.js:1:37087)

I've never gotten message passing to work so I might try to work backwards from there. That is, find some simple boilerplate that sends messages between a background.js and a content.js and then add the extra functionality I need.

If I remove the 'content.js' from even my manifest.json file -- as opposed to just having an empty content.js file -- then I get the 'Could not establish connection...' error in the service worker console -- which seems reasonable.

...also, I have disabled all other extensions and Chrome apps because I read something about asynchronous and multiple listeners and etc.



Solution 1:[1]

The callback of chrome.tabs.update runs almost immediately, so the subsequent sendMessage runs before the new URL is navigated i.e. before the page is created and before the content script runs.

There are several solutions.

1. Use chrome.storage.local.

background script:

chrome.omnibox.onInputEntered.addListener(async text => {
  await chrome.storage.local.set({text});
  await chrome.tabs.update({ url: 'http://www.asknoam.com' });
});

content script:

chrome.storage.local.get('text', ({text}) => {
  process(text);
  chrome.storage.local.remove('text');
});
chrome.storage.onChanged.addListener(changes => {
  if (changes.text) process(changes.text.newValue);
});

manifest.json:

  "permissions": ["storage"]

2. Wait for the tab to load

background script:

chrome.omnibox.onInputEntered.addListener(async text => {
  const tab = await chrome.tabs.update({ url: 'http://www.asknoam.com' });
  chrome.tabs.onUpdated.addListener(function onUpd(tabId, info) {
    if (tabId === tab.id && info.status === 'complete') {
      chrome.tabs.onUpdated.removeListener(onUpd);
      chrome.tabs.sendMessage(tabId, text);
    }
  });
});

content script:

chrome.runtime.onMessage.addListener(msg => {
  sendResponse('bar');
  // use msg
  // ........
});

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 wOxxOm