Chromeの拡張
やってみたいことがあるので、Chromeの拡張の作り方を調べる。
チュートリアルやる
チュートリアルがあったので、チュートリアルをやる。ここの背景色を変えるやつみたいだけど、せっかくなのでこのブログのを変えたい。
manifest.json
{
"name": "Getting Started Example",
"version": "1.0",
"description": "Build an Extension!",
"manifest_version": 2
}
これだけでもう拡張として認識されるみたい。
なった。
background.js
落としてきて、同じフォルダに入れる。あと、manifestのdescription以下に
"background": {
"scripts": ["background.js"],
"persistent": false
},
追記することでbackground.jsを使いますよーという意味になるみたい。persistantは知らん。background.jsの中身は
'use strict';
chrome.runtime.onInstalled.addListener(function() {
chrome.storage.sync.set({color: '#3aa757'}, function() {
console.log("The color is green.");
});
});
なんですが、はっきり言ってさっぱり意味が分からん。うーんと’use strict’;がコードを厳格に書かなきゃいけないみたいなモードの文言みたい。chrome.runtime.onInstalled.addListenerが拡張がインストールされた時とかに走るみたいなやつ。chrome.storage.sync.setがchrome内にデータを保存するやつで、syncが同期可能な感じで保存、ここではcolorというキーに、#3aa757という値を保存してる。そのコールバック…コールバックもよく分かってないけど、成功・失敗時にconsole.logに表示する。
ここの、chrome.storageはchromeで用意されてるAPIで、使うにはmanifest.jsonにpermissionを追加する必要がある。なので、descriptionの下に
"permissions": ["storage"],
を追記する。拡張機能を再読込すると、バックグラウンドページのリンクがついて、クリックするとコンソールが開く。
UserInterface (popup.html, etc)
popup.html
これを落としまして。htmlうまく貼れない。styleタグ内がcssってやつでボタン作ってる。button idをchangeColorとする。scriptがよく分かんない。ボタン押した時?html開いた時?どっちで実行されんだろ。popup.jsも作ってない。どこにあるんだこれ。とりあえず先に進むとして、popup.htmlを使うためにも、manifest.jsonに追記する必要がある。
"page_action": {
"default_popup": "popup.html"
},
こうか。page_actionってのがメニューんとこにあるアイコンをどうのこうのするやつみたい。
icon
アイコンの指定もここでできてimgを落としてきて同じフォルダに置き、
,
"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"
},
と追記。
アイコンついた。
declarativeContent
指定urlによってアイコンの状態を変化させるためにbackground.jsのさっきのリスナ内に
chrome.declarativeContent.onPageChanged.removeRules(undefined, function() {
chrome.declarativeContent.onPageChanged.addRules([{
conditions: [new chrome.declarativeContent.PageStateMatcher({
pageUrl: {hostEquals: 'developer.chrome.com'},
})
],
actions: [new chrome.declarativeContent.ShowPageAction()]
}]);
});
こう。ううう、何だこれは…。chrome.declarativeContentが
to take actions depending on the content of a page, without requiring permission to read the page’s content.
ページのコンテンツを読み取る許可を必要とせずに、ページのコンテンツに応じてアクションを実行します。
うん。で、onPageChangedっていうぐらいだから、ページを遷移した時に自分で設定したルールとマッチするか、みたいな感じだろか。そいでそのルールの編集がremoveRulesとaddRulesかな。
ここの
Event objects may support rules. These event objects don’t call a callback function when events happen but test whether any registered rule has at least one fulfilled condition and execute the actions associated with this rule. Event objects supporting the declarative API have three relevant methods: events.Event.addRules, events.Event.removeRules, and events.Event.getRules.
イベントオブジェクトはルールをサポートする場合があります。これらのイベントオブジェクトは、イベントが発生したときにコールバック関数を呼び出しませんが、登録されたルールに少なくとも1つの条件を満たす条件があるかどうかをテストし、このルールに関連付けられたアクションを実行します。宣言型APIをサポートするイベントオブジェクトには、events.Event.addRules、 events.Event.removeRules、およびevents.Event.getRulesの 3つの関連メソッドがあり ます。
うん。そのルールの書き方が
var rule = {
conditions: [ /* my conditions */ ],
actions: [ /* my actions */ ]
};
が基本形で、最低でもconditionsとactionsが必要。
- conditions
- List of conditions that can trigger the actions.
- actions
- List of actions that are triggered if one of the conditions is fulfilled.
ここではconditionsにchrome.declarativeContent.PageStateMatcherを使って、pageUrl(UrlFilterページのトップレベルURLの 条件が満たされている場合に一致)のhostEquals(URLのホスト名が指定された文字列と等しい場合に一致)でdeveloper.chrome.comを指定してる。このURLをdalomo.netに変えりゃいいんだな。まぁ後にしよ。で、actionsにchrome.declarativeContent.ShowPageActionでメニューバーのアイコンに色付いて使えるようになるし、アクティブタブへのアクセスが許可される。分かりづらいよぅ。慣れてないからなのかなぁ…。
popup.js
おぉ、さっき作ったpopup.htmlで呼ばれる外部スクリプトのpopup.jsだ。
'use strict';
let changeColor = document.getElementById('changeColor');
chrome.storage.sync.get('color', function(data) {
changeColor.style.backgroundColor = data.color;
changeColor.setAttribute('value', data.color);
});
えーっと、letは変数のスコープがブロック内になるやつ。そこにgetElementById(‘changeColor’)でエレメントを取得。changeColorが設定されてるタグはButtonなのでそれが取得される。chrome.storage.sync.getでこの前保存したキーのcolorを使って値を取り出す。そのコールバックで、取得した値を引数として、buttonであるchangeColorのstyle.backgroundColorを値で設定して、setAttributeでvalue属性に値を設定する。でいいのかな。data.colorっていう書き方でなんで値が引っ張れるのか分からん。style.colorっていうのがあって、それの戻り値がそれっぽい感じだったけど、ここのdataってstyleなのか?どうなの?Javascriptはそういうもんなのかもしれない。ここまで終わってpopup.htmlは
たんと追加されてた。うーんと、これstyleとvalueって何が違うんだろ。試しにstyleの方を消してみたら色が付かなかった。でもvalue消しても色付いたままだった。なんだろな。
LayerLogic
ようやく背景色変えるところだ。popup.jsに
changeColor.onclick = function(element) {
let color = element.target.value;
chrome.tabs.query({active: true, currentWindow: true}, function(tabs) {
chrome.tabs.executeScript(
tabs[0].id,
{code: 'document.body.style.backgroundColor = "' + color + '";'});
});
};
を追加。buttonであるchangeColorの.onclickで、クリックした際にプログラムが走る。だけど、ここのelementが分からない。見た感じchangeColorが入ってるっぽいんだけど、そういうもんとして捉えるしかないんだろうか。代入する文が見当たらないからなんでこのまま使えてるのか困惑してしまう…。こちらの
- イベント発生時の情報をイベントオブジェクトとして引数に受け取ることができる。これはJavaScript側で自動的に、イベントハンドラに指定したコールバック関数へ渡してくれるもの。
- イベントハンドラとして設定したコールバック関数の引数にイベントオブジェクト「e」を設定しています。「e」はイベント発生時の情報を持つオブジェクトなので「e.target.id」のように情報を得ることが可能。
このあたりなのかな。だからelement.target.valueでさっき属性を追加したvalueの値を引っ張れるんだと思う。んで、chrome.tabs.queryでqueryInfoをactive(タブがウィンドウでアクティブかどうか。)かつ、currentWindow(タブが現在のウィンドウにあるかどうか。)なやつを指定して、コールバックに(ここのtabsも分からん)、chrome.tabs.executeScriptを設定する。プログラムによってContent Scriptsにプログラムを挿入するみたいです。引数は、tabs[0].idで現在のタブを指定して、codeを挿入してる。「document.body.style.backgroundColor = color;」っていうコードを作って挿入して実行してる。疲れた。あ、manifestに
"activeTab"
を追記。background.jsのサイトをdalomo.netに変更して実行してみると
なった!
options.html
緑じゃないオプションを追加するためのページみたいなのを作る。とりあえずファイルを落としてきまして同じフォルダに置いて、manifestに
"options_page": "options.html",
と追記。そんでoptions.jsを作る。
let page = document.getElementById('buttonDiv');
const kButtonColors = ['#3aa757', '#e8453c', '#f9bb2d', '#4688f1'];
function constructOptions(kButtonColors) {
for (let item of kButtonColors) {
let button = document.createElement('button');
button.style.backgroundColor = item;
button.addEventListener('click', function () {
chrome.storage.sync.set({ color: item }, function () {
console.log('color is ' + item);
})
});
page.appendChild(button);
}
}
constructOptions(kButtonColors);
getElementById(‘buttonDiv’)でdivタグのとこを取得。constは定数で色コードの配列を作る。constructOptions関数は、その定数の引数として、定数の配列のアイテム数分createElementでボタンを作ってく。style.backgroundColorでボタンの色に定数の色を設定し、addEventListenerでボタンクリック時の処理を書いてく。storage.sync.setでcolorキーに定数の色をセットするから、色が変わるのか。page.appendChildでbuttonDivの直下末尾にbuttonを追記して完了。
結果こういうソースになる。なるほどにゃん。
愚痴
日本語の情報とか見るとさー、manifestとcontent.jsだけでできるとか書いてあるからさー、それでいいのかと思ってたら、チュートリアルだとこんな感じになるのね。どっちがいいのかは俺にはわかんないけど、チュートリアルは俺には敷居が高いな…。やりたいことはあるんだけど、できる気がしなくなってきたな。
コメント