LoginSignup
14
14

More than 5 years have passed since last update.

Chromeブラウザ拡張機能を作ってみた

Last updated at Posted at 2018-06-19

一から作ってみた時の作業記録みたいなもの。

ディレクトリを作る

適当にディレクトリを作る

manifest.jsonを作る

以下のような内容でプラグインを作ってディレクトリに入れる。

manifest.json
{
  "name": "テストプラグイン",
  "version": "0.1",
  "description": "テストプラグイン説明",
  "manifest_version": 2
}

manifest.xmlの詳しい書き方は公式サイト参照。

拡張機能を入れてみる

Chromeでchrome://extensions/にアクセスし、右上から「デベロッパーモード」を有効にする。
b1.PNG

「パッケージ化されていない拡張機能を読み込む」から先程作ったディレクトリを指定する。
b2.PNG

するとこんな感じで読み込まれる。
b3.PNG

拡張のアイコンを設定してみる

manifest.jsonファイルに以下のように書き足す。

manifest.json
{
  :,
  "icons": {
    "16": "images/icon16.png",
    "32": "images/icon32.png",
    "48": "images/icon48.png",
    "128": "images/icon128.png"
  }
}

アイコンはもちろん対象の場所に用意する。
その後再度「読み込む」。
するとアイコンが適用される。
b1.PNG

ちなみに各アイコンのサイズは以下の通りらしい。

サイズ 使われる場所
16x16 拡張機能ページのfavicon
32x32 Windowsの場合、変倍がかかってしまうのでこのアイコンを48x48アイコンの代わりに利用しているらしい
48x48 拡張機能の管理ページに表示されるアイコン
128x128 Chrome ウェブストアで表示されるアイコン

ログだけ出力する機能を作る

適当にGitHubのユーザー名を書き換えるだけのものを作ってみる。
manifest.jsonファイルに以下のように書き足す。

manifest.json
{
  :,
  "background": {
    "scripts": ["js/background.js"],
    "persistent": false
  }
}

そして以下のようなJavaScriptを書く。

js/background.js
chrome.runtime.onInstalled.addListener(function (details) {
  console.log(details.reason);
});

その後再度「読み込む」。
すると「バックグラウンドページ」からDevToolsを起動するとupdateとログが出力されている。
b1.PNG
chrome.runtime.onInstalledは拡張機能がインストールされた時に呼ばれるイベントで、この時に初期化をしたりする。

これはバックグラウンドページと呼ばれている。
お察しの通り、配列なので複数のスクリプトを列挙することもできる。
persistentは基本的にfalseにして残り続けないようにする。

GitHubのページで動くようにする

github.comのタブの情報が得られるように、manifest.jsonファイルに以下のように書き足す。

manifest.json
{
  :,
  "permissions": ["tabs", "https://github.com/*"]
}

詳細な権限の一覧は公式サイト参照。実はtabsが入っていないようだけど…
URLのマッチングについてはこちら

background.jsをこんな感じで書き換える。

js/background.js
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete') {
    console.log(tabId);
    console.log(changeInfo);
    console.log(tab);
  }
});

するとページをリロードする毎にこんな感じのログが出力される。
b2.PNG

GitHubのauthorを書き換えてみる

この部分を書き換える。
b3.PNG

authorノードの情報を取得する。
authorを右クリック→検証。
b6.png

更にDev Toolsから右クリック→Copy→Copy selector。
b5.png

background.jsからタブ内でbase.jsを呼ぶようにする。

js/background.js
chrome.tabs.onUpdated.addListener(function (tabId, changeInfo, tab) {
  if (changeInfo.status === 'complete') {
    chrome.tabs.executeScript(tab.id, { file: "js/base.js" });
  }
});

chrome.tabs.executeScriptは、そのタブで指定したスクリプトを実行させる。
バックグラウンドページのスクリプトはそのページのスクリプトとは分離されていてページ内の情報を読み書きできないので、こういうかたちになる。

base.jsでは先程取得したセレクタをそのままquerySelectorに貼り付けて利用する。

js/base.js
var authorNode = document.querySelector('#js-repo-pjax-container > div.pagehead.repohead.instapaper_ignore.readability-menu.experiment-repo-nav > div > h1 > span.author > a');
if (authorNode) {
  authorNode.innerHTML = 'hoge';
}

できた :tada:
b1.PNG

設定画面を作ってみる

次は設定画面を作ってみる。hogeだけだと微妙なので自分で設定できるようにする(そういう問題ではないが)。

manifest.json
{
  :,
   "options_page": "html/option.html"
}

適当にHTMLの設定画面を作る。

