20100915 學習撰寫 google chrome extension
DESCRIPTION
Taipei Google Technology User Group於2010/9/15的Google Chrome Extension開發教學。TRANSCRIPT
學習撰寫Google Chrome Extension
阿修 (Justin Lee)www.lis186.com
2010/9/15
Chrome Extension
• 擴充Google Chrome的功能• 使用HTML,CSS和Javascript撰寫• 可使用任何Chrome支援的技術,如:XMLHttpRequest,JSON,HTML5
• 安裝後無須重新啓動• 自動更新
開發工具
• Google Chrome • 開發人員工具• Javascript控制台• 文字編輯器(Mac OSX上推薦textmate)
•圖形處理軟體(畫icon用,非必要)
Chrome Extension的架構
manifest檔
Browser Action或Page ActionContent Script
Background Page
必備:
至少有一項:
Chrome Extension的通訊
Background Page
Window Content Script
Popup Page
popup
Browser ActionPage Action
message passing
match patternspermissions
Web Page Script
DOM
Chrome Extension的通訊
Background Page
Window Content Script
Popup Page
popup
Browser ActionPage Action
message passing
match patternspermissions
Web Page Script
DOM
Chrome Extension的通訊
Background Page
Window Content Script
Popup Page
popup
Browser ActionPage Action
message passing
match patternspermissions
Web Page Script
DOM
Chrome Extension的架構
.crx{manifest.json.html
.css
.js
.png, .jpg, .gif(zipped folder)
other files
Chrome Extension API
• 新增使用者介面• Browser Actions
• Page Actions
• 與網頁或server互動• content script
• cross-origin XMLHttpRequests
• 操作瀏覽器的功能• windows, tabs
• bookmarks
• history
• cookies
• chome.extension.*
• chrome.browerAction.*
• chrome.pageAction.*
• chrome.tabs.*
• chrome.windows.*
• chrome.bookmarks.*
Chrome Extension API
• chrome.cookies.*
• chrome.history.*
• chrome.contextMenus.*
• chome.i18n.*
• chrome.idle.*
範例:現在天氣怎麼樣
顯示目前位置的氣象狀態
Manifest FileBackground PagePopup PageBrowser ActionOption Pagei18n
你可以學到:
功能:
Step1:建立Browser Action UI
{ "name": "現在天氣怎麼樣", "version": "0.1", "description": "顯示所在地現在的天氣狀態", "icons": { "16": "images/icon_16.png", "32": "images/icon_32.png", "64": "images/icon_64.png", "128": "images/icon_128.png" }, "browser_action": { "default_icon": "images/loading.png", "default_title": "現在天氣怎麼樣" }}
manifest.json
Step2:取得目前位置
{ "name": "現在天氣怎麼樣", "version": "0.2", "description": "顯示所在地現在的天氣狀態", "icons": { ... }, "background_page": "background.html", "permissions": [ "geolocation" ], "browser_action": { "default_icon": "images/loading.png", "default_title": "現在天氣怎麼樣" }}
manifest.json
background.html<html><head><meta charset="utf-8" /><script>
var errorCode;var lat;var lng;
function getCurrentLocation(){ navigator.geolocation.getCurrentPosition(success, error);}
function success(position){ console.log(position); lat=Math.round(position.coords.latitude*1000000); lng=Math.round(position.coords.longitude*1000000);}
function error(msg){ console.log(msg); chrome.browserAction.setBadgeText({text:"?"}); errorCode="unable_to_locate_your_position";}
getCurrentLocation();
</script></head></html>
『如果你寫程式沒用undocumented API,那一定是因為你的程式沒什麼了不起的功能。』
lukhnos
http://lukhnos.org/blog/zh/archives/581
http://www.google.com/ig/api?hl={locale}&weather=,,,{lat},{lng}
Google’s secret Weather API
http://www.google.com/ig/api?hl=zh-tw&weather=,,,25060808,121485606
<?xml version="1.0"?><xml_api_reply version="1"><weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" > <forecast_information> <city data=""/> <postal_code data=""/> <latitude_e6 data="25060808"/> <longitude_e6 data="121485606"/> <forecast_date data="2010-09-15"/> <current_date_time data="2010-09-14 23:00:00 +0000"/> <unit_system data="SI"/> </forecast_information> <current_conditions> <condition data="多雲"/> <temp_f data="79"/> <temp_c data="26"/> <humidity data="濕度: 87%"/> <icon data="/ig/images/weather/cloudy.gif"/> <wind_condition data="風向: 公里/小時"/> </current_conditions> <forecast_conditions> <day_of_week data="週三"/> <low data="26"/> <high data="35"/> <icon data="/ig/images/weather/thunderstorm.gif"/> <condition data="晴午後短暫雷陣雨"/> </forecast_conditions> ...</weather></xml_api_reply>
http://img0.gmodules.com/前面要加上
Step3:取得目前位置的天氣狀態
{ "name": "現在天氣怎麼樣", "version": "0.3", "description": "顯示所在地現在的天氣狀態", "icons": { ... }, "background_page": "background.html", "permissions": [ "http://www.google.com/ig/*", "http://img0.gmodules.com/ig/images/weather/", "geolocation" ], "browser_action": { ... }}
manifest.json
background.html...var weatherXML;var current;...function success(position){ ... getWeather();}...function getWeather(){ console.log("http://www.google.com/ig/api?hl=zh_tw&weather=,,,"+lat+","+lng); $.get("http://www.google.com/ig/api?hl=zh_tw&weather=,,,"+lat+","+lng, function(data) { weatherXML=data; if($(weatherXML).find("weather current_conditions").length==1) { current={}; current.condition=$(weatherXML).find("current_conditions condition").attr("data"); current.temp_c=$(weatherXML).find("current_conditions temp_c").attr("data")+"℃"; current.temp_f=$(weatherXML).find("current_conditions temp_f").attr("data")+"℉"; current.humidity=$(weatherXML).find("current_conditions humidity").attr("data"); current.wind_condition=$(weatherXML).find("current_conditions wind_condition").attr("data"); current.icon="http://img0.gmodules.com"+$(weatherXML).find("current_conditions icon").attr("data"); console.log(current); chrome.browserAction.setBadgeText({text:current.temp_c}); chrome.browserAction.setIcon({path:current.icon}); } else { chrome.browserAction.setBadgeText({text:"?"}); errorCode="unable_to_load_data"; } });}...
background.html...
function startRequest(){ getCurrentLocation(); }
function scheduleRequest() { var reqeustInterval = 1000 * 60 * 5; console.log("Scheduling request..."); window.setTimeout(startRequest, reqeustInterval);}startRequest();scheduleRequest();...
Step4:每五分鐘更新一次天氣manifest.json..."version": "0.4",...
manifest.json
{ "name": "現在天氣怎麼樣", "version": "0.5", "description": "顯示所在地現在的天氣狀態", "icons": { ... }, "background_page": "background.html", "popup": "popup.html", "permissions": [ ... ], "browser_action": { "default_icon": "images/loading.png", "default_title": "現在天氣怎麼樣", "default_popup": "popup.html" }}
Step5:在popup顯示詳細資訊
<html><head><meta charset="utf-8" /><script type="text/javascript" src="jquery.min.js"></script> <script>var current;var errorCode;function renderPage(){ current=chrome.extension.getBackgroundPage().current; errorCode =chrome.extension.getBackgroundPage().errorCode; if(current) { $("#temp").html('<img src='+current.icon+'>'+current.temp_c); $("#detail").html(current.condition+'<br>'+current.humidity+'<br>'+current.wind_condition); } else { switch(errorCode){ case "unable_to_locate_your_position": $("#current").html("無法確定目前所在位置。"); break; case "unable_to_load_data": $("#current").html("無法載入資料。"); break; default: $("#current").html("資料載入中..."); } }}</script></head><body onload="renderPage();"><div id="current" style="width: 160px"><div id="temp"></div><div id="detail"></div></div></body>
popup.html
manifest.json..."version": "0.6",...
Step6:把popup裝飾一下
style.cssbody{ font-size: 14px; color: #333;}
img{ padding-right: 8px;}
#temp{ color: #333; font-size: 48px; font-family: Arial; text-shadow:3px 3px 3px #EEE;}
manifest.json... "version": "0.6",... "options_page": "options.html",...
Step7:新增溫度單位切換選項
options.html...<body onload="restoreOption();"> 溫度單位<input type="radio" name="temp_mode" value="C" checked>攝氏 <input type="radio" name="temp_mode" value="F">華氏<br><button onclick="saveOption();">儲存</button><div id="status"></div></body>...
options.html...function saveOption(){ if(localStorage["temperature_mode"] != $('input[name=temp_mode]:checked').val()) { localStorage["temperature_mode"] = $('input[name=temp_mode]:checked').val(); chrome.extension.getBackgroundPage().getWeather(); }
console.log(localStorage["temperature_mode"]); $("#status").html("儲存完成。<a href='javascript:window.close();'>按此關閉</a>");}
function restoreOption(){ var temp_mode=localStorage["temperature_mode"]; if(!temp_mode) { return; }else { switch(temp_mode) { case "C": $("input[name=temp_mode]")[0].checked=true; break;
case "F": $("input[name=temp_mode]")[1].checked=true; break;
default: console.log("error"); } }}...
Step8:讓「歪果人」也看得懂(i18n)
.crx{manifest.json.html
.css
.js
.png, .jpg, .gif
_locales{en
zh_TW messages.json(zipped folder)
別忘了設定default_locale
{ "extName": { "message": "現在天氣怎麼樣", "description":"擴充套件名稱" }, "extDescription": { "message": "顯示所在地現在的天氣狀態", "description":"擴充套件描述" }, "locale": { "message": "zh-tw", "description":"要傳送給Google Weather API的語系編碼" }, "loading": { "message": "資料載入中...", "description":"載入資料時的popup內容" }, "unable_to_load_data": { "message": "無法載入資料。", "description":"資料載入錯誤時的popup內容" }
...}
zh_tw/messages.json
{ "extName": { "message": "How is the weather now", "description":"擴充套件名稱" }, "extDescription": { "message": "Display current weather condition here.", "description":"擴充套件描述" }, "locale": { "message": "en", "description":"要傳送給Google Weather API的語系編碼" }, "loading": { "message": "Loading...", "description":"載入資料時的popup內容" }, "unable_to_load_data": { "message": "Unable to load data.", "description":"資料載入錯誤時的popup內容" } ...}
en/messages.json
masifest.json
{ "name": "__MSG_extName__", "version": "1.0", "description": "__MSG_extDescription__", "default_locale": "zh_TW", "icons": { ... }, ... ], "browser_action": { "default_icon": "images/loading.png", "default_title": "__MSG_extName__", "default_popup": "popup.html" }}
...var locale=chrome.i18n.getMessage("locale");...
function getWeather(){... $.get("http://www.google.com/ig/api?hl="+locale+"&weather=,,,"+lat+","+lng, function(data) {...}
background.html
...function renderPage(){ $("#temperature_scale").html(chrome.i18n.getMessage("temperature_scale")); $("#celsius").html(chrome.i18n.getMessage("celsius")); $("#fahrenheit").html(chrome.i18n.getMessage("fahrenheit")); $("#save").html(chrome.i18n.getMessage("save"));}</script></head><body onload="restoreOption();renderPage();"><span id="temperature_scale"></span><input type="radio" name="temp_mode" value="C" checked><span id="celsius"></span> <input type="radio" name="temp_mode" value="F"><span id="fahrenheit"></span><br><button onclick="saveOption();"><span id="save"></span></button><div id="status"></div></body>
options.html
Step9:封裝擴充功能
{extName}.crx{extName}.pem 祕密金鑰
擴充功能
Step10:上傳到Chrome Extensions Gallery
Q&A
Thank you!