勉強したことのメモ

Webエンジニア / プログラマが勉強したことのメモ。

指定サイトのaタグにblank化、クリック済みの場合は文字色を変更するブラウザ拡張機能の作成方法

  拡張機能 ブラウザ

ポップアップ内にテキストエリアを設置し、そちらにドメインを入力すると該当サイトのaタグは全て別タブで開くようにし(target="_blank")、さらにクリック済みの場合はaタグの文字色を変更するといった内容のChrome / Firefox用拡張機能(アドオン)を作成したい。以下に対応方法をメモ。

 

事前準備

(必要に応じて)アイコン画像の作成

アイコン画像ジェネレーター等でアイコン画像を作成しておく。今回は128x128サイズのpng画像を「128.png」というファイル名で作成した。

ディレクトリの用意

以下ディレクトリをPC内に作成しておく。以降拡張機能に関するファイルはlink_change内に作成する。

 

拡張機能の作成

拡張機能のための各種設定ファイル(manifest.json)

{
    //開発仕様
    "manifest_version": 3,

    //拡張機能名
    "name": "リンク変更",

    //バージョン
    "version": "1.0",

    //拡張機能の説明
    "description": "クリック済みリンクの色を変更&リンクを別タブで開く",

    //アイコン設定
    "icons": {
        "128": "icons/128.png"
    },

    //拡張機能APIの使用設定
    "permissions": [
        //ユーザーデータの保存、取得、変更
        "storage",

        //ブラウザのタブシステムを使用
        "tabs"
    ],

    //拡張機能が操作できるページ
    "host_permissions": [
        //全てのURL
        "<all_urls>"
    ],

    //ツールバー側のアイコンとポップアップの設定
    "action": {
        //アイコンファイルのパス
        "default_icon": "icons/128.png",

        //ポップアップ(ダイアログ)のパス
        "default_popup": "popup.html"
    },

    //特定のブラウザ専用の設定
    "browser_specific_settings": {
        //firefox用設定
        "gecko": {
            //ユニークID(実際のメールアドレスにはしない)
            "id": "link-change@sample.org",

            //データ収集に関する設定
            "data_collection_permissions":{
                "required": ["none"]
            }
        }
    },

    //対象サイトと読み込むファイルの設定
    "content_scripts": [
        {
            //対象サイトを全てに設定
            "matches": ["<all_urls>"],

            //使用するJavaScriptファイルのパス
            "js": ["main.js"]
        }
    ]
}

メイン処理用のJS(main.js)

console.log('main.js');

//ストレージからデータを取得
chrome.storage.sync.get(

    //データが存在しない場合の初期値を空配列にする
    { target_domain: [] }, 

    //完了時のコールバック関数
    function( items ){

        //登録されているドメイン一覧
        const domain_list = items.target_domain;

        //ドメインが登録されていない場合は終了
        if( !domain_list.length ){
            return false;
        }

        //現在表示中のホスト名
        const current_host = window.location.hostname;

        //登録されているドメイン一覧内に現在表示中のホスト名が存在しない場合は終了
        if( !domain_list.includes(current_host) ){
            return false;
        }

        //CSSを作成
        const style = document.createElement('style');

        //クリック済みaタグの文字色を変更
        style.textContent = `
            a:visited {
                color: #ccc !important;
            }
        `;

        //headタグの末尾にCSSを挿入
        document.head.appendChild(style);

        //リンクを_blankに変更
        document.querySelectorAll('a').forEach(
            function(a){
                a.setAttribute('target', '_blank');
            }
        );
    }
);

ポップアップ側処理用のJS(popup.js)

console.log('popup.js');

