当你看完这一页和入门指南之后,就可以开始开发自己的扩展程序和打包应用程序(packaged apps)了。
Note: 应用程序包是作为扩展程序来实现的,所以除非特别说明,本页所有内容都适用于应用程序包。
mail扩展程序使用browser action(工具栏上的图标)。 | 这个map扩展程序使用page action (地址栏上的图标) 和content script (注入web页面的代码)。 | 这个news扩展程序也应用了browser action,点击时会显示一个弹出式窗口。 |
扩展程序和应用程序包也可以以其他的方式呈现它们的界面,比如增加到Chrome的上下文菜单、提供一个选项页面或使用content script改变页面的外观。请参考开发者指南获得扩展程序特性的完整列表以及它们各自的实现细节。
一个打包应用程序通常使用一个捆绑到程序里面的HTML页面来呈现它的主要功能。例如下面的打包应用程序在一个HTML页面中显示了一个Flash文件。
请看Packaged Apps获得更多的信息。
在开发扩展程序的时候,需要将所有这些文件都放在同一个文件夹里面。发布扩展程序的时候,这个文件夹会被打包成一个特殊以 .crx 为后缀的ZIP文件。如果使用 Chrome Developer Dashboard 上传扩展程序,则会自动为你创建 .crx文件。更多有关发布扩展程序的细节,请看 Hosting 。
你可以将任何你想要的文件放进扩展程序里面,但你怎么使用它呢?通常,你可以使用相对路径引用文件,就像你在一个普通HTML页面做的那样。下面的例子展示了如何引用子目录images中的myimage.png文件。
src="images/myimage.png">
正如你所注意到的,当你使用Google Chrome调试器的时候,在扩展程序里面的每一个文件也可以通过一个绝对路径访问,像下面这样:
chrome-extension://
在这个URL中,
当你在开发扩展程序(尚未打包)时,扩展程序ID是可以改变的。特别地,如果从不同的目录加载一个未打包的扩展程序,那么其ID是会改变的;在打包的时候扩展程序的ID又也会改变。如果在代码中需要指定扩展程序中某个文件的完整路径,可以在开发期间使用 @@extension_id 这个预定义消息(predefined message)以避免硬性的指定ID。
扩展程序在被打包(典型地,通过dashboard上传)后会获得一个永久的固定的ID,这个ID即使在以后更新扩展程序的时候也不会改变。一旦ID固定了,就可以将所有出现@@extension_id 的地方改为真正的ID。
一个名为manifest.json的manifest文件给出了扩展程序的相关信息,比如说扩展程序可能使用到的重要的文件和功能。下面是一个典型的manifest文件,使用了browser action并访问google.com的信息:
{ "name": "My Extension", "version": "2.1", "description": "Gets information from Google.", "icons": { "128": "icon_128.png" }, "background": { "scripts": ["bg.js"] }, "permissions": ["http://*.google.com/", "https://*.google.com/"], "browser_action": { "default_title": "", "default_icon": "icon_19.png", "default_popup": "popup.html" } }更多细节,请看 Manifest Files。
很多扩展程序都有一个后台页面(background page),用来控制扩展程序的主要逻辑功能的看不见的页面。扩展程序也可以包含其他的页面来呈现其界面。如果扩展程序需要和用户加载的web页面(相对于包含在扩展程序中的页面)交互,则必须使用 content script。
下图显示也一个至少安装了两个扩展程序的浏览器:一个browser action(黄色图标)和一个page action(蓝色图标)。browser action 和 page action 都有一个后台页面。这个图显示了 browser action 的后台页面,它是通过background.html这个文件定义的。background.html中也包含了能够控制 browser action 在两个窗口中的行为的JavaScript代码。
虽然后台页面可能很有用,但除非需要,否则别使用。后台页面一般都是开放的,当一个用户安装了许多含有后台页面的扩展程序时,Chrome的性能可能会受到影响。
下面是一些通常不需要后台页面的扩展程序的例子:
查看 Background Pages 获得更多细节。
扩展程序可以包含显示其界面的普通的HTML页面。例如,一个使用browser action 的扩展程序可以有一个弹出式窗口,该窗口是通过一个HTML文件实现的。任何扩展程序都可以提供一个让用户自定义其如何工作的选项页面。另一种类型的特殊页面是重载页面。最后,你可以使用 chrome.tabs.create() 或者 window.open() 显示在扩展程序中的任何其他HTML页面。
在扩展程序里面的HTML页面能够访问彼此的DOM,也能够相互调用各自的函数。
下图显示了包含一个弹出式窗口的browser action扩展程序的架构。弹出式窗口的内容是由一个HTML文件(popup.html)定义的web页面。这个扩展程序刚好也包含了一个后台页面(backggound.html)。由于弹出式窗口页面能够调用后台页面的函数,因此不需要复制后台页面的代码到自己的页面中。
查看 Browser Actions,Options,Override Pages 和“页面间的通信”这一节获得更多细节。
扩展程序需要一个content script来与web页面进行交互。一个content script其实是一些JavaScript代码,这些代码是在被加载到浏览器的页面的上下文中执行的。我们把content script看做是加载页面的一部分,而不是它所在的扩展程序(称为父扩展程序parent extension)的一部分。
Content script能够读取浏览器所访问的web页面的详细信息,而且能够修改这些页面。在下图中,content script可以读取并修改显示的web页面的DOM。然而,它却不能修改它的父扩展程序的后台页面的DOM。
但content scripts也不是完全和他们的父扩展程序脱离的。像下图的箭头所指示的那样,content script可以和父扩展程序交换信息。比如说无论何时content script发现一个RSS feed,它可以发送一条消息给父扩展程序。或者后台页面可以发送一条消息让 content script 改变其浏览器页面的外观。
请看 Content Scripts 获得更多信息。
//THIS CODE DOESN'T WORK 1: var tab = chrome.tabs.getSelected(null); //WRONG!!! 2: chrome.tabs.update(tab.id, {url:newUrl}); 3: someOtherFunction();
这种办法将会失败,因为getSelected()是一个异步方法,它并不会等待工作完成后才返回,它甚至没有返回一个值(尽管有些异步方法有返回值)。你可以通过在getSelected()的完整名称中的callback参数判断它是一个异步方法:
chrome.tabs.getSelected(integer windowId, function callback)
为了改正之前的代码,你必须使用callback参数。下面的代码告诉你应该如何定义一个回调函数并取得 getSelected()的结果(作为一个名为 tab的参数),然后调用 update()。
//THIS CODE WORKS 1: chrome.tabs.getSelected(null, function(tab) { 2: chrome.tabs.update(tab.id, {url:newUrl}); 3: }); 4: someOtherFunction();
在这个例子里面,各行的代码是按一下的顺序执行的:1,4,2。getSelected 中指定的回调函数仅在当前选择的标签的信息准备好之后才被调用,一般是在 getSelected()返回后的某一时刻。虽然update()也是一个异步函数,但我们没有对其结果做任何事情,所以在这里我们没有使用回调函数。
更多的信息请看chrome.*API文档。
在一个扩展程序中的HTML页面经常需要通信。因为扩展程序里的所有页面都是在同个进程的同个线程中执行,所以它们能够直接调用彼此的函数。在扩展程序中查找页面可以使用chrome.extension
方法,比如说 getViews()和 getBackgroundPage()。在扩展程序中,一旦一个页面能够引用其他的页面,则这个页面可以调用在其他页面中的函数,以及操作它们的DOM。
扩展程序能够使用HTML5的 web storage API(例如 localStorage)保存数据,或者向服务器提交保存数据的请求。无论何时你想要保存某些数据,首先应该考虑的是这些数据是否来自处于隐身模式的窗口。默认情况下,扩展程序不会在隐身模式的窗口中运行,打包应用也是这样。当浏览器处于隐身模式下,你需要考虑用户期望你的扩展程序或者打包应用做什么。
隐身模式下的窗口在离开后将不会留下任何痕迹。当处理来自隐身窗口的数据时,尽可能的遵守这一规则。例如,如果你的扩展程序通常都将用户的浏览历史保存到云端,那么不要保存来自隐身窗口的历史数据。另一方面,你可以保存扩展程序的来自任何窗口的设置,无论是隐身模式还是非隐身模式。
Rule of thumb: 当一个数据显示了用户在网页上的位置或者用户所做的事情,如果它是来自隐身窗口,则不要保存它。
判断一个窗口是否是隐身模式,可以查看相关的 Tab 或 Window 对象的 incognito 属性。例如:
var bgPage = chrome.extension.getBackgroundPage(); function saveTabData(tab, data) { if (tab.incognito) { bgPage[tab.url] = data; // Persist data ONLY in memory } else { localStorage[tab.url] = data; // OK to store data }
注:本系列教程均翻译自谷歌扩展程序官方开发文档