🍄

Chrome Extension作ってみよう(初心者向け)

2022/01/12に公開

この記事は

非エンジニア向け勉強会資料として、難しいところにはあまり踏み込まずに書きます。
いつもは探して使うだけのChrome拡張機能も、実は自分で作れるんだと、手を動かしながら実感してもらいたいです。

Chrome拡張とは

Chrome拡張、Chrome Extension は、Google Chromeブラウザに機能を加えることができます。

サンプル

Google公式でいくつかのサンプルを公開しています。
https://github.com/GoogleChrome/chrome-extensions-samples

サンプル 機能
Hello World 新規タブを開いて Hello World を表示する
Page Redder 開いているページを赤く塗る
My Bookmarks ブックマークを開く

ローカルの拡張機能を動かす準備

ウェブストアで公開されている拡張機能をインストールすることが多いと思いますが、今回は自分で作った非公開の拡張機能を動かします。

試しに、先ほどのGoogleのサンプルコードをダウンロードして動かしてみます。

サンプルコードを取得

  1. サンプルコードをブラウザで開き、"Code" > "Download ZIP" をクリックします。

  2. ダウンロードした zip を解凍します。

Chromeでローカルの拡張機能を許可

  1. 拡張機能の管理画面をChromeブラウザで開きます。
  2. 画面右上の方の 「デベロッパーモード」を有効にします。
    有効にすると、上部にボタンが表示されます。

サンプルコードを実行

  1. 拡張機能の管理画面に出てきたボタン「パッケージ化されていない拡張機能を読み込む」をクリックします。

  2. 先ほど解凍したサンプルコードの examples ディレクトリの中から好きな拡張機能のディレクトリを選択します。

  3. 拡張機能の一覧に追加されていることを確認します。

  4. Chromeブラウザのツールバー右上にある拡張機能アイコンにも追加されているので、実行してみてください。

以上で、ローカルに用意した拡張機能を動作させる準備は完了です。

読み込んだ拡張が不要であれば、管理画面で「削除」しておいてください。

拡張機能を作ってみる

ここから先は自分が欲しい機能を作っていけばよいです。

今回は以前つぶやきがあった「JIRAのリンクは別タブで開かれて欲しい」を拡張で実現したいと思います。

サンプルを眺めてざっくり理解

今回は、「Page Redder」を例にします。

ファイル構成

page-redder
  |- background.js
  |- manifest.json

manifest.json

拡張機能の定義ファイルです。

{
  "name": "Page Redder",
  "action": {},
  "manifest_version": 3,
  "version": "0.1",
  "description": "Turns the page red when you click the icon",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "background.js"
  }
}
項目 内容 必須
name 拡張機能の名前 必須
action ツールバーに表示される拡張機能アイコンの設定
アイコン画像の設定とかができます。
推奨
manifest_version マニフェストファイルのバージョン
長らくバージョン2だったが、2021年に3が公開された。
2023年からは徐々にバージョン2の拡張が利用不可になっていくらしい。
必須
version 拡張機能のバージョン 必須
description 拡張機能の説明 推奨
permissions 拡張機能が制御できる範囲 任意
background 操作イベントの取得 任意

他にも設定可能な項目はいろいろあります。詳しくは公式のドキュメントを参照してください。

background.js

今回はこのファイルが拡張機能の本体です。

コードの解説をコメントで追記しました。

function reddenPage() {
  // body タグに background-color: red; をスタイル指定する → 開いているページの背景が赤くなる
  document.body.style.backgroundColor = 'red';
}

// 拡張機能アイコンがクリックされたら中身を実行する
chrome.action.onClicked.addListener((tab) => {
  // スクリプトを実行する
  chrome.scripting.executeScript({
    // クリックされたタブを対象にする
    target: { tabId: tab.id },
    // 実行するのは reddenPage の中身
    function: reddenPage
  });
});

2ファイル編集すれば動くものができそうですね。

「Page Redder」を編集

準備

「Page Redder」ディレクトリを好きなディレクトリにコピーします。

manifest.jsonを用意

「manifest.json」をエディタで開いて編集します。

  • name, description を書き換えます。(好きな内容で良いです)
  • permissions, background は必要に応じて追加するので空にしておきます。
{
  "name": "My JIRA",
  "action": {},
  "manifest_version": 3,
  "version": "0.1",
  "description": "JIRA内のリンクを別タブで開くようにする",
  "permissions": [],
  "background": {}
}

この状態で拡張機能を読み込ませると、とりあえず追加されます。

まだ何も動かないですが。

ページ内のリンクを別タブ開きにする

開いているページ内のリンク要素を別タブ開きにするのが今回作る機能です。

background.js をエディタで開いて編集します。

function linkToNewTab() {
  document.querySelectorAll('a').forEach((elem) => {
    elem.setAttribute('target', '_blank');
  })
}

chrome.action.onClicked.addListener((tab) => {
  chrome.scripting.executeScript({
    target: { tabId: tab.id },
    function: linkToNewTab
  });
});

変えたところ

  • 関数名
  • 関数の中身

関数の中身の解説

  • document.querySelectorAll('a') :ページの中の a タグを全部見つける
  • forEach :見つけた要素それぞれに処理をする
  • elem.setAttribute('target', '_blank');target="_blank" を追加する

必要な権限が増えたので「manifest.json」で改めて定義しておきます。

{
  "name": "My JIRA",
  "action": {},
  "manifest_version": 3,
  "version": "0.2",
  "description": "JIRA内のリンクを別タブで開くようにする",
  "permissions": [
    "activeTab",
    "scripting"
  ],
  "background": {
    "service_worker": "background.js"
  }
}

ついでにバージョンも 0.2 に上げました。

拡張機能を更新読み込みします。

「Page Redder」と同じく、拡張機能アイコンをクリックするとページ内容が書き換わり、リンクがすべて別タブ開きになる拡張機能ができました。

いちいちアイコンをクリックするのは面倒なので、自動で動くようにします。

ページを開いたら自動で動作する

また、すべてのページで動かれると困るので、JIRAページでだけ動くようにします。

background.js

const linkToNewTab = () => {
  document.querySelectorAll('a').forEach((elem) => {
    elem.setAttribute('target', '_blank');
  })
}

chrome.tabs.onUpdated.addListener(
  (tabId, changeInfo, tab) => {
    if (changeInfo.status === 'complete' && tab.url.startsWith('JIRAのアドレス')) {
      console.log('link change'); // 管理画面の「ビューを検証」リンクで起動するDevToolにログが出ます
      chrome.scripting.executeScript({
        target: { tabId: tabId },
        function: linkToNewTab
      });
    }
  }
)

manifest.json

{
  "name": "My JIRA",
  "action": {},
  "manifest_version": 3,
  "version": "0.3",
  "description": "JIRA内のリンクを別タブで開くようにする",
  "permissions": [
    "activeTab",
    "tabs",
    "scripting"
  ],
  "host_permissions": ["JIRAのアドレス"],
  "background": {
    "service_worker": "background.js"
  }
}

参考

まとめ

不便だな~は自分で解消できます!

改善ポイントを見つけたら、自分で便利ツールを作ってしまいましょう。

あとがき

勉強会の準備をして学んだこと。

  • いつの間にかマニフェストが v.3 になってた。
  • 最近気になっていた zenn を使ってみた。見た目が良い。

Discussion