Chrome拡張機能をAngularで作ってみた

Blog Single

今朝見かけた記事で、Chromeの拡張機能の改竄について取り上げられていました。

クローム拡張機能の「MEGA」が改ざん、ユーザーのモネロや個人情報を盗む | Cointelegraph

これを読んでいて、「そういえば拡張機能作ったことがなかったな…」と思いまして。
どういうものかを知るついでに、簡単なものですが作成してみました!
ただ単にJavaScriptで作るのは面白みに欠けるので、今回はAngularを使用します。

ベースの作り方は以前techに投稿された記事をご覧ください。
Chrome拡張機能を自作する

実装環境

  • Angular v6.1.7(ちょうど本日9/6に更新されてました!)
  • angular/cli v6.1.5

あらかじめAngularのプロジェクトを新しく作成しておきます。

基本設定

manifest.jsonの設定

Chrome拡張機能に必須であるManifest Fileは、以下の場所に配置します。

[Angular Project]/src/manifest.json

manifest.jsonはbuild後にも必要になるのでangular.jsonに追加します。

// angular.json
{
  // ...
  "projects": {
    "project_name": {
      "architect": {
        "build": {
          "options": {
            // ...
            "assets": [
              "src/favicon.ico",
              "src/assets",
              "src/manifest.json" // 追記
            ],
          },
        }
      }
    }
  }
}

その他設定

@types/chromeのインストール
開発時に便利なパッケージ@types/chromeがあるようなので、上のサイトの手順を基にインストールしましょう。
(現在の最新versionは0.0.72

ページ作成

今回は拡張アイコンクリック時のpopupページと、常に起動するbackgroundページを作ります。
ページはAppRoutingModuleでわけていきます。

// src/app/app-routing.module.ts 例
const routes: Routes = [
    {
        // popupページ
        path: 'popup',
        component: PopupComponent
    },
    {
        // backgroundページ
        path: 'event',
        component: EventComponent
    },
    {
        path: '**',
        redirectTo: 'popup',
        pathMatch: 'full'
    }
];

@NgModule({
    imports: [RouterModule.forRoot(routes, {useHash: true})],
    exports: [RouterModule]
})
export class AppRoutingModule { }

あとはこのルーティングをmanifest.jsonに設定していきます。

// src/manifest.json
{
    // ...
    "content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'",
    "browser_action": {
        "default_popup": "index.html#/popup"
    },
    "background": {
        "page": "index.html#/event",
        "persistent": true
    },
    "permissions": [
        "tabs"
    ]
}

今回はChromeのtabsを使用したいのでpermissionsに設定、
content_security_policyはjsファイルの実行エラー回避のために入れています。
backgroundページは常に起動しているようにするため、persistentにtrueを設定しました。
これがfalseの場合はeventページとして認識され、イベントが完了すると停止してしまいます。

ビルド実行、Chromeに設定

以下のコマンドでビルドを実行します。

ng build --aot

あとはChromeに作成したものを読み込ませるだけです!
読み込むのはビルド後のoutputディレクトリdist/[projectName]を選択します。
Chromeの右上のアイコンを押して以下のようなポップアップが表示がされていれば完成です!

作成した拡張機能

今回作成したのは、指定日時に対象のサイトを自動で開く機能です。
出勤・退勤時に勤怠管理システムにアクセスしたり、毎日作業報告書をまとめるページを開く場合に、これを設定しておくと忘れることがなくなるかなと思い作りました。
そもそも忘れなければ済む話ではありますが←

popupページではスケジュールリストの一覧確認・登録・削除ができます。
backgroundページでは、一定時間経過毎にスケジュールリストの確認と、サイトを開く処理をさせています。
ページの構成・機能自体は結構単純なものになっています。

ページを開く際には新規タブを作成する処理を書いています。
最初に@types/chromeパッケージをインストールしたので、コードは以下のようにかなり短く書くことができます。

// event.component.ts
const url = 'https://www.fox-hound.tech/';
chrome.tabs.create({url: url});

詳しいコードはGitHubに公開しておりますので、良ければ試しに使ってみてください!
使用方法はREADMEに記載しております。
backgroundページが常に起動していて処理が重たくなる可能性がありますので、使わないときは無効にしておくことをお勧めします汗
mao-miyaji/chrome_sou

最後に

Chromeユーザーとしては拡張機能は便利で非常にいいと思います。
公開されているものも多いので試しに色々使用してみるのも面白そうですね!
Chrome ウェブストア – 拡張機能
自作に関しては、JavaScriptで簡潔に書くことができるといった印象でした。
私自身拡張機能の作成は初でしたので今回は簡単な機能のものになってしまいましたが、次はもっと複雑な処理を含んだ機能を作成しようと思います!

参考

Posted by Mao Miyaji
千葉にある夢の国を愛して止まない、元「魚のお姉さん」のエンジニア。PHP, TypeScriptメインで、暇さえあれば色々な言語を一かじり。

Other Posts: