chrome_extension 0.1.2 copy "chrome_extension: ^0.1.2" to clipboard
chrome_extension: ^0.1.2 copied to clipboard

A library for accessing the `chrome.*` APIs available in Chrome extensions.

chrome_extension.dart #

pub package Build Status

A library for accessing the chrome.* APIs available in Chrome extensions.

This allows to build Chrome extension with Dart & Flutter and to interop with the native APIs easily with a high-level type-safe interface.

The JS interop is build on top of dart:js_interop (static interop) which make it ready for future WASM compilation.

Using the library #

Example #

import 'package:chrome_extension/alarms.dart';
import 'package:chrome_extension/power.dart';
import 'package:chrome_extension/storage.dart';

void main() async {
  // Use the chrome.power API
  chrome.power.requestKeepAwake(Level.display);

  // Use the chrome.storage API
  await chrome.storage.local.set({'mykey': 'value'});
  var values = await chrome.storage.local.get(null /* all */);
  print(values['mykey']);

  // Use the chrome.alarms API
  await chrome.alarms.create('MyAlarm', AlarmCreateInfo(delayInMinutes: 2));
}

Available APIs #

Documentation #

Tips to build Chrome extensions with Flutter #

Develop the app using Flutter Desktop

In order to develop in a comfortable environment with hot-reload, most of the app can be developed using Flutter desktop.

This will require an abstraction layer between the UI and the chrome_extension APIs.

A fake implementation of this abstraction layer is used in the Desktop entry point:

// lib/main_desktop.dart
void main() {
  // Inject a fake service that doesn't use the real chrome_extension package.
  var service = FakeBookmarkService();
  runApp(MyExtensionPopup(service));
}

abstract class BookmarkService {
  Future<List<Bookmark>> getBookmarks();
}

class FakeBookmarkService implements BookmarkService {
  @override
  Future<List<Bookmark>> getBookmarks() async => [Bookmark()];
}

Launch this entry point in desktop with
flutter run -t lib/main_desktop.dart -d macos|windows|linux

Create the real entry point:

// lib/main.dart
void main() {
  var service = ChromeBookmarkService();
  runApp(MyExtensionPopup(service));
}

class ChromeBookmarkService implements BookmarkService {
  @override
  Future<List<Bookmark>> getBookmarks() async {
    // Real implementation using chrome.bookmarks
    return (await chrome.bookmarks.getTree()).map(Bookmark.new).toList();
  }
}

Build script

web/manifest.json

{
  "manifest_version": 3,
  "name": "my_extension",
  "permissions": [
    "activeTab"
  ],
  "options_page": "options.html",
  "background": {
    "service_worker": "background.dart.js"
  },
  "action": {
    "default_popup": "index.html",
    "default_icon": {
      "16": "icons-16.png"
    }
  },
  "content_security_policy": {
    "extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self';"
  }
}
// tool/build.dart
void main() async {
  await _process.runProcess([
    'flutter',
    'build',
    'web',
    '-t',
    'web/popup.dart',
    '--csp',
    '--web-renderer=canvaskit',
    '--no-web-resources-cdn',
  ]);
  for (var script in [
    'background.dart',
    'content_script.dart',
    'options.dart'
  ]) {
    await _process.runProcess([
      Platform.resolvedExecutable,
      'compile',
      'js',
      'web/$script',
      '--output',
      'build/web/$script.js',
    ]);
  }
}

It builds the flutter app and compiles all the other Dart scripts (for example: options.dart.js, popup.dart.js, background.dart.js)

Testing

Write tests for the extension using puppeteer-dart.

import 'package:collection/collection.dart';
import 'package:puppeteer/puppeteer.dart';

void main() async {
  // Compile the extension
  var extensionPath = '...';

  var browser = await puppeteer.launch(
    headless: false,
    args: [
      '--disable-extensions-except=$extensionPath',
      '--load-extension=$extensionPath',
      // Allow to connect to puppeteer from inside your extension if needed for the testing
      '--remote-allow-origins=*',
    ],
  );

  // Find the background page target
  var targetName = 'service_worker';
  var backgroundPageTarget =
      browser.targets.firstWhereOrNull((t) => t.type == targetName);
  backgroundPageTarget ??=
      await browser.waitForTarget((target) => target.type == targetName);
  var worker = (await backgroundPageTarget.worker)!;

  var url = Uri.parse(worker.url!);
  assert(url.scheme == 'chrome-extension');
  var extensionId = url.host;

  // Go to the popup page
  await (await browser.pages)
      .first
      .goto('chrome-extension://$extensionId/popup.html');

  // Etc...
}
48
likes
0
pub points
77%
popularity

Publisher

verified publisherxaha.dev

A library for accessing the `chrome.*` APIs available in Chrome extensions.

Repository (GitHub)
View/report issues

License

unknown (license)

More

Packages that depend on chrome_extension