【簡単】FlutterでChrome拡張機能を作ってみた

今回は、Flutterで拡張機能を作ってみようと思います!
僕が過去に、チャットワークの一括既読という拡張機能を作ったのですが、具体的な開発方法は載せていなかったので、改めてまとめてみました!
※リリースからしばらく経っているのとGyazoの有料プラン解約して画像も消えてしまいました…今使えるかは分かりません (*_ _)՞՞
Flutterプロジェクト作成してローカル起動
Chrome拡張機能なのでプラットフォームはwebでOK!
% fvm flutter create --platforms web chrome_extension_demo
以下コマンドでローカル起動してみます。
% flutter run -d chrome
いつものFlutterの初期カウンターアプリがwebで表示されました。

manifest.jsonで拡張機能の基本設定
web/manifest.json
を以下のように修正します。
{
"manifest_version": 3,
"name": "デモ拡張機能",
"description": "デモ拡張機能です。",
"version": "1.0.0",
"content_security_policy": {
"extension_pages": "script-src 'self' ; object-src 'self'"
},
"action": {
"default_popup": "index.html",
"default_icon": "/icons/sample.png"
},
"icons": {
"16": "/icons/sample16.png",
"32": "/icons/sample32.png",
"48": "/icons/sample48.png",
"128": "/icons/sample128.png"
},
"background": {
"service_worker": "background.js"
},
"content_scripts": [
{
"matches": ["http://*/*", "https://*/*"],
"js": ["content_script.js"]
}
],
"permissions": ["activeTab", "tabs", "scripting", "storage"],
"host_permissions": ["http://*/*", "https://*/*"]
}
基本的な項目だけ簡単に説明します。
- name
- Chromeウェブストアでユーザーに表示される拡張機能の名前です。
- description
- 拡張機能の説明で、Chromeウェブストアにも表示されます。
- icons
- Chromeウェブストアなどのアイコンとして使用され、16x16px, 32x32px, 48x48px, 128x128pxのアイコンを用意する必要があります。
簡単なChrome拡張機能を実装してみる
今回は、現在表示しているタブのURLを取得して表示するという拡張機能を作ってみます。
完成系のイメージはこちら↓
.png?w=1428&fit=max&fm=webp)
Flutterにjsを読み込む
Flutter上でjsを使用するために以下のパッケージを使用します。
このパッケージを使うことで、dart側からJavascirptの処理を直接呼び出すサポートをしてくれます。
dependencies:
flutter:
sdk: flutter
js: ^0.6.5
index.htmlの整理
拡張機能を表示するhtmlの基本設定です。
content_script.js
の読み込みと、拡張機能ポップアップのサイズ(<html style="height: 500px; width: 450px">
)を指定しておきましょう。
<!DOCTYPE html>
<html style="height: 500px; width: 450px">
<head>
<base href="$FLUTTER_BASE_HREF">
<meta charset="UTF-8">
<meta content="IE=Edge" http-equiv="X-UA-Compatible">
<meta name="description" content="A new Flutter project.">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<meta name="apple-mobile-web-app-title" content="chrome_extension_demo">
<link rel="apple-touch-icon" href="icons/sample.png">
<link rel="icon" type="image/png" href="icons/sample.png" />
<title>chrome_extension_demo</title>
<link rel="manifest" href="manifest.json">
</head>
<body>
<script type="application/javascript" src="main.dart.js"></script>
<script type="application/javascript" src="content_script.js"></script>
</body>
</html>
Chrome APIを使用してタブの情報を取得
タブのURLを取得するにあたり、chrome.tabs
API を使用してブラウザのタブシステムを操作します。
https://developer.chrome.com/docs/extensions/reference/api/tabs?hl=ja#get-the-current-tab
この API を使用すると、ブラウザのタブを作成、変更、並べ替えなどができます。
web/content_script.js
async function getUrl() {
let queryOptions = { active: true, lastFocusedWindow: true };
let [tab] = await chrome.tabs.query(queryOptions);
return tab.url;
}
main.dartでアプリUIと機能作成
lib/main.dart
import 'package:flutter/material.dart';
import './content_script.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatefulWidget {
const MyApp({super.key});
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
String currentUrl = 'URL未取得';
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () async {
var url = await getUrl();
setState(() {
currentUrl = url;
});
},
child: const Text('このページのURLを取得・表示'),
),
const SizedBox(height: 32),
Text(
currentUrl,
style: const TextStyle(fontSize: 16, color: Colors.black),
),
],
),
),
);
}
}
lib/content_script.dart
ここでは、jsパッケージを使用してjsの呼び出しをしています。
@JS()
library chrome_api;
import 'package:js/js.dart';
import 'package:js/js_util.dart';
@JS('getUrl')
external Object _getUrl();
Future<String> getUrl() async {
return promiseToFuture<String>(_getUrl());
}
ここまでできたらあとはビルドするだけです。
ちなみに、flutter run
で表示の確認はできますが、Chrome APIの実行はローカルでできませんので注意してください。
.png?w=1428&fit=max&fm=webp)
ビルドする
拡張機能としてビルドします。
% flutter build web --web-renderer html --csp 13:02:15
Compiling lib/main.dart for the Web...
✓ Built build/web
Chrome拡張機能として読み込む
chrome://extensions/
ページを開きます。
右上の「デベロッパーモード」をオンにしておきましょう。
.png?w=1428&fit=max&fm=webp)
そして、「パッケージ化されていない拡張機能を読み込む」を選択すると、ファイル選択のポップアップが表示されるので、ソースコードの「buildフォルダ」内にある「webフォルダ」を選択して決定してください。
.png?w=1428&fit=max&fm=webp)
以下のように追加されていればOKです。
.png?w=1428&fit=max&fm=webp)
実際に拡張機能を使ってみる
実際に確認してみます。
.png?w=1428&fit=max&fm=webp)
ボタンをクリックすると…
.png?w=1428&fit=max&fm=webp)
URLが取得できていますね!
まとめ
いかがでしたか?
Flutterでも意外と簡単に拡張機能を作ることができました!
Flutter信者はぜひ試してみてください!
番外編:Chromeウェブストアへリリースもできる
Chromeウェブストアのデベロッパーアカウントを作成($5の費用がかかります)してリリースすることもできます。
今回はそこまでやりませんが、興味ある方はぜひ。