GitHub上で動くChrome拡張では、単純にmanifest.jsonで指定するだけではPRやIssueに遷移した際に毎回Content Scriptsを発火させることができません。
発火させたい
Content Scriptsはbackgroundからメッセージを受け取った際に発火するようにしておき、backgroundではchrome.runtime.onMessageイベントによって、メッセージを送信するようにしました。
遷移時にタブのURLが変わるので、このURLをコールバックの中で受け取り、各ページのURLパターンにマッチした場合に、PRやIssueのページに遷移したとみなしています。
ただし、PRの一覧ページにクエリパラメータ付きで遷移する場合、URL的にはIssue一覧ページに遷移した後でPR一覧ページにリダイレクトするようで、この場合のみIssueの一覧に遷移した後でPRの一覧に遷移する動作をしてしまう問題が残っています。
サンプル
manifest.json
{
"manifest_version": 2,
"name": "Sample for GitHub",
"version": "1.0.0",
"description": "Sample Chrome extension for GitHub issue and pull request.",
"permissions": ["https://github.com/*"],
"background": {
"scripts": ["scripts/background.js"],
"persistent": false
},
"content_scripts": [
{
"matches": ["https://github.com/*"],
"run_at": "document_end",
"js": ["scripts/main.js"]
}
]
}
main.js
`use strict`;
// GitHub has async compile dom so kick script by ajax http access via background
chrome.runtime.onMessage.addListener(function(message, sender, sendResponse) {
console.log(message);
return;
});
メッセージを受け取っています。処理を実行する場合、ログを出力している部分に処理を記述します。messageには、遷移したページの種別が入力されます。
background.js
`use strict`;
class PageType {
constructor(urlPattern, type) {
this.urlPattern = urlPattern;
this.type = type;
}
}
class PageTypeMap {
constructor(pageTypes) {
this.pageTypes = pageTypes;
}
getMatchType(url) {
let result = this.pageTypes.filter(t => t.urlPattern.test(url));
if (result.length === 0) {
return null;
}
return result[0].type;
}
}
const PR_LIST_PATH_REGEX = /^https:\/\/github.com\/.*\/pulls.*/;
const PR_FILES_PATH_REGEX = /^https:\/\/github.com\/.*\/pull\/[0-9]+\/files.*/;
const PR_COMMITS_PATH_REGEX = /^https:\/\/github.com\/.*\/pull\/[0-9]+\/commits.*/;
const PR_CHECKS_PATH_REGEX = /^https:\/\/github.com\/.*\/pull\/[0-9]+\/checks.*/;
const PR_PATH_REGEX = /^https:\/\/github.com\/.*\/pull\/[0-9]+$/;
const ISSUE_LIST_PATH_REGEX = /^https:\/\/github.com\/.*\/issues[^\/]*$/;
const ISSUE_PATH_REGEX = /^https:\/\/github.com\/.*\/issues\/[0-9]+/;
const PAGE_TAPES = [
new PageType(PR_LIST_PATH_REGEX, "PR_LIST"),
new PageType(PR_FILES_PATH_REGEX, "PR_FILES"),
new PageType(PR_COMMITS_PATH_REGEX, "PR_COMMITS"),
new PageType(PR_CHECKS_PATH_REGEX, "PR_CHECKS"),
new PageType(PR_PATH_REGEX, "PR"),
new PageType(ISSUE_LIST_PATH_REGEX, "ISSUE_LIST"),
new PageType(ISSUE_PATH_REGEX, "ISSUE")
];
const PAGE_TYPE_MAP = new PageTypeMap(PAGE_TAPES);
chrome.tabs.onUpdated.addListener(function(tabId, changeInfo, tab) {
if (changeInfo.url == null) {
return;
}
kick(PAGE_TYPE_MAP.getMatchType(changeInfo.url));
});
function kick(type) {
chrome.tabs.query({ active: true, currentWindow: true }, function(tabs) {
chrome.tabs.sendMessage(tabs[0].id, type, function(response) {});
});
}
chrome.tabs.onUpdatedに対して処理を定義しています。ここでは、URLパターンに対してページの種別を判定し、Content Scriptsにメッセージとして送信しています。
各ソースはこちらです。