前回はWebアプリの検索ボックスとコンテキストメニューの拡張を通して、
ほかのWebサイトと連携する
みなさんは、
今回の機能追加では、

Webアプリの構成
今回は、

{
"name": "Odometer",
"description": "距離計",
"version": "0.5",
"app": {
"launch": {
"local_path": "main.html"
}
},
"icons": {
"16": "icon_16.png",
"48": "icon_48.png",
"128": "icon_128.png"
},
"omnibox": {
"keyword": "Odometer"
},
"options_page": "options.html",
"background_page": "background.html",
"content_scripts": [
{
"matches": ["*://maps.google.co.jp/*", "*://maps.google.com/*"],
"js": ["js/content_script.js"]
}
],
"permissions": [
"geolocation",
"notifications",
"background",
"contextMenus",
"tabs"
]
}
Content Scriptsを利用するには、
フィールド名 | 説明 |
---|---|
content_ | 対象のWebサイトで任意のJavaScriptやCSSを適用する設定項目をオブジェクト配列で指定 |
matches | 対象のWebサイトのURLを配列で指定 "http:// |
css | 挿入するCSSファイルを配列で指定 |
js | 実行するJavaScriptファイルを配列で指定 |
run_ | JavaScriptを実行するタイミングを指定 "document_ |
all_ | すべてのフレーム要素でスクリプトを実行するかどうかを指定 |
include_ | "matches" からさらに適用するパターンを指定 |
exclude_ | "matches" からさらに除外するパターンを指定 |
Content Scripts
Content Scriptsは、

Content Scriptsのセキュリティ
Content Scriptsは、
Chrome 14からは、
"content_security_policy": "default-src 'self'"
Googleマップにボタンを追加してOdometerを呼び出す
今回は、
(function(){
// Google Mapsのドメイン上で対象のノードがあればボタンを埋め込む
var insertTarget = document.querySelector('table.cntrltable>tbody>tr');
if ( !insertTarget ) {
return;
}
// Odometer目的地設定ボタン追加
var img = document.createElement('img'),
button = document.createElement('button'),
innerDiv = document.createElement('div'),
outerDiv = document.createElement('div'),
td = document.createElement('td');
img.src = chrome.extension.getURL('icon_16.png');
img.style.cssText = 'margin-right:5px; padding-bottom:8px;';
button.className = 'kd-button kd-button-submit';
button.style.cssText = 'cursor:pointer;min-width:105px;height:30px;padding:5px 5px 0 0;';
button.appendChild(img);
button.appendChild(document.createTextNode('目的地設定'));
// ~省略~
innerDiv.className = 'q-inner';
innerDiv.appendChild(button);
outerDiv.className = 'q-outer';
outerDiv.appendChild(innerDiv);
td.appendChild(outerDiv);
insertTarget.appendChild(td);
})();
要素の追加は、
// Odometer上で目的地を設定する
button.addEventListener('click', function(evt){
evt.preventDefault();
// スクリプト要素を挿入して挿入したスクリプトから座標をsessionStorageに格納する
var script = document.createElement('script');
script.textContent = 'var p = gApplication.getMap().getCenter(); sessionStorage.lat = p.lat(); sessionStorage.lng = p.lng();';
document.head.appendChild(script);
// 挿入したスクリプトから座標がsessionStorage経由で格納されるのを監視する
var polingCount = 5;
function getLatLng(){
console.log(polingCount);
// 座標が格納されている場合、バックグラウンドページへリクエストを送信する
if ( sessionStorage.lat && sessionStorage.lng ) {
chrome.extension.sendRequest({
action: 'set_destination_from_websites',
lat: sessionStorage.lat,
lng: sessionStorage.lng
});
// 後処理
sessionStorage.removeItem('lat');
sessionStorage.removeItem('lng');
document.head.removeChild(script);
return;
}
if ( polingCount-- ) {
setTimeout(getLatLng, 500);
}
}
setTimeout(getLatLng, 500);
}, false);
挿入するスクリプト要素の中で、
/*
* メッセージを受信し、各処理へ振り分ける
*/
chrome.extension.onRequest.addListener(
function(request, sender, sendResponse) {
switch ( request.action ) {
// ~省略~
case 'set_destination_from_websites':
setDestinationOnApp(request.lat, request.lng);
sendResponse({});
break;
default:
sendResponse({});
break;
}
}
);
/*
* アプリ上で目的地設定を行います
*/
function setDestinationOnApp(lat, lng){
selectOrCreateTab(APP_URL, function(tab){
var view = getView(APP_URL);
if ( !view ) {
return;
}
if ( tab.status === 'loading') {
view.destination = {
lat: lat,
lng: lng
};
} else {
view.setDestination(lat, lng, true);
}
});
}
バックグラウンドページでは、
/*
* 目的地設定
*/
function setDestination(lat, lng, focus){
var latLng = new google.maps.LatLng(lat, lng);
if ( destMarker ) {
destMarker.setMap(null);
}
destMarker = new google.maps.Marker({
title: '目的地',
position: latLng,
map: map
});
//目的地情報表示
showDestinationPosition(lat, lng);
/*
* Background Pageで目的地を設定
*/
chrome.extension.sendRequest(
//リクエストデータ
{
action: 'set_destination',
lat: lat,
lng: lng
},
//レスポンスコールバック
function(response) {
if ( response.type && response.type == 'distance' ) {
//目的地までの距離を表示
showDistance(response.distance);
} else {
alert('目的地の設定に失敗しました');
}
}
);
if ( focus ) {
map.setCenter(latLng);
}
}
メイン画面のsetDestinationメソッドでは、


動的にJavaScriptを挿入する
Content Scriptsのようにあらかじめ対象としたURLに対してJavaScriptファイルを挿入するのではなく、
"permissions": [
"tabs",
"http://*/*"
]
"permissions" に、
// JavaScriptの実行
chrome.tabs.executeScript(null,
{ code: "alert(1)" });
// JavaScriptファイルの挿入
chrome.tabs.executeScript(null,
{ file: "js/execute_script.js" });
// スタイルの適用
chrome.tabs.insertCSS(null,
{ code: "body { backround-color: white; }" });
// CSSファイルの挿入
chrome.tabs.insertCSS(null,
{ file: "css/insert.css" });
実際にJavaScriptやCSSを挿入する場合のサンプルコードです。executeScriptメソッドとinserCSSメソッドは、
メソッド/ | 説明 |
---|---|
executeScript(tabId, details, callback) | 指定のタブにJavaScriptを挿入する |
insertCSS | 指定のタブにCSSを挿入する |
プロパティ | 説明 |
---|---|
code | JavaScriptコード、 |
file | JavaScriptファイル、 |
allFrames | すべてのフレーム要素でスクリプトを実行するかどうかを指定 |
まとめ
これで、
今回は、
- ※
crxファイルはzipファイルですので、
右クリックからのダウンロード後に拡張子をzipに変えていただければ中身を参照できます。