//ダイアログの保存ボタンをクリック時
document.getElementById('save').addEventListener('click', function(){

    //入力されたドメイン
    let domain_text = document.getElementById('domains').value;

    //改行で区切って配列化
    let lines = domain_text.split(/\r\n|\n/);

    //結果を入れる配列
    let domains = [];

    for( let i = 0; i < lines.length; i++ ){

        //前後のスペースを削除
        let trimmed = lines[i].trim();

        //文字が入っている場合、配列に追加
        if( trimmed.length ){
            domains.push(trimmed);
        }
    }

    //ストレージにデータ登録
    chrome.storage.sync.set(

        //target_domainに入力された内容を配列形式で格納
        { target_domain: domains }, 

        //完了時のコールバック関数
        function(){

            //結果表示エリアにメッセージ表示
            const result = document.getElementById('result');
            result.innerHTML = '保存しました。<br>ページをリロードします。';

            //メッセージを読む時間分遅延処理
            setTimeout(() => {

                //メッセージ非表示
                result.textContent = '';

                //指定されたプロパティを持つすべてのタブを取得
                chrome.tabs.query(
                    {
                        //タブがアクティブのもの
                        active: true, 

                        //タブが現在のウィンドウにあるもの
                        currentWindow: true 
                    },
                    function( tabs ){

                        //タブが存在する場合
                        if( tabs && tabs[0] && tabs[0].id ){

                            //リロード
                            chrome.tabs.reload(tabs[0].id);
                        }
                    }
                );
            }, 1000);
        }
    );
});

//ダイアログの読み込みが完了した際
document.addEventListener('DOMContentLoaded', function(){

    //ストレージからtarget_domainを取得
    chrome.storage.sync.get(

        //データが存在しない場合の初期値を空配列にする
        { target_domain: [] },

        //完了時のコールバック関数
        function( items ){

            //ダイアログの入力欄にtarget_domainを改行区切りで挿入
            document.getElementById('domains').value = items.target_domain.join('\n');
        }
    );
});

ポップアップ画面のHTML(popup.html)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link href="popup.css" rel="stylesheet">
</head>
<body>
    <h1>対象サイト設定</h1>
    <p>適用するドメイン(1行1件):</p>
    <textarea id="domains" placeholder="test.com"></textarea>
    <button id="save">保存</button>
    <span id="result"></span>

    <script src="popup.js"></script>
</body>
</html>

ポップアップ画面のCSS(popup.css)

body{
    width: 280px;
    padding: 12px;
    font-family: sans-serif;
    font-size: 13px;
}
textarea{
    width: 100%;
    height: 80px;
    box-sizing: border-box;
    margin-bottom: 8px;
}
button{
    width: 100%;
    padding: 6px;
    cursor: pointer;
}
#result{
    display: block;
    margin-top: 6px;
    color: #4169e1;
    text-align: center;
}

補足

ディレクトリ構造とファイル設置状況

以下のようになっていればOK。

link_change/
├── icons/
│   └── 128.png
├── main.js
├── manifest.json
├── popup.css
├── popup.html
└── popup.js

拡張機能のインストール

拡張機能のインストール方法は過去記事を参照。

確認方法

確認方法は過去記事を参照。

Firefoxで動作しない場合

Firefoxは権限の問題で動作しない場合がある。

その場合は「about:addons」を開き、当該アドオンを選択→権限とデータタブを開く→「保存されたすべてのウェブサイトのユーザーデータへのアクセス」をONにすること。

 

リファレンス

chrome.storage

https://developer.chrome.com/docs/extensions/reference/api/storage?hl=ja

chrome.tabs

https://developer.chrome.com/docs/extensions/reference/api/tabs?hl=ja

 - 拡張機能 ブラウザ

  関連記事

ChromeとFirefoxにてHello World表示する拡張機能(アドオン)を作成する方法
ChromeとFirefoxにてHello World表示する拡張機能(アドオン)を作成する方法

Google Chrome / Firefoxの拡張機能(アドオン)を作ってみた ...

ChromeとFirefoxにて拡張機能(アドオン)にポップアップを追加する方法
ChromeとFirefoxにて拡張機能(アドオン)にポップアップを追加する方法

先日ChromeとFirefoxにてHello World表示する拡張機能(アド ...