0

I'm building chrome extension that is going to interact with web applications and send data to it. I have 2 features - connect to web app and generate hash message (Metamask like functionality). But I faced with issue that to interact with extension http web app needs to have permissions (externally_connectable) and write permissions for every http site is a bad idea I guess (as I know it works good for https web apps). As patterns for externally_connectable like <all_urls> is prohibited I ask for help, maybe I chose wrong solution for this features. Help please.

manifest.json

{
  "manifest_version": 3,
  "name": "extension",
  "description": "extension",
  "version": "1.0.0",
  "icons": {
    "16": "16x16.png",
    "48": "48x48.png",
    "128": "128x128.png"
  },
  "host_permissions": ["https://google.com/", "http://localhost:3000/"],
  "permissions": ["cookies", "storage", "tabs"],
  "action": {
    "default_popup": "popup.html",
    "default_title": "Open popup",
    "default_icon": "16x16.png"
  },
  "background": {
    "service_worker": "background.js"
  },
  "externally_connectable": {
    "matches": [
      "http://my-http-test-web-app/",
      "http://localhost:3000/",
      "http://localhost:3001/"
    ]
  }

webapp script

const message = { id: ExtensionID, method: 'requestAccounts' }

chrome?.runtime?.sendMessage(ExtensionID, JSON.stringify(message),  (response) => console.log(response)}

background.js


chrome.runtime.onMessageExternal.addListener(async (request, sender, sendResponse) => {
  const parsedRequest: IExternalRequest = JSON.parse(request)
  
  const { connectedSites, activeAccount, userBalances } = await chrome.storage.local.get()

  if (connectedSites && connectedSites.includes(sender.origin)) {
    sendResponse({
      id: EXTENSION_ID,
      success: true,
      method: 'responseRequestAccounts',
      data: {
        address: activeAccount.address,
        guildName: activeAccount.username,
        balance: userBalances,
      },
    })
    return
  }

  await chrome.storage.local.set(prepareRequestData(method, sender.tab, sender.origin))
  await openNewNotificationsPage()

  chrome.runtime.onMessage.addListener((request) => {
    sendResponse(JSON.parse(request))
  })

}

const openNewNotificationsPage = async () => {
  const { top, left, width } = await chrome.windows.getCurrent()
  const topPosition = Math.max(top, 0)
  const leftPosition = Math.max(left + (width - 340), 0)
  const options = {
    url: 'notification.html',
    type: 'popup',
    width: 340,
    height: 516,
    left: leftPosition,
    top: topPosition,
  }
  openWindow(options)
}


function openWindow(options) {
  chrome.windows.create(options)
}

On new opened window there is a extension script that gets account data and sends it

chrome.runtime.sendMessage(
        EXTENSION_ID,
        JSON.stringify(buildConnectWalletResponseData(response, true)),
        handleClose
      
  • Use a content script and CustomEvent messaging: [example](https://stackoverflow.com/a/10527809). – wOxxOm May 09 '22 at 10:48

2 Answers2

0

In your web application, you need to put window.chrome.runtime instead of chrome.runtime in order for your script to have access to the chrome runtime. Keep in mind this will cause errors if you run this JS outside of Chrome.

  • Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Sep 20 '22 at 11:11
0

As stated by user16951074, you need to use window.chrome.runtime instead of chrome.runtime.

In addition, by default, Google Chrome enforces a policy that requires websites to use HTTPS when accessing certain sensitive APIs, including the Chrome extension API. This means that if your webapp is served over HTTP rather than HTTPS, you may encounter errors when trying to access window.chrome.runtime.

However, there is a way to enable the Chrome extension API in an HTTP webapp by setting the --allow-running-insecure-content flag in Google Chrome:

  • In chrome://flags, search for "insecure" in the search bar.*
  • Find the "Insecure origins treated as secure" option and click the "Enable" link next to it.
  • In the "Insecure origins" text box that appears, enter the origin of your webapp. For example, if your webapp is served at http://localhost:3000, you would enter http://localhost:3000 in the text box.
  • Click the "Relaunch" button to relaunch Google Chrome with the flag enabled. After relaunching Google Chrome with the --allow-running-insecure-content flag, your webapp should be able to access window.chrome.runtime even if it is served over HTTP.

Note that enabling this flag can expose your webapp to security vulnerabilities, so it is generally not recommended to use it in a production environment.

aj3409
  • 186
  • 2
  • 14