2025/02/19

テクノロジー

サクッとChromeの拡張機能を作る方法

この記事の目次

    今回は、GoogleChromeの拡張機能をサクッと作ってみようと思います。

    概要

    Google Chromeの拡張機能を作成する際には、主に3つの重要要素があります。

    • ポップアップ(popup)
    • バックグラウンドスクリプト(background)
    • コンテントスクリプト(content script)

    ポップアップ

    ポップアップは、ユーザーがChromeの拡張機能アイコンをクリックしたときに表示されるものです。

    参考: DeepL

    コンテントスクリプト

    コンテントスクリプトは、ユーザーが閲覧しているウェブページに直接挿入されるJavaScriptです。ページのDOMを操作したり、ページからデータを取得したりするために使用されます。

    参考: Dimentions (青い線 と 19px*214pxのツールチップ)

    バックグラウンドスクリプト

    バックグラウンドスクリプトは、拡張機能の背後で動作し、イベント駆動型で特定のイベントが発生したときにのみ起動します。バックグラウンドスクリプトは、APIへのアクセスやデータの管理、他のスクリプトとの通信を担当します。

    コンテントスクリプトを発火させる時にも使用していたりします。

    必要なファイル

    この後のチュートリアルでは、chrome-extension-v3-starter を参考にして作成していきます。
    このリポジトリのファイルを参考に細くしてみると大体こんな感じです。

    my-chrome-extension/
    ├── manifest.json // ---------------- 拡張機能の概要やファイル定義を書く
    ├── logo/ // ------------------------ アイコン画像
    │   └── (ロゴ画像ファイルなど)
    ├── popup/ // ----------------------- ポップアップを書く
    │   ├── index.html
    │   └── style.css
    ├── foreground.js // ---------------- コンテンツスクリプトを書く
    └── service-worker.js // ------------ バックグラウンドスクリプトを書く
    

    チュートリアル (スクリーンショット撮れる拡張機能)

    ポップアップボタンまたは、ショートカットキーでスクリーンショットを取れる拡張機能を作成してみようと思います。

    ※開発のための準備に関しては割愛します。(こちらを参照してください。)

    ①コマンドを実行して、スクリーンショットのバイナリをコンソールに出力させる

    1. manifest.json にコマンドを追加する
    2. バックグラウンドスクリプト (service-worker.js) にて、画面キャプチャを書く

    manifest.json には、コマンドを追加するのと、スクリーンショットをするために、permissionを更新しています。①~③で更新が必要な箇所をまとめて追加していきます。気になる人は、公式ドキュメントなどを参照してみてください。

    manifest.json

    {
      "manifest_version": 3,
      "name": "Chrome Extension v3 Starter",
      "description": "A minimal example of a chrome extension using manifest v3",
      "version": "0.0.1",
      "icons": {
        "16": "logo/logo-16.png",
        "48": "logo/logo-48.png",
        "128": "logo/logo-128.png"
      },
      "options_page": "settings/settings.html",
      "action": {
        "default_title": "Chrome Addon v3 Starter",
        "default_popup": "popup/popup.html"
      },
      "permissions": ["tabs", "commands", "activeTab"], // update permission
      "host_permissions": ["*://*/*"],
      "background": {
        "service_worker": "service-worker.js"
      },
      "content_scripts": [
        {
          "js": ["foreground.js"],
          "matches": ["https://*/*"] // update url pattern
        }
      ],
      // ↓ add commands
      "commands": {
        "take-screenshot": {
          "suggested_key": {
            "default": "Ctrl+Shift+F",
            "mac": "Command+Shift+F"
          },
          "description": "Take a screenshot of the current page"
        }
         // ↑ add commands
      }
    }

    バックグラウンドスクリプト(service-worker.js)も修正します。manifest.json で定義した、"take-screenshot"を確認して、スクリーンショットを行い、バイナリを出力しています。

    service-worker.js

    // add ↓
    chrome.commands.onCommand.addListener((command) => {
    if (command === "take-screenshot") {
    chrome.tabs.captureVisibleTab(null, {}, (image) => {
    console.log(image);
    });
    }
    });
    // add ↑

    こんな感じになります。

    ※コマンドがうまく反映されない人は、ショートカットの設定から設定してみてください。

    ② コンテンツスクリプトを使用して、開いているWebサイトで、スクリーンショットを表示させる

    1. コンテンツスクリプトにて、messageAPIを用いて、スクリーンショットを発火させる。
    2. 発火したスクリーンショットをWebサイトにレンダリングする。

    先ほど、バックグラウンドスクリプトの、take-screenshotコマンド実行時の関数を修正します。
    内容としては、スクリーンショットを行い、そのデータをsendMessageで渡そうとしています。

    service-worker.js

    // update ↓
    chrome.commands.onCommand.addListener(async (command) => {
    if (command === "take-screenshot") {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    chrome.tabs.captureVisibleTab(tab.windowId, { format: "png" }, (dataUrl) => {

    if (chrome.runtime.lastError) {
    console.error("Error capturing screenshot:", chrome.runtime.lastError);
    return;
    }
    console.log("Screenshot captured, sending data URL");
    chrome.tabs.sendMessage(tab.id, { type: "screenshot", dataUrl });
    });
    }
    });
    // update ↑

    sendMessageで渡ってきたものを検知して、コンテンツスクリプト(foreground.js)にて、イベントを発火させています。
    表示しているWebサイトの左下に撮ったスクリーンショットを同じものをレンダリングしています。

    foreground.js

    // add ↓
    chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
    console.log("Received message in foreground script", message);

    if (message.type === "screenshot") {
    const img = document.createElement("img");
    img.src = message.dataUrl;
    img.onload = () => console.log("Image loaded successfully");
    img.onerror = (e) => console.error("Error loading image:", e);
    img.style.position = "fixed";
    img.style.bottom = "10px";
    img.style.left = "10px";
    img.style.width = "400px";
    img.style.height = "300px";
    img.style.zIndex = "10000";
    img.style.border = "2px solid #000";
    document.body.appendChild(img);
    }
    });
    // add ↑

    コマンドを実行すると、下記のよう左側に表示されます。

    ③ポップアップから実装したスクリーンショットの機能を発火させる

    1. ポップアップのHTMLとJSを修正
    2. バックグラウンドスクリプトで、スクリーンショットの機能を発火させるように設定

    ポップアップ用のHTMLを更新します。JSのインポートとボタンの追加を行っています。

    popup/popup.html

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <link rel="stylesheet" href="popup.css">
        <title>Chrome Addon v3: popup</title>
        <script src="/popup/popup.js"></script> <!-- add import -->
    </head>
    <body>
        <button id="take-screenshot">キャプチャする</button> <!-- add button -->
    </body>
    </html>

    新しくJSを追加します。追加したボタンにクリックイベントを付与して、take-screenshot のメッセージを送るように設定します。

    popup/popup.js

    // ↓ add click event
    document.addEventListener('DOMContentLoaded', function () {
      document.getElementById('take-screenshot').addEventListener('click', () => {
        console.log('take-screenshot');
        chrome.runtime.sendMessage({ name: 'take-screenshot' });
      });
    });

    バックグラウンドスクリプトで、新しく関数を追加します。take-screenshot のメッセージを感知して、スクリーンショット機能を発火させています。(中身の処理は②で書いた関数とほとんど同じ)

    service-worker.js

    // ↓ add
    chrome.runtime.onMessage.addListener(async (request, sender, sendResponse) => {
    if (request.name === "take-screenshot") {
    const [tab] = await chrome.tabs.query({ active: true, currentWindow: true });
    chrome.tabs.captureVisibleTab(tab.windowId, { format: "png" }, (dataUrl) => {

    if (chrome.runtime.lastError) {
    console.error("Error capturing screenshot:", chrome.runtime.lastError.message);
    return;
    }
    console.log("Screenshot captured, sending data URL");
    chrome.tabs.sendMessage(tab.id, { type: "screenshot", dataUrl });
    });
    }
    });
    // ↑ add

    chrome.commands.onCommand.addListener(async (command) => {
    ...

    こんな感じで実行すると、ポップアップからもスクリーンショット機能を発火することができるようになります。

    チュートリアルは以上です。

    まとめ

    概念を理解すると意外と簡単に作れるので、今後業務効率化できそうなところがあれば、自作してみようと思います。
    最後まで見ていただきありがとうございました🙇

    ※本記事は2025年02月時点の情報です。

    著者:マイナビエンジニアブログ編集部