Chrome插件(Extensions)開發攻略

本文將從我的經驗出發,講述爲何須要Chrome插件,如何開發,如何調試,到哪裏找資料,會遇到怎樣的問題以及如何解決等,同時給出一個我的認爲的比較典型的例子——獲取網頁內容,和服務器交互,再把信息反饋給用戶。OK,準備開始吧,我儘可能把文章寫得好看點,以避免讀者打瞌睡。javascript

目錄

  1. 爲何須要
  2. 爲何是Chrome
  3. 須要準備什麼
  4. 如何開始
  5. Page Action
  6. Chrome插件結構
  7. 學習資料
  8. 個人例子
  9. 調試
  10. 總結

爲何須要

簡單地說,瀏覽器插件,能夠大大的擴展你的瀏覽器的功能。包括但不只限於這些功能:捕捉特定網頁的內容,捕捉HTTP報文,捕捉用戶瀏覽動做,改變瀏覽器地址欄/起始頁/書籤/Tab等界面元素的行爲,與別的站點通訊,修改網頁內容……給你增長許多想象空間,試想一想看,你能夠用它來識別一些網站上的廣告代碼,並直接把這些代碼刪掉,這樣你就不會受到廣告的困擾了,沒錯,如你所願,這樣的插件別人已經開發好了,你能夠直接用。不過,也要說瀏覽器插件的弊端,那就是:會帶來一些安全隱患,也可能讓你的瀏覽器變得緩慢甚至不穩定。php

爲何是Chrome

由於Chrome的插件開發起來最簡單,整體上看沒什麼新的技術,開發語言就是javascript,web前端工程師能很快上手;而Firefox的插件開發則複雜許多,涉及到環境的搭建和一些WEB之外的技術;IE的插件開發就更復雜了,須要熟悉C++和COM技術,固然還要裝微軟的Visual Studio。html

這裏有篇老外寫的文章,對比Chrome、Opera和Firefox的插件開發的:http://blog.nparashuram.com/2011/10/writing-browser-extensions-comparing.html前端

應該說Chrome和Opera的插件的開發都不難,但Firefox的則比較棘手,也許你要問,那爲何Firefox的插件是最豐富的?我想這有些歷史緣由,Chrome出來畢竟比較晚,另外幾種瀏覽器提供的插件的功能也是不盡相同的,OK,咱們仍是言歸正傳吧。java

須要準備什麼

幾乎是零需求。Chrome瀏覽器和一個文本編輯器便可,文本編輯器最好是帶語法高亮的那種。谷歌對咱們作技術的人來講真是太大度了。jquery

如何開始

強烈建議看看官方的說明:https://developer.chrome.com/extensions/getstarted.html程序員

文章不長,照着文章去作,完成後,你就成功開發了第一個Chrome插件,這個插件會彈出一個小窗口,上面顯示些阿貓阿狗的小圖片。如圖:web

這個插件一共有4個文件:ajax

  • manifest.json - 全部插件都要有這個文件,這是插件的配置文件,可看做插件的「入口」。
  • icon.png - 小圖標,推薦使用19*19的半透明png圖片,更好的作法是同時提供一張38*38的半透明的png圖片做爲大圖標,在我後面提供的例子中,我就是那麼幹的。
  • popup.html - 就是你所看到的那個阿貓阿狗的彈出頁面。
  • popup.js - 阿貓阿狗頁面所引用的javascript文件。

這裏千萬千萬注意了,我當初沒仔細看popup.html裏有一小段註釋,這一小段註釋說:出於安全考慮,javascript必須與html分開存放。而我想嘛,一個小測試程序,不必分開吧,直接寫一塊兒不就好了嗎?結果javascript死活執行不了,我翻來覆去找不到緣由,還覺得彈出的小窗口不支持javascript,在網上搜索了半天又沒有結果,最後才發現是這個緣由,浪費了許多時間,這個事情也必定程度上說明了:細節決定成敗。正則表達式

manifest.json中的內容也很是顯而易見,我選擇其中幾個屬性講一下:

{
  "manifest_version": 2,

  "name": "One-click Kittens",
  "description": "This extension demonstrates a browser action with kittens.",
  "version": "1.0",

  "permissions": [
    "https://secure.flickr.com/"
  ],
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  }
}

