Flutter Google Chrome Extension - how to communicate between Dart and service worker when the popup is not active?

84 Views Asked by At

Context: I am currently building a Password Manager app in Flutter (thanks to FlutterFlow) for IOS, Android and Chrome (as an extension).

Build info:

  • manifest V3
  • flutter 3.13.7 (current flutter version used by FlutterFlow)
  • Chrome: Version 120.0.6099.234

Current status: I successfully configured my popup.html and manifest.json to be able to launch the flutter app as a Chrome extension. Currently, my extension can catch the current tab information from the popup (I use the chrome_extension flutter pub in a FlutterFlow custom action).

Objective: I want to set a communication channel between my service_worker and my Dart code (compiled into the "main.dart.js" file) that can works even when the popup is not opened.

Issue: To get a functional code for the web, flutter compiled the main.dart file into JavaScript (if I am not wrong), making the whole app contained into the "main.dart.js" resulting file. I use it as the source for the body of my popup.html, which make the code only available when the popup is active.

I need to check the available user credential for the current website when the popup is not opened (so not active).

Given the users connect through popup, their authentication info, functions for credential queries etc.. are all contained into the main.dart.js logic, which is not accessible when the popup is not active.

I do not find how to communicate between a service_worker/content_script and my dart code when the popup is not active.

One of the workaround could be to store user authentication info into chrome storage, to make db queries from another file than main.dart.js, but I am not sure about the practicality and security of this solution.

Do you have any idea? solution?

Thanks in advance for your help

What I tried: For testing purpose, I implemented a simple sendMessage function on content script and service_worker, and Listener on the Dart side, but if the popup is not active, it results with this error: "Unchecked runtime.lastError: Could not establish connection. Receiving end does not exist."

If the popup is active, the communication works directly between my content_script and my Dart code. I spend lot of time on forums and chatGPT to find a solution, with no success.

Some of the code:

content_script.js:

// Send a message to the service worker
chrome.runtime.sendMessage({greeting: 'Hello from content script'}, (response) => {
  console.log('Received response in content script:', response);
});

service_worker.js:

// Listen for messages from the content script
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log('Service Worker: Received message:', message);

    var messageFromSE = 'Hello from Service Worker';

    // Forward the message to the Dart code and listen for a response
    chrome.runtime.sendMessage(messageFromSE, (responseFromDart) => {
        console.log('Service Worker: Received response from Dart:', responseFromDart);

        // Send the response back to the content script
        sendResponse(responseFromDart);
    });

    // Return true to indicate that you wish to send a response asynchronously
    return true;
});

Custom action in FlutterFlow, compiled into my main.dart.js file:

import 'dart:async';
import 'dart:js' as js;
import 'dart:convert';
import 'package:chrome_extension/runtime.dart' as chrome_ext;

Future<void> listenForMessagesFromServiceWorker() async {
  chrome_ext.chrome.runtime.onMessage.listen((chrome_ext.OnMessageEvent e) {
    print('Dart: Received message from Service Worker: ${e.message}');

    // Process the message and send a response back
    var response = {'greeting': 'Hello back from Dart'};
    e.sendResponse(js.JsObject.jsify(response));
  });

  // Return a future that never completes to keep the listener active
  return Future.value();
}

This last dart function is added to the main.dart file as an action to perform when the app is initializing, so that the listener is active as soon as the app starts.

0

There are 0 best solutions below