html/option.html
<!doctype html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB" crossorigin="anonymous">
    <title>設定</title>
  </head>
  <body>
    <div class="container">
      <h1>設定</h1>
      <form>
        <div class="form-group">
          <label for="author">Author</label>
          <input class="form-control" type="text" name="author" id="author">
        </div>
        <div class="form-group">
          <button class="btn btn-default" name="save" type="button">更新</button>
        </div>
      </form>
    </div>
  </body>
</html>

再読込してから「詳細」へ移動する。
b3.png

「拡張機能のオプション」ができているので、そこから「↗」マークをクリックする。
b4.PNG

すると先程作ったページが閲覧できる。
b2.PNG

次に、設定を読み書きしたいのでローカルストレージを利用する。
manifest.jsonに権限を追加してローカルストレージにアクセスできるようにする。

manifest.json
{
  :,
  "permissions": ["tabs", "https://github.com/*", "storage"]
}

オプションのページでJavaScriptを読み込む。

html/option.html
:
  <script type="text/javascript" src="/js/option.js"></script>
  <title>設定</title>
:

読み込み先のJavaScriptを書く。

js/option.js
document.addEventListener('DOMContentLoaded', function () {
    chrome.storage.local.get("github_author", function (item) {
        const author = item.github_author;
        if (author) {
            document.querySelector('[name="author"]').value = author;
        }
    });

    document.querySelector('[name="save"]').addEventListener('click', function (e) {
        const author = document.querySelector('[name="author"]').value;
        chrome.storage.local.set({ "github_author": author }, function () {
            alert('saved');
        });
    });
});

上半分でローカルストレージに値があったらフォームに初期値として入力している。
下半分で「保存」ボタン押下時にローカルストレージに値を保存している。
これで設定画面が機能するようになった。

ちなみにchrome.storage.localの場合、ローカルに保存されるのでマシンごとに値が異なる。
アカウントごとに同期したい場合は変わりにchrome.storage.syncを使うと良いらしい。

仕上げにbase.jsで値をローカルストレージから呼ぶように変更する。

js/base.js
var authorNode = document.querySelector(
  "#js-repo-pjax-container > div.pagehead.repohead.instapaper_ignore.readability-menu.experiment-repo-nav > div > h1 > span.author > a"
);
if (authorNode) {
  chrome.storage.local.get("github_author", function(item) {
    const author = item.github_author;
    if (author) {
      authorNode.innerHTML = author;
    }
  });
}

拡張機能を再読込し、github.comのページにアクセスしてみる。
すると設定画面で設定した値に書き換わるようになる。
b1.PNG

右上のメニューに出してみる

更にmanifest.jsonに書き足す。

manifest.json
{
  :,
  "browser_action": {
  }
}

するとこんな感じでアイコンが出る。何も指定していないので無反応。
b1.png

ポップアップするHTMLを指定する。

manifest.json
{
  :,
  "browser_action": {
    "default_popup": "html/popup.html"
  }
}

popup.htmlの中身はとりあえずほぼ同じにする。

html/popup.html
<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.1/css/bootstrap.min.css" integrity="sha384-WskhaSGFgHYWDcbwN70/dfYBj47jz9qbsMId/iRN3ewGhXQFZCSftd1LZCfmhktB"
    crossorigin="anonymous">
  <script type="text/javascript" src="/js/option.js"></script>
  <title>設定</title>
</head>

<body>
  <div class="container" style="width: 200px">
    <form>
      <div class="form-group">
        <label for="author">Author</label>
        <input class="form-control" type="text" name="author" id="author">
      </div>
      <div class="form-group">
        <button class="btn btn-default" name="save" type="button">更新</button>
      </div>
    </form>
  </div>
</body>

</html>

するとこんな感じでポップアップする。
b1.png

右クリックメニューを出してみる

次に右クリックメニュー(コンテキストメニュー)に追加してみる。
更に権限を足す。

manifest.json
{
  :,
  "permissions": [..., "contextMenus"]
}

background.jsに以下のように書き足す。

background.js
var parentId = chrome.contextMenus.create({
  "id": "sampleParent",
  "title" : "サンプル親"
});

するとこんな感じになる。

b2 - コピー.png

更にサブメニューを追加してみる。

background.js
chrome.contextMenus.create({
  "id": "sampleChild",
  "title" : "サンプル子",
  "parentId" : parentId
});

するとこんな感じ。

b2.png

クリックした時のイベント登録はこんな感じ。
これでサンプル子をクリックした時にアラートダイアログが表示される。

chrome.contextMenus.onClicked.addListener( function(info, tab) {
  alert(info.menuItemId + "をクリック");
});

参考

Getting Started Tutorial - Google Chrome
C:\Users\user_name\AppData\Local\Google\Chrome\User Data\Default\Extensionsにも自分のブラウザに入っている拡張機能がたくさんあるので、それらを参考にすると良いかもしれない。

14
14
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
14
14