"manifest_version":如今應該老是2。

"permissions":很重要的東西,即容許插件作哪些事情,訪問哪些站點,假如一個插件的"permissions"裏寫有「http://*.hacker.com/」,那麼這個插件就被容許訪hacker.com上的全部內容,包括可能會把你的一些我的信息提交給hacker.com,危險性不言而喻,查看一個插件能訪問那些站點的方法是:在chrome的地址欄裏輸入「chrome://extensions/」(注意:這個頁面咱們以後要頻繁用到,請收藏一下),而後點對應插件的旁邊的那個「權限」,如:

"default_popup":用來指定點擊小圖標後彈出的小窗口中默認顯示的是哪一個html,這個彈出的小窗口就叫作「popup」。

"browser_action":這是一個瀏覽器級的動做,也就是說,無論你如今在訪問哪一個頁面,那個小按鈕老是顯示出來,而咱們的插件若是僅僅是針對某些頁面的話,就不適合用這個"browser_action"了。下面咱們來弄一個只有訪問博客園(www.cnblogs.com)纔會出現的小按鈕。

Page Action

chrome-plugin-page-action-demo.7z

這個插件只有4個文件,其中兩個仍是圖標,那就只剩下一個必須的manifest.json和一個background.js了。

mainifest.json:

{
     "manifest_version": 2,
     "name": "cnblogs.com viewer",
     "version": "0.0.1",
     "background": { "scripts": ["background.js"] },
     "permissions": ["tabs"],
     "page_action": {
          "default_icon": {
               "19": "cnblogs_19.png",
               "38": "cnblogs_38.png"
          },
          "default_title": "cnblogs.com article information"
     }
}

注意:這裏是「page_action」而不是「browser_action」屬性了。

「permissions」屬性裏的「tabs」是必須的,不然下面的js不能獲取到tab裏的url,而這個url是咱們判斷是否要把小圖標show出來的依據。background是什麼概念?這是一個很重要的東西,能夠把它認爲是chrome插件的主程序,理解這個很關鍵,一旦插件被啓用(有些插件對全部頁面都啓用,有些則只對某些頁面啓用),chrome就給插件開闢了一個獨立的javascript運行環境(又稱做運行上下文),用來跑你指定的background script,在這個例子中,也就是background.js。

background.js

function getDomainFromUrl(url){
     var host = "null";
     if(typeof url == "undefined" || null == url)
          url = window.location.href;
     var regex = /.*\:\/\/([^\/]*).*/;
     var match = url.match(regex);
     if(typeof match != "undefined" && null != match)
          host = match[1];
     return host;
}

function checkForValidUrl(tabId, changeInfo, tab) {
     if(getDomainFromUrl(tab.url).toLowerCase()=="www.cnblogs.com"){
          chrome.pageAction.show(tabId);
     }
};

chrome.tabs.onUpdated.addListener(checkForValidUrl);

代碼中,咱們使用了一個正則表達式去匹配url,獲取出其中的domain部分,若是domain部分是「www.cnblogs.com」的話,就把小圖標show出來,效果以下:

固然了,你如今點那個小圖標的話,是沒有任何反應的,我沒有像官方提供的那個例子那樣提供了popup。OK,如今是時候描述下chrome插件的結構了。

Chrome插件結構

須要聲明的是,這個結構圖是我本身畫的,表明我對Chrome插件的理解,可能並不全面,甚至還不是十分準確,但找來找去找不到現成的,只好本身動手,若有謬誤,請不吝指出。

如圖,manifest.json做爲插件的配置文件,同時能夠看做程序的「入口」,由於它指定了顯示什麼圖標,background script有哪些文件,content script又有哪些文件,pop up的頁面是什麼,等等。

