您的位置:首页 > 编程语言 > Go语言

谷歌浏览器扩展程序开发教程之基本概念

2012-04-17 16:46 232 查看


综述

当你看完这一页和入门指南之后,就可以开始开发自己的扩展程序和打包应用程序(packaged apps)了。

Note: 应用程序包是作为扩展程序来实现的,所以除非特别说明,本页所有内容都适用于应用程序包。


基本概念

一个扩展程序其实是压缩捆绑在一起的一系列文件(HTML、CSS、JavaScript、图片以及其他任何需要的文件),它可以向谷歌浏览器中添加新的功能。扩展程序本事上是web页面,它们可以使用浏览器提供给web页面的所有API,从XMLHttpRequest到JSON再到HTML5。
扩展程序可以使用content scripts或者cross-origin XMLHttpRequests与web页面、服务器进行交互。扩展程序也可以和浏览器提供的功能进行互动,比如说书签和标签等。


扩展程序界面

很多扩展程序(不包括打包应用程序)以browser actions或page actions的形式添加自己的界面到浏览器中。每个扩展程序至多只能由一个browser action或page action。当扩展程序是和大多数页面相关时,选择一个browser action。若扩展程序的图标是否显示取决于某个页面,那么应当选择一个page action。




mail扩展程序使用browser action(工具栏上的图标)。这个map扩展程序使用page action (地址栏上的图标) 和content script (注入web页面的代码)。这个news扩展程序也应用了browser action,点击时会显示一个弹出式窗口。
扩展程序和应用程序包也可以以其他的方式呈现它们的界面,比如增加到Chrome的上下文菜单、提供一个选项页面或使用content script改变页面的外观。请参考开发者指南获得扩展程序特性的完整列表以及它们各自的实现细节。


打包应用程序界面

一个打包应用程序通常使用一个捆绑到程序里面的HTML页面来呈现它的主要功能。例如下面的打包应用程序在一个HTML页面中显示了一个Flash文件。



请看Packaged Apps获得更多的信息。


文件

每一个扩展程序包含一下的文件:

一个 manifest 文件

一个或多个 HTML 文件 (除非这个扩展程序是一个主题)

可选: 一个或多个 JavaScript 文件

可选: 任何其他扩展程序所需要的文件,比如说图片文件

在开发扩展程序的时候,需要将所有这些文件都放在同一个文件夹里面。发布扩展程序的时候,这个文件夹会被打包成一个特殊以 .crx 为后缀的ZIP文件。如果使用
Chrome Developer Dashboard 上传扩展程序,则会自动为你创建 .crx文件。更多有关发布扩展程序的细节,请看
Hosting 。


引用文件

你可以将任何你想要的文件放进扩展程序里面,但你怎么使用它呢?通常,你可以使用相对路径引用文件,就像你在一个普通HTML页面做的那样。下面的例子展示了如何引用子目录images中的myimage.png文件。

<img src="images/myimage.png">


正如你所注意到的,当你使用Google Chrome调试器的时候,在扩展程序里面的每一个文件也可以通过一个绝对路径访问,像下面这样:

                                   chrome-extension://<extensionID>/<pathToFile>

在这个URL中,<extensionID>是扩展程序系统为每个程序生成的唯一的标识符。你可以在chrome://extensions页面中看到你所载入的扩展程序的ID。<pathToFile>是文件在扩展程序顶级目录中的位置,也即文件的相对路径。
当你在开发扩展程序(尚未打包)时,扩展程序ID是可以改变的。特别地,如果从不同的目录加载一个未打包的扩展程序,那么其ID是会改变的;在打包的时候扩展程序的ID又也会改变。如果在代码中需要指定扩展程序中某个文件的完整路径,可以在开发期间使用 @@extension_id 这个预定义消息(predefined
message)以避免硬性的指定ID。
扩展程序在被打包(典型地,通过dashboard上传)后会获得一个永久的固定的ID,这个ID即使在以后更新扩展程序的时候也不会改变。一旦ID固定了,就可以将所有出现@@extension_id 的地方改为真正的ID。


manifest 文件

一个名为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的性能可能会受到影响。
下面是一些通常不需要后台页面的扩展程序的例子:
仅仅是通过一个弹出式窗口(或者可能是一个选项页面)呈现界面的使用了browser action的扩展程序。
提供一个重载页面(override page,替换标准Chrome页面的页面)的扩展程序。
含有一个不使用 localStorage 或者扩展程序 API 的content scripts的扩展程序。
除了选项页面,没有其他界面的扩展程序。
查看
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 scripts

扩展程序需要一个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 获得更多信息。


使用chrome.* APIs

除了可以访问web页面和应用使用的所有的API,扩展程序也可以使用和谷歌浏览器紧密结合的Chrome独有的API(通常称为chrome.*API)。例如,任何扩展程序或者web应用可以使用标准的window.open() 方法打开网址。若想要指定该网站显示在哪个窗口上,扩展程序可以使用Chrome独有的chrome.tabs.create()
方法来代替。
异步方法和同步方法
大部分chrome.*API里面的方法都是异步的:这些方法不会等待某个操作完成就立即返回。如果需要了解操作的结果,可以将一个回调函数(callback functions)作为参数传递给异步方法。回调函数将会稍后执行(可能是在很久以后),在方法返回后的某一时刻。下面是一个异步方法的完整名称:

chrome.tabs.create(object createProperties,
function callback)

其他的 chrome.* 方法是同步的。它们不需要回调函数,因为它们会等到所有的工作完成后才返回。通常,同步方法有一个返回类型。考虑方法 chrome.extensions.getBackgroundPage():

DOMWindow chrome.extension.getBackgroundPage()

这个方法没有回调函数,它的返回类型为 DOMWindow。它同步地返回了后台页面且没有执行其他的非同步的工作。


举例:使用回调函数

假设你想要将用户当前选择的标签导航到一个新的网址。为了达到这样的目的,你需要取得当前标签的ID(使用方法 chrome.tabs.getSelected())然后让这个标签转到新的网址(使用方法 chrome.tabs.update())。
如果
getSelected() 是同步的,你可以像下面这样编写代码:

//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
}


注:本系列教程均翻译自谷歌扩展程序官方开发文档
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息