既読のリンクを非表示にするchrome拡張機能を作る
0. この投稿の概要
1. 機能の概要
自分が実装した拡張機能は以下のような構成になっています。今回初めて拡張機能を作ったので、私の構成は最適ではないと思いますが参考まで。
- google chromeの拡張機能アイコンをクリックすることで機能が動きます。
- まずbackground.jsがクリックイベントに反応して実行され、chromeの閲覧履歴から対象のURLを取得してlocal storageに保存、その後content.jsを実行します。*1
- content.jsでアクティブなタブのhtmlから特定のclassを持つリンクを抽出し、それが閲覧履歴に含まれる場合はdisplayプロパティをnoneにすることで非表示にします。
2. 実装例
フォルダ構成
- 以下の通りになっています。必要なコードは全部載せているので、コピーをして同様の構成を作り、chromeで読み込めば機能を使えます。読み込み方についてはchrome拡張機能のチュートリアルを参考にしてください。
- アイコン画像は何でもいいですが、私は同ページからダウンロードした画像をそのまま使っています。
.
├── background.js
├── content.js
├── images
│ ├── get_started128.png
│ ├── get_started16.png
│ ├── get_started32.png
│ └── get_started48.png
└── manifest.json
manifest.json
- 拡張機能の設定ファイルみたいなもので、必須のファイルです。拡張機能の名前や呼び出すスクリプト、アイコン画像などを設定します。
- 特に重要なのはpermissionです。ここで拡張機能がアクセスできる資源を指定しています。今回は閲覧履歴を取得するためのhistory、閲覧履歴を保存するためのstorage、webページを操作するためのactiveTab、スクリプトをページに追加するためのscriptingを許可しています。
{ "name": "Hide read link", "description": "Hide links from web page if you have already read them.", "version": "1.0", "manifest_version": 3, "background": { "service_worker": "background.js" }, "permissions": ["storage", "activeTab", "scripting", "history"], "action": { "default_title": "Click", "default_icon": { "16": "/images/get_started16.png", "32": "/images/get_started32.png", "48": "/images/get_started48.png", "128": "/images/get_started128.png" } }, "icons": { "16": "/images/get_started16.png", "32": "/images/get_started32.png", "48": "/images/get_started48.png", "128": "/images/get_started128.png" } }
background.js
- イベントに反応して実行されるスクリプトです。
let microseconds3Days = 1000 * 60 * 60 * 24 * 3; var threeDaysAgo = (new Date).getTime() - microseconds3Days; // Execute when the icon is clicked. chrome.action.onClicked.addListener((tab) => { storeHistory(tab); }); function storeHistory(tab) { chrome.history.search({ "text": "https://pairs.lv/user/profile/", "startTime": threeDaysAgo, "maxResults": 10000, }, function(historyItems) { let historyList = []; for (let i = 0; i < historyItems.length; ++i) { let url = historyItems[i].url; let url_split = url.split("/"); // Store only profile ID historyList.push(url_split[url_split.length-1]); }; chrome.storage.local.set({ historyList }); chrome.scripting.executeScript({ target: {tabId: tab.id}, files: ['content.js'], }); }); };
- 拡張機能のアイコンをクリックするとchrome.action.onClicked.addListenerで指定した関数が実行されます。
- 今回は3日分のペアーズのプロフィール閲覧履歴をchrome.history.searchで取得しています。
- URLは表示される場所によって変わるようなので、プロフィール固有と思われるIDをURLから抽出しています。そのリストをchrome.storage.local.setで保管しています。
- 最後にchrome.scripting.executeScriptでcontent.jsをwebページに埋め込みます。
content.js
- chrome.storage.local.getで保存しておいた履歴データを読み込む意外は普通のjavascriptコードです。対象リンクのクラスはchromeのデベロッパーツールで確認しました。
function deleteReadLinks() { chrome.storage.local.get("historyList", ({ historyList }) => { let historySet = new Set(historyList) let profiles = document.getElementsByClassName("css-opde7s"); for (let i = 0; i < profiles.length; ++i) { if ("href" in profiles[i]) { let url_split = profiles[i].href.split("/"); if (historySet.has(url_split[url_split.length-1])) { profiles[i].style.display = "none"; } } }; }); } deleteReadLinks();
3. 参考
- Getting started - Chrome Developers: Chrome公式ページのチュートリアル。拡張機能開発が初めての場合は取りあえずなぞってみると良いと思います。拡張機能に関する書籍やwebページは多くないので、基本的に公式ページを参考にすることになるかと思います。