什麼是popup,什麼是background script,相信你們都清楚了,那什麼是content script呢?content script就是咱們要注入到頁面中的腳本,插件容許咱們往網頁中注入腳本,這是一個多麼讓人有想象力的功能,其功能之強大無需多解釋,總的來講,就是讓咱們全面干預頁面的內容!也許你立刻會想到,這可能帶來很大的安全隱患,沒錯,有些惡意插件會竊取你的頁面信息,而有些有漏洞的插件則可能讓你遭受跨站腳本注入(XSS)的攻擊;另外一個可能你會想到的問題是:往頁面中注入本身的腳本,難道不會跟頁面本來的腳本發生衝突嗎?能想到這點說明你真的很厲害,若是咱們的注入腳本和頁面本來的腳本處於同一個運行環境中,確實會發生衝突,因此,Chrome是另外開闢了一個獨立的運行空間,供咱們的Content Script使用的,Content Script能訪問DOM的內容,但卻不能訪問頁面本來的腳本(我是說直接訪問不行),反之,頁面本來的腳本也不能直接訪問Content Script。在圖中,淺紅色的背景塊表明Content Script的運行環境,而淺藍色的背景塊表明頁面運行環境,另外插件的運行環境我用淺綠色表示,注意,這是三個不一樣的運行環境,調試的時候你會充分體會到它們的不一樣。

那麼,Content Script會在何時運行呢?默認狀況下,是在網頁加載完了和頁面腳本執行完了,頁面轉入空閒的狀況下(Document Idle),但這個是能夠改變的,詳情可參考https://developer.chrome.com/extensions/content_scripts.html,查看其中的「run_at」。

因爲處於不一樣的運行環境中,Content Script和Background Script不能直接互相訪問,那它們之間如何通訊?經過Message!這個以後的代碼中會有。

學習資料

理解了Chrome插件結構以後,我相信你徹底有能力開發一款本身的插件了,固然了,你得本身去google一些資料,這裏我就分享下個人方法。

首先,官方的資料必定得看看,https://developer.chrome.com/extensions/index.html,這個上面的資料得大體瀏覽一下(不須要所有仔細看),這樣你可以明白一些術語,知道如何去尋找你的解決方案。

再則,官方提供的例子,能夠看看,https://developer.chrome.com/extensions/samples.html,我發現上面的例子有些已經不能用於新版的Chrome了,但不要緊,你只要找你想要的就好了,也不用一個個嘗試,就根據你的須要,挑選幾個你感興趣的看看便可。

遇到問題,怎麼辦?固然是用google去查找問題,但這裏我最最最強烈推薦stackoverflow.com,這簡直是解決問題的神器!很少解釋了,用過便知。

學習過程基本上就是:看個大概,寫點代碼,調試調試。就能夠了。哦,大前提固然是你得有javascript的基礎。(你:呵呵,你在逗我吧!)

個人例子

chrome-plugin-cnblogs-article-information.zip

chrome-plugin-cnblogs-article-info-server.zip (服務器端,PHP代碼)

好,輪到個人例子登場了。它的功能是這樣的:當你瀏覽博客園的時候,它會啓動並嘗試獲取你瀏覽的文章的信息(標題、做者和日期),再經過往另外一個服務器發送請求的方式,記錄和獲取你第一次訪問這篇文章的時間,把這個時間連帶文章的信息,顯示在popup上。聽起來挺無聊的功能,但關鍵是爲了演示嘛,如圖:

這個插件一共有9個文件,新出現的文件有兩個(其它相信你們都很熟悉了),一個是「content_script.js」,這就是前面提到的Content Script,獲取和修改頁面的內容就靠它了;另外一個是「jquery-2.0.0.min.js」,大名鼎鼎的jQuery,我很喜歡用的js庫,其理念是「write less,do more」,能幫我減小不少代碼,這是目前最新的2.0.0版,這個版本跟之前的1.x.x的最大差異就是再也不支持IE六、7和8,我我的是十分贊同這種作法的,微軟的舊版瀏覽器都成了Web技術發展的絆腳石了,並且此次咱們用的是Chrome瀏覽器,果斷選擇最新版了。

另外還有一個服務器端,爲了讓問題簡化,此次我用了php代碼,一個php文件就是整個處理了,沒有太多繁雜的配置,簡潔,這是php最大的優點。系統結構如圖:

抓取網頁的內容得依靠content_script.js,而後經過sendMessage/onMessage和background.js交換數據,background.js將url信息經過ajax(XMLHttpRequest)發送給localhost,獲取此頁面的第一次訪問的時間,最後,用戶點小圖標,popup.html出現,popup.html會讀取(代碼在popup.js中)background.js中的articleData的數據,把它顯示出來。這就是整個過程。

