利用者としての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拡張でメールを送る方法