Vaughn Dickson
Vaughn Dickson

Reputation: 296

Chrome extension: sending data to window created with chrome.windows.create

I'm struggling to find the best way to communicate with my web app, which I'm opening with chrome.windows.create in my extension.

I've got the wiring between content script and background script right. I can right click an element and send it's value to the background script, and the background script creates a window containing my webapp. But from there I can't figure out how to access and use that value in my webapp (it needs to load the value into an editor).

I've tried setting fns and vars on the window and tab objects, but somehow they go missing from the window object once the web app is loaded. With chrome.tabs.executeScript I can fiddle with the dom, but not set global variables or anything on 'window' either.

If there isn't a better way, I guess I'm forced to add to the DOM and pick that up once my web app is loaded, but it seems messy. I was hoping for a cleaner method, like setting an onLoadFromExtension fn which my web app can execute to get the value it needs.

Upvotes: 4

Views: 1967

Answers (2)

aleclarson
aleclarson

Reputation: 19055

  1. Within the popup, do the following:
    const parentWindow = window.opener
    parentWindow.postMessage({ action: 'opened' })
    window.onmessage = msg => {
      alert(JSON.stringify(msg.data)) // Alerts you with {"your":"data"}
    }
    
  2. Within the script that will call chrome.windows.create, do the following:
    window.onmessage = msg => {
      if (msg.data.action == 'opened') {
        msg.source.postMessage({ your: 'data' })
      }
    }
    
  3. Set setSelfAsOpener: true when calling chrome.windows.create

How does this work?

Due to limitations of the Chrome extension windows API, the created window needs to post a message to its creator (aka window.opener) or else the creator won't have access to a WindowProxy (useful for posting messages to the created window).

Upvotes: 1

Vaughn Dickson
Vaughn Dickson

Reputation: 296

I found a method that works after much trial and error, though it still seems error prone. And it also depends on the extension ID matching the installed one, so if that can't be hard-coded it'll be another message that needs passing through another channel (after reading up, looks like that can be hard-coded since it's a hash of the public key, so problem solved)... Starting to think manipulating the DOM is less messy...

background.js:

var selectedContent = null;
chrome.runtime.onMessageExternal.addListener(
  function(request, sender, sendResponse) {
    console.info("------------------------------- Got request", request);
    if (request.getSelectedContent) {
      sendResponse(selectedContent);        
    }
  });

web app:

var extensionId = "naonkagfcedpnnhdhjahadkghagenjnc";
  chrome.runtime.sendMessage(extensionId, {getSelectedContent: "true"},
    response => {
      console.info("----------------- Got response", response);
      if(response) {
        this.text = response;
      }
    });

manifest.json:

"externally_connectable": {
  "ids": ["naonkagfcedpnnhdhjahadkghagenjnc"],
  "matches": ["http://localhost:1338/*"]
},

Upvotes: 2

Related Questions