0

In a chrome extension I'm trying to basically use the background.js as an API. Here's what I mean...

From my understanding of chrome extensions, the end-user does not have access to the background scripts. For this reason it is safe to use API keys inside a background script. (If this is wrong please someone correct me).

Currently my extension looks a little something like this: Application Workflow

Ex:

Content.js function -> background.js listener -> external api

Content.js callback <- background.js listener <- external api

The issue occurs in that the message passing for chrome extensions have two options.

  1. "Simple one-time requests" via chrome.runtime.sendMessage
    • Limitation: Unchecked runtime.lastError: The message port closed before a response was received.
  2. "Long-lived connections" via port.postMessage.
    • Limitation: No callback function

Research

Attempts

With method 1

content.js

chrome.runtime.sendMessage({action: "hello from content"}, response => {
  console.log("content: callback", response);
});

background.js

chrome.runtime.onMessage.addListener(async function(message, sender, sendResponse) {
    return new Promise((resolve, reject) => {
        GetCurrentlyPlaying()
            .then((response) => {
                    //sendResponse({response: response}); // tried using this
                    //resolve({response: response}); // also tried using this, also tried both
            });
    })
});

Result

Error: Unchecked runtime.lastError: The message port closed before a response was received. the callback is called and logs unndefined

With method 2

content.js

let port = chrome.runtime.connect();

port.postMessage({
  callback: function(response) {
    console.log('content: callback', response);
  }
});

port.onMessage.addListener(function (message) {
  if (message.callback && message.data) {
    message.callback(message.data);
    return;
  }
});

background.js

chrome.runtime.onConnect.addListener(function (port) {
    port.onMessage.addListener(function (message) {
            GetCurrentlyPlaying()
                .then((response) => {
                    port.postMessage({
                        callback: message.callback,
                        data: response
                    });
                });
    });
});

Result

The callback function is lost as postMessage accepts only json, so functions are stripped


I think the best course of action will have something to do with method 1 and promises but I'm just not sure how to make it work correctly. At the end of the day the content script needs to get the api's response in a callback function.

  • `it is safe to use API keys inside a background script` - of course, anyone can read them, without even installing the extension - did you need the API keys to be completely hidden from end user? – Jaromanda X May 06 '19 at 00:52
  • as far as `sendResponse` goes, that is being removed from the w3cspec and returning a Promise is now preferred - note: this comes from MDN documentation, not sure if Chrome cares about w3c specs - looking at https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/runtime/onMessage Chrome does NOT support returning a promise, so, why is *Similar Issue, not required solution* not a solution for you? Seems to be the way to do it in Chrome – Jaromanda X May 06 '19 at 00:56
  • @JaromandaX I tried to use what that suggested but it didn't work. Am I missing something? –  May 06 '19 at 02:24
  • I can't see how you tried that, considering you haven't returned true to indicate an asynchronous response – Jaromanda X May 06 '19 at 02:31
  • Under "With method 1" I did `resolve({response: response});` I showed it commented but I I did try it. I could never get the resolved promise to return. Could you possibly show where my code is wrong? It sounds like I'm missing something obvious –  May 06 '19 at 02:35
  • @JaromandaX I also was wondering since you pointed out that api's are by no means safe inside background, do you know of any resources for how to safety use apis within chrome extensions? Everything I search just brings up the chrome api's. –  May 06 '19 at 02:37
  • chrome doesn't work with Promises ... so that is not at all using the solution – Jaromanda X May 06 '19 at 02:38
  • Is it a difference between chrome.runtime and browser.runtime? when I try and use browser I get `browser is not defined` –  May 06 '19 at 02:43
  • MDN documentation is not Chrome documentation ... while the concepts are the same, there are differences, use chrome dicumentation for web extensions for chrome extensions – Jaromanda X May 06 '19 at 02:46
  • End users can **trivially** inspect your background script code [either in devtools](https://stackoverflow.com/questions/10257301/where-to-read-console-messages-from-background-js-in-a-chrome-extension) or in their browser profile directory in a file manager. Also, you can't return Promise to chrome extension API so the best solution is probably Mozilla's WebExtension polyfill. And you can't send functions via messaging, only simple jsonifiable types are transferrable. – wOxxOm May 06 '19 at 04:36

0 Answers0