📗

現在開いているタブを別の環境で開くChrome拡張機能を作る

2021/03/01に公開

概要

コンテキストメニューから環境を選択し、現在開いているタブのhostnameを書き換えて、再表示するChrome拡張機能を作成しました

成果物

指定した特定のページでコンテキストメニューが表示され、開く環境を選択することができます

ソースコード

https://github.com/meihei3/open-in-another-environment

環境

Requirements

  • chrome-extension-cli >= 0.2.1
  • node >= v12

Chrome Extension CLIは以下のコマンドでインストールできます

$ npm install -g chrome-extension-cli

実装

  1. Chrome拡張機能のベースを作成
  2. コンテキストメニューの表示
  3. 別環境のURLを読み込む
  4. Chromeへ拡張機能を読み込む

の順で説明していきます。

Chrome拡張機能のベースを作成

Chrome Extension CLIを使ってプロジェクトを作成します

$ chrome-extension-cli [project name]

Successと出てくれば、作成が正常に行われています

Success! Created [project name] at [current dir path]/[project name]
Inside that directory, you can run below commands:

  npm run watch
    Listens for files changes and rebuilds automatically.

  npm run build
    Bundles the app into static files for Chrome store.

We suggest that you begin by typing:

  1. cd [project name]
  2. Run npm run watch
  3. Open chrome://extensions
  4. Check the Developer mode checkbox
  5. Click on the Load unpacked extension button
  6. Select the folder [project name]/build

サンプルコードとしてpopupカウンターのコードが存在するので、それらを削除します

コンテキストメニューの表示

拡張機能でコンテキストメニューを表示するには、permissionscontextMenusを追加します

{
  ...
  "permissions": [
    "contextMenus"
  ]
}

次にbackground.jsに別の環境の設定を書いていきます

パラメータ 説明
id contextMenusをクリックした時のmenuItemId
title 表示される文字列
hostname 移動先のホスト
const ENV = {
  production: {
    id: 'production',
    title: 'Production',
    hostname: 'https://example.com',
  },
  staging: {
    id: 'staging',
    title: 'Staging',
    hostname: 'https://example.net',
  },
  development: {
    id: 'development',
    title: 'Development',
    hostname: 'https://example.edu',
  },
};

先程の環境の設定をもとに、コンテキストメニューを追加していきます

chrome.runtime.onInstalled.addListener(() => {
  const parentId = chrome.contextMenus.create({
    id: 'parent',
    title: '別の環境で開く',
    contexts: ['all'],
    documentUrlPatterns: [
      ENV.production.hostname + '/*',
      ENV.staging.hostname + '/*',
      ENV.development.hostname + '/*',
    ],
  });

  Object.values(ENV).forEach((_env) => {
    chrome.contextMenus.create({
      id: _env.id,
      title: _env.title,
      parentId: parentId,
    });
  });
});

chrome.runtime.onInstalled.addListener()は拡張機能がインストールされた時、一度だけ呼び出します

chrome.contextMenus.create()でコンテキストメニューを作成します

パラメータの説明は以下の通り (より詳しい情報はこちら)

パラメータ 説明
id contextMenusをクリックした時のmenuItemId
title 表示される文字列
parentId 親メニューのID(パラメータのidか、create()の返り値のどちらでも可)
contexts どの要素を選択した時に表示するか
documentUrlPatterns 指定したURLパターンだけコンテキストメニューを表示する

別環境のURLを読み込む

ページを移動するためにpermissionstabsを追加します

{
  ...
  "permissions": [
    "contexMenus",
    "tabs"
  ]
}

コンテキストメニューから選択した環境で開くように、background.jscontextMenusonClickedを設定します

const openIn = (hostname, pageUrl) => {
  const url = new URL(pageUrl);
  chrome.tabs.update(null, { url: hostname + url.pathname + url.search });
};
chrome.contextMenus.onClicked.addListener((info) => {
  switch (info.menuItemId) {
    case ENV.production.id:
      openIn(ENV.production.hostname, info.pageUrl);
      break;
    case ENV.staging.id:
      openIn(ENV.staging.hostname, info.pageUrl);
      break;
    case ENV.development.id:
      openIn(ENV.development.hostname, info.pageUrl);
      break;
    case 'parent':
      break;
    default:
      console.log('err: clicked undefined menu');
      break;
  }
});

chrome.contextMenus.onClicked.addListener()でコンテキストメニューをクリックした時のアクションを設定します
全てのコンテキストメニューのクリックで発火してしまうので、menuItemIdを使ってアクションを設定します

chrome.tabs.update()で指定したURLへ遷移します。location.hrefのような振る舞いをします(より詳しい情報はこちら

Chromeへ拡張機能を読み込む

作成した拡張機能をビルドします

$ npm run build

chrome://extensions/へ移動してデベロッパーモードをONにしておきます


「パッケージ化されていない拡張機能を読み込む」から先程ビルドした[project name]/buildを選択します

https://example.com/ にアクセスして、コンテキストメニューをが表示されていたら完成です

参考

Discussion