利用者としてのGoogle Chrome拡張機能
このページは開発者としての内容です。 利用者としてのGoogle Chrome拡張機能は、Google Chromeに記載しています。
マニュアル
WebExtensions
Firefoxの話ですが、 Google Chromeが採用しているAPIとある程度互換性がある、 WebExtensions APIがあります。
そのため、Firefoxの拡張機能のドキュメントは、 Google Chromeのドキュメントを読むときに、ある程度参考になります。 翻訳されているものも多いため、概要を理解するには良いでしょう。
セキュリティ
以下のような制限があります。
- コンテンツスクリプト
- 使えるAPIが制限されている。
- Understand Content Script Capabilities
- browserActionなどは使えない。
- 使えるAPIが制限されている。
- バックグラウンドスクリプト
- Webページのコンテンツにアクセスできない。
なので、Webページのコンテンツにアクセスしつつ、 バックグラウンドスクリプトでbrowserActionを使う場合は、 この2つのスクリプトで通信をする必要があります。
制限事項
- evalはそれに類するものは使用不可。
- 対策
- 基本的にはevalを使わない。
- sandboxを使う。
- 対策
- インラインJavaScriptは実行されない。
- 対策
- 関数定義は外部ファイルに移動。
- イベントハンドラはaddEventListenerを使用。
- onloadはDOMContentLoadedイベントをハンドリング。
- DOM構築前でよければ
"run_at": "document_start"
を使用。
- Chrome 46からはbase64エンコードされて、ハッシュ付きならOKの模様。
- 対策
- ローカルのスクリプトとリソースのみ読み込まれる。
- 対策
- ファイルをダウンロードしてパッケージに含める。
- CSPを適切に設定すればリモートのスクリプトも使える?
- 対策
- Content Security Policyの変更が可能。
- manifest.jsonのキーは
content_security_policy
- ただし
unsafe-inline
は使えない(see. Inline Script)。
- ただし
- Content Scriptsと題していろいろ書かれている。
- manifest.jsonのキーは
Scaffold(足場)
0から作ると大変なことも多いので、このようなツールを使うといいかもしれません。
- yeoman/generator-chrome-extension: Scaffold out a Chrome extension
- 2016年度版 僕が考えたChrome拡張機能を作るときのデザインパターン - Qiita
マニフェストファイル
必須項目
- manifest_version(number): マニフェストファイルのバージョン。現在は'2’(数値)
- name(string): 拡張機能の名前(45文字以下)。Chrome Web Storeなどで使われる。
- version(string): バージョン文字列。自動更新システムが認識するため、厳密な規定あり。ユーザが認識する文字列を指定する時は、version_nameを使う(後述)
- 1〜4つのドット区切りの整数
- それぞれの整数は0〜65535の範囲であること。
- ‘0’以外は'0’で始まるものはNG(例: ‘032’)
- バージョンの比較時は、左側から比較する。存在しないフィールドは'0’として扱う。
- 例1: ‘1.2.0’は'1.1.9.9999’より新しい。
- 例2: ‘1.1.9.9999’は'1.1’より新しい。
バージョン
- version_name: 画面表示に使用するバージョン。“beta”, “rc"などを含めたいときに便利。
パーミッション
Declare Permissions - Google Chrome
APIを使用する権限を表します。 “permissions"をキーとして、配列で記載します。
事前に定義されたものの他に、URLも記載できます。 Webページ内で実行したい場合は、Inject Declarativelyの方がいいかも。。。
アイコン
Manifest - Icons - Google Chrome
- 16x16: ファビコン(右上のアイコン)
- 48x48: 拡張機能の管理ページのアイコン
- 128x128: Chrome Web Store で使われる
アクション
ユーザがツールバー(URLバーの右側)で操作するもの。
- browser_action: 常に有効にする場合
- page_action: ページの内容によって有効にするかどうかが変わる場合
Content Script
Webページ上で動くもの。
- content_scripts(array):
- matches(array): マッチするサイト
- ワイルドカードが使用可能。詳細はmatch_patterns参照。
- css(array): 読み込まれるCSSファイル
- js(array): 読み込まれるJavaScriptファイル
- matches(array): マッチするサイト
Background Script
バックグラウンドで動くもの。
- background(object):
- scripts(array): 動くスクリプト
- persistent(boolean): 通常はfalse
- chrome.webRequestというネットワークリクエストを解析するAPI以外では使わなさそうです。
オプション画面
Give Users Options - Google Chrome
- options_page(string): オプション画面のHTML。新しいタブでオプション画面を表示する。
- options_ui(object): 拡張機能管理ページの中で埋め込み表示
- page: オプション画面のHTML。
- open_in_tab:
- true: 新しいタブで表示(options_page指定と同じ?)
- false: 埋め込み表示
オプション画面は内容を書き込むため、storageパーミッションは事実上必須。
タブ
タブのタイトルとURL、ファビコンURLを取得するには、permissionsに、tabs
をつける必要がある。
単にアクティブなタブを取得するだけなら不要。
クリップボード
permissionsに clipboardWrite
または clipboardRead
をつける必要がある。
少なくともChrome 71まではDocument.execCommandを使うのがよい。
以下の記事で書かれているように、テキストエリアを作成
→全選択→document.execCommand("copy")
を使用する。
chrome.clipboardというAPIがあるが、Chrome 71から導入(現在の安定版はChrome 69)のもので、 現在は開発中となっている。
また、説明には「オープン標準ができるまでの一時的な解決案」と書かれている。 これはClipboard APIのことと思われる。
コンテキストメニュー
以下の作業が必要。
- パーミッション
contextMenus
を追加 - バックグラウンドページを追加
バックグラウンドで書く件については以下の記事に記載。
開発手法
Promise/await/async
ほとんどが非同期で動く、callback付きで定義されているメソッドのため、 Promiseでラップして、await/asyncを使う機会が多いです。 まずこれを学ぶのが良いと思います。
パッケージ化されていない拡張機能を読み込む
- 拡張機能の画面を開く
- macOSの場合「︙」→「その他のツール」→「拡張機能」で出る。
- 適当な拡張機能を右クリック→「拡張機能を管理」→「拡張機能の名前の左の"←”」の方がいいかも。
- 「パッケージ化されていない拡張機能を読み込む」を押す。
- ダイアログが出るので、manifest.jsonがあるディレクトリを選択。
再読込するときは、拡張機能の画面のリロードボタンを押す。
公開
- 事前準備
- クレジットカード(初回のみ$5必要)
- スクリーンショット(1〜5枚, 1280x800)
- Screenshots
- 言語ごと対応可能
- アイコン
- 96x96 + パディング16px = 128x128
- アプリの詳細説明(言語ごと対応可能)
- 手順
- ZIP形式で固める
- ダッシュボードに行く
- ZIPのアップロード
- スクリーンショット、アイコン、詳細説明の記入など諸々作業
- プレビューして問題なければ公開
- 公開は数分で行われるようですが、キャッシュのためかすぐに反映されないため、シークレットモードで確認すると良さそうです。
API
- API一覧
- 履歴: chrome.history
- 設定の保存: chrome.storage
storage
オプションの保存を行う。
- chrome.storage.sync
- Chrome Syncによる同期を行うもの。
- Syncを有効化していないときは、localとしてふるまう。
Even if a user disables syncing, storage.sync will still work. In this case, it will behave identically to storage.local.
- 容量および操作回数の制限が大きいのに注意(chrome.storage.sync参照)
- chrome.storage.local
- ローカルのみ保存を行うもの。
- 容量は5MBだが、それ以外の制限はない。
- chrome.storage.managed
- 管理者が設定したポリシー(書き込み不可)。通常は意識しない。
いずれもAPIとしては共通(callbackを受け取る)のため、 非同期メソッドとして対処が必要。
注意点
単純なことですが、何度も間違えたので書いておきます。
{key: value}
のようなオブジェクトを格納する場合、
getとsetは以下のように書きます。
(例示のためPromiseは使わない)
// set
chrome.sync.set({key: value}, function() {
...
});
// get
chrome.sync.get({key: default_value}, function(items) {
const value = items.key; // items == valueと勘違いしてしまう
});
国際化
manifest.json
- “default_locale”: デフォルトのロケール。基本的には"en”
_locales/${localeCode}/messages.json
- localcode: ロケールコード。英語は’en’、日本語は’ja’
- キー: chrome.i18n.getMessageの最初の引数に使うキー
- message(必須): 取得するメッセージ
- description: 翻訳者に対する説明。アプリ内では使わない。
- manifest.json, CSS中に
__MSG_
と__
で囲むと、メッセージが使用可能。
HTMLの国際化
別記事にしました。
逆引きマニュアル: Google Chrome拡張機能: HTMLの国際化 - Hideki Ikemoto’s Site
国際化のテスト
- Windows:
--lang
オプションを使用 - Linux:
LANGUAGE
環境変数を使用 - macOS
- 「システム環境設定」を開く
- 「言語と地域」を開く
- Chromeを再起動
macOSだけめんどくさいですね(OSの機能そのままですが)。
公式サイト
外部サイト
関連項目
逆引きマニュアル
- Google Chrome拡張: CLIでパッケージ化する方法
- Google Chrome拡張機能: アクティブなタブを取得する
- Google Chrome拡張機能: HTMLの国際化
- WebStormでGoogle Chrome拡張機能を開発する方法
- 【失敗】Google Chrome拡張でメールを送る方法