我抓取網頁數據的方式並不能確保全部的博客園的文章都能被正常獲取,這跟用戶使用的博客模板有關係,但我嘗試下來大多數文章仍是能夠抓取的,我不去適應全部的模板了,畢竟這只是個演示的demo。

另外還需說明的一點是我使用了jQuery作XMLHttpRequest,post的內容不是傳統的html表單形式,而是json數據,因此在服務器端這邊,就不能直接用$_REQUEST獲取,而是經過讀取「php://input」的內容獲取。順便談談我的對web api的一個見解:「統一」大於「靈活」,這是個人觀點,我肯定個人接口的格式是json,使用utf-8編碼,因而就一直用下去,調用者不用考慮用XML仍是html表單仍是別的,開發者也沒必要多考慮,讓這成爲一種統一的約定,在團隊協助和之後的開發中會很省事。

調試

程序開發,一定要涉及到調試,記得我剛開始作WEB開發前,問一些作了很久WEB開發的朋友,大家是怎樣作javascript調試的,我發覺大多數人居然回答:用alert一點點試吧——不是不行,是太原始,過低效了,對吧?其實Chrome直接支持javascript的調試,擁有了Chrome,就至關於擁有了一個強大的javascript調試器了。

Chrome打開開發者工具的方法是<Ctrl>+<Shift>+<I>(Windows版),大體以下:

咱們此次須要關心的有「Elements」、「Sources」和「Console」這三個標籤。Elements是用來作DOM分析的,功能有點相似Firebug,幫助咱們分析頁面的內容;而Sources,是咱們用來調試javascript的;Console則是咱們的Log的輸出窗口,也是一個調試利器。

調試Content Script

如我提供的這個例子,可在Sources的「Copntent Scripts」下看到「content_script.js」而後設斷點,執行到斷點處時,Chrome會挺住,你能夠觀察到上面的值,如圖:

太cool了,請問你還要一點點alert嗎?

調試Background

因爲background和content script並不在同一個運行環境中,所以上面的方法是看不到Background的javascript的。要調試Background,還須要打開插件頁,也就是「chrome://extensions」。點對應的插件的「generated background page.html」,就出現了調試窗口,接下來的操做就跟前面的相似了。如圖:

至於你看到ID,「aajnhhjiia……」這一長串東西,這是chrome自動安排的一個ID。

調試Popup

雖然Popup和Background是處於同一運行環境中,但在剛纔的Background的調試窗口中是看不到Popup的代碼的。調試Popup還須要這樣:

而後……就跟前面差很少了。

一些問題

也許有時候你會發覺調試器不是很靈,至少我用下來感受如此,好比你可能發現斷點設不了,或者斷點不起做用,或者看不到你本身的javascript文件。個人方法是在插件頁中,把對應的插件的「已啓用」這個複選框去掉,再從新勾上,而後再點一下「從新加載(Ctrl+R)」,一般能解決問題。固然了,還有些很古怪的問題,還很差重現,整體的解決思路就是從新載入一下,實在不行的話重啓瀏覽器,或者清除瀏覽器緩存什麼的,再試試看。

在作插件調試的時候我還遇到一個十分鬱悶的問題,那就是個人Chrome使用了「Go Agent」,關於Go Agent是用來幹嗎的,這個嘛,能夠去google一下,我相信絕大多數程序員都會喜歡上它……可因爲使用了這個東西,極可能會致使插件的XMLHttpRequest工做不正常,並且可能你會思索半天也找不到緣由,好吧,暫時把Go Agent停用掉,甚至可能你須要重啓下Chrome——個人經驗。

總結

我仍是想說,我以爲Google對咱們程序員來講是個很大度的公司,在Chrome這個產品上面就可見一斑。利用Chrome插件技術,咱們能夠作許多有用的東西,經過本文,相信你已經知道如何去開發一款Chrome插件了,固然了,Chrome插件的功能是很強大的,我用到的僅是冰山一小角。要深刻,固然還須要更加充分地利用google和stackoverflow.com了。

相關文章
相關標籤/搜索