当您看完该页面以及入门教程后,您已经准备好开始编写应用了。
基础
应用由一些文件(包括HTML、CSS、JavaScript、图片以及其他任何您需要的文件)经过 zip 打包得到,为百度浏览器增加功能。应用本质上是网页,它们可以利用浏览器为网页提供的所有 API,例如XMLHttpRequest、JSON、HTML 5 等等。
应用可以通过内容脚本或跨域 XMLHttpRequest 与网页或者服务器交互,应用也可以以编程方式与浏览器功能。
应用的用户界面
<!—ecms @Many extensions—but not Chrome Apps—addUI to百度浏览器in the form ofbrowser actionsor page actions.Each extension can have at most one browser action or page action.Choose a browser action when the extension is relevant to most pages.Choose a page action when the extension’s iconshould appear or disappear,depending on the page.–>许多应用(但不包括百度浏览器应用)以浏览器按钮或页面按钮的形式向百度浏览器增加用户界面,每个应用最多能有一个浏览器按钮或页面按钮。当应用与大部分网页相关时选择使用浏览器按钮,当应用的图标显示还是消失取决于具体网页时选择使用页面按钮。
应用(以及百度浏览器应用)也可以以其他形式呈现用户界面,例如在百度浏览器的右键菜单中添加内容,提供选项页面,或者利用内容脚本更改页面的显示方式。有关完整的应用功能以及每一种功能的实现细节,请参见开发者指南。
文件
每一个应用包含以下文件:
- <!—ecms @A manifest file–>一个清单文件
- <!—ecms @One or more HTML files (unless the extension is a theme)–>一个或多个 HTML 文件(除非应用是一个主题背景)
- <!—ecms @Optional: One or more JavaScript files–>可选:一个或多个 JavaScript 文件
- <!—ecms @Optional: Any other files your extension needs—for example, image files–>可选:您的应用需要的任何其他文件,例如图片
<!—ecms @While you're working on your extension,you put all these files into a single folder.When you distribute your extension,the contents of the folder are packaged into a special ZIP filethat has a .crx suffix.If you upload your extension using theChrome Developer Dashboard,the
.crx file is created for you.For details on distributing extensions,see Hosting.-->当您编写您的应用时,您将所有这些文件放在一个文件夹中。当您发布您的应用时,该文件夹的内容将被压缩成一个特殊的ZIP 文件,以
.crx 为后缀。<!---ecms 如果您通过Chrome开发者信息中心上传您的应用,该
.crx文件会自动为您创建。有关发布扩展的细节,请参见托管。-->
引用文件
<!---ecms @You can put any file you like into an extension,but how do you use it?Usually,you can refer to the file using a relative URL,just as you would in an ordinary HTML page.Here's an example of referring toa file named myimage.pngthat's in a subfolder named
images.-->您可以在应用中放置您需要的任何文件,但是您如何使用它们呢?通常,您可以通过相对URL 引用文件,就像在普通的 HTML页面中那样。下面是一个例子,引用位于子文件夹
images 中名为
myimage.png 的文件。
<img <b>src="images/myimage.png"</b>>
您使用百度浏览器的调试器时可能会发现,应用中的每一个文件也可以通过绝对 URL 访问,如下所示:
chrome-extension://<应用标识符>/<文件路径>
<!---ecms @In that URL, the <extensionID> is a unique identifierthat the extension system generates for each extension.You can see the IDs for all your loaded extensionsby going to the URL chrome://extensions.The <pathToFile> is the location of the fileunder the extension's top folder;it's the same as the relative URL.-->在这一 URL 中,<应用标识符>是应用系统为每一个应用生成的唯一标识符,您可以进入chrome://extensions查看您加载的所有应用的标识符。<文件路径>是应用的主目录下的文件位置,与相对 URL 相同。
<!---ecms @While you're working on an extension(before it's packaged),the extension ID can change.Specifically, the ID of an unpacked extension will changeif you load the extension from a different directory;the ID will change again when you package the extension.If your extension's codeneeds to specify the full path to a file within the extension,you can use the @@extension_idpredefined messageto avoid hardcoding the ID during development.-->当您编写应用时(打包之前),应用标识符可能会更改。特别地,如果您从另一个目录加载未打包的应用,它的标识符会改变,当您打包应用时会再次改变。如果您的应用代码需要指定应用中某个文件的完整路径,您可以使用
@@extension_id 这一预定义消息,避免开发过程中硬编码标识符。
<!---ecms @When you package an extension(typically, by uploading it with the dashboard),the extension gets a permanent ID,which remains the same even after you update the extension.Once the extension ID is permanent,you can change all occurrences of@@extension_id to use the real ID.-->当您打包应用时(典型情况下,通过信息中心上传),该应用将会获得一个永久的标识符,即使您更新了这一应用仍然保持不变。一旦应用的标识符变成永久的了,您就可以将所有的
@@extension_id 修改为真正的唯一标识符。
清单文件
清单文件名为 manifest.json,提供有关应用的各种信息,例如最重要的文件和应用可能具有的能力。以下是一个典型的清单文件,用于一个浏览器按钮,它将会访问来自 google.com 的信息:
{ "name": "我的应用", "version": "2.1", "description": "从 Google 获取信息。", "icons": { "128": "icon_128.png" }, "background": { "persistent": false, "scripts": ["bg.js"] }, "permissions": ["http://*.google.com/", "https://*.google.com/"], "browser_action": { "default_title": "", "default_icon": "icon_19.png", "default_popup": "popup.html" }}
有关更多细节,请参见清单文件。
架构
<!---ecms @Many extensions have a background page,an invisible pagethat holds the main logic of the extension.An extension can also contain other pagesthat present the extension's UI.If an extension needs to interact with web pages that the user loads(as opposed to pages that are included in the extension),then the extension must use a content script.-->许多应用有一个后台网页,它是一个包含应用主要逻辑的不可见页面。应用也可以包含其他页面,展现应用的用户界面。如果应用需要与用户加载的网页交互(相对于包含在应用中的页面),应用必须使用内容脚本。
后台网页
<!---ecms @The following figure shows a browserthat has at least two extensions installed:a browser action (yellow icon)and a page action (blue icon).Both the browser action and the page actionhave background pages.This figure shows the browser action's background page,which is defined by background.htmland has JavaScript code that controlsthe behavior of the browser action in both windows.-->下图所示的浏览器至少安装了两个应用:一个浏览器按钮(黄色图标)和一个页面按钮(蓝色图标)。浏览器按钮和页面按钮都有后台页面。下图显示了浏览器按钮的后台页面,由
background.html 定义,并且包含在这两个窗口中控制浏览器按钮的JavaScript 代码。
后台网页持续运行,持续运行的后台网页保持打开状态。
有关更多细节,请参见后台网页。
用户界面网页
<!---ecms @Extensions can contain ordinary HTML pages that display the extension's UI.For example, a browser action can have a popup,which is implemented by an HTML file.Any extension can have an options page,which lets users customize how the extension works.Another type of special page is the override page.And finally, you canuse tabs.createor window.open()to display any other HTML files that are in the extension.-->应用可以包含普通的 HTML网页,用来显示应用的用户界面。例如,浏览器按钮可以包含弹出菜单,通过HTML 文件实现。最后,您可以使用tabs.create 或
window.open()来显示应用中的任何其他 HTML 文件。
应用中的 HTML 网页可以互相访问其他页面的全部DOM,并且可以互相调用函数。
<!---ecms @The following figure shows the architectureof a browser action's popup.The popup's contents are a web pagedefined by an HTML file(popup.html).This extension also happens to have a background page(
background.html).The popup doesn't need to duplicate codethat's in the background pagebecause the popup can invoke functions on the background page.-->下图显示了浏览器按钮弹出菜单的架构。弹出菜单是由一个 HTML文件(
popup.html)定义的网页,该应用也正好有一个后台网页(
background.html)。弹出窗口不用重复后台网页中的代码,因为弹出窗口可以调用后台网页上的函数。
有关更多细节,请参见浏览器按钮和页面间通信这些部分。
内容脚本
<!---ecms @If your extension needs to interact with web pages,then it needs a content script.A content script is some JavaScriptthat executes in the context of a pagethat's been loaded into the browser.Think of a content script as part of that loaded page,not as part of the extension it was packaged with(its parent extension).-->如果您的应用需要与网页交互,您就需要使用内容脚本。内容脚本是一些JavaScript代码,它们在浏览器中已加载页面的上下文中执行。您应该将内容脚本视为已加载页面的一部分,而不是打包在一起的应用(它所属的应用)的一部分。
内容脚本可以读取浏览器访问的网页的细节,并且可以修改页面。在下图中,内容脚本可以读取并且修改显示的网页的DOM。然而,它不能修改所属应用后台网页的 DOM。
内容脚本并不是完全与所属应用隔离的。内容脚本可以与所属应用交换消息,如下图箭头所示。例如,每当在浏览器页面中发现 RSS 供稿时,内容脚本可以发送消息,反过来后台页面也可以发送消息要求内容脚本更改浏览器页面的外观。
有关更多信息,请参见内容脚本。
使用 chrome.* API
<!---ecms @In addition to having access to all the APIs that web pages and apps can use,extensions can also use Chrome-only APIs(often called chrome.* APIs)that allow tight integration with the browser.For example, any extension or web app can use thestandard window.open() method to open a URL.But if you want to specify which window that URL should be displayed in,your extension can use the Chrome-onlytabs.createmethod instead.-->应用除了能够使用网页和应用可以使用的所有 API 外,还能使用仅用于百度浏览器的 API(通常称为 chrome.* API)来更好地与浏览器集成。例如,任何应用或网上应用可以使用标准的
window.open()方法来打开一个网页,但是如果您想指定网页应该显示在哪个窗口中,您的应用就可以使用仅用于百度浏览器的 tabs.create 方法。
异步方法与同步方法的区别
<!---ecms @Most methods in the chrome.* APIs are asynchronous:they return immediately, without waiting for the operation to finish.If you need to know the outcome of that operation,then you pass a callback function into the method.That callback is executed later (potentially much later),sometime after the method returns.Here's an example of the signature for an asynchronous method:-->大部分 chrome.* API 的方法都是异步的,它们不等待操作完成就立即返回。如果您需要知道操作结果,您可以向方法传递一个回调函数,回调函数将稍后在方法返回后的某个时刻执行(可能很久之后)。下面是一个异步方法签名的例子:
chrome.tabs.create(object createProperties, function callback)
<!---ecms @Other chrome.* methods are synchronous.Synchronous methods never have a callbackbecause they don't return until they've completed all their work.Often, synchronous methods have a return type.Consider theruntime.getURL method:-->也有一些 chrome.* 方法是同步的。同步的方法没有回调参数,因为它们只有当所有操作完成后才返回。通常,同步方法有返回值类型。考虑runtime.getURL 方法:
string chrome.runtime.getURL()
<!---ecms @This method has no callback and a return type of stringbecause it synchronously returns the URLand performs no other, asynchronous work.-->该方法没有回调参数,但是有返回值类型
string,因为它同步地返回URL,不进行任何其他异步操作。
例子:使用回调函数
假设您想在用户当前选定的标签页中打开新的页面。要想这么做,您首先需要获得当前标签页的标识符(使用 tabs.query),然后使该标签转到指定的新的URL(使用 tabs.update)。
假如 query() 是同步的,您可能会写这样的代码:
<b>//以下代码不能正常工作!</b>var tab = chrome.tabs.query({'active': true}); <b>//错误!</b>chrome.tabs.update(tab.id, {url:newUrl});someOtherFunction();
<!---ecms @That approach failsbecause query() is asynchronous.It returns without waiting for its work to complete,and it doesn't even return a value(although some asynchronous methods do).You can tell that
query() is asynchronousby the callback parameter in its signature:-->这样的方法不行,因为
query()是异步的,它不等待操作完成就返回了,并且事实上它都不返回任何值(尽管有些异步方法会返回信息)。您可以通过它签名中的callback参数看出
query() 是异步的:
chrome.tabs.query(object queryInfo, function callback)
<!---ecms @To fix the preceding code,you must use that callback parameter.The following code showshow to define a callback functionthat gets the results from query()(as a parameter named
tab)and calls
update().-->要改正上面的代码,您必须使用那个回调参数。以下代码显示如何定义一个回调函数,从
query() 获得结果(通过名为
tab 的参数)并调用
update()。
<b>//以下代码可以正常工作</b>chrome.tabs.query({'active': true}, <b>function(tabs) {</b> chrome.tabs.update(tabs[0].id, {url: newUrl});<b>}</b>);someOtherFunction();
<!---ecms @In this example, the lines are executed in the following order: 1, 4, 2.The callback function specified to query() is called(and line 2 executed)only after information about the currently selected tab is available,which is sometime after
query() returns.Although
update() is asynchronous,this example doesn't use its callback parameter,since we don't do anything about the results of the update.-->在这一例子中,以上几行是按照这样的顺序执行的:1、4、2。只有在有关当前选定标签的信息可用后,即
query() 返回后的某一时刻,才调用在
query()中指定的回调函数(并且执行第二行)。尽管
update()是异步的,这一例子没有使用回调参数,因为我们对于调用的结果并不感兴趣。
更多详情
有关更多信息,请参见chrome.* API 文档
页面间的通信
应用中的 HTML 网页通常需要通信。因为一个应用的所有网页在同一个进程中的同一个线程上执行,网页之间可以直接调用函数。
<!---ecms @To find pages in the extension, usechrome.extensionmethods such as
getViews() and
getBackgroundPage().Once a page has a reference to other pages within the extension,the first page can invoke functions on the other pages,and it can manipulate their DOMs.-->要获得应用中的网页,请使用
chrome.extension方法,例如 extension.getViews 和 extension.getBackgroundPage。一旦一个网页引用了应用中的其他网页,第一个网页可以执行其他网页上的函数,并且可以操纵它们的 DOM。
保存数据和隐身模式
<!---ecms @Extensions can save data using the storage API,the HTML5 web storage API(such as localStorage)or by making server requests that result in saving data.Whenever you want to save something,first consider whether it'sfrom a window that's in incognito mode.By default, extensions don't run in incognito windows.You need to consider what a user expectsfrom your extensionwhen the browser is incognito.-->应用可以使用 storage API、HTML5网页存储 API(例如
localStorage)或者向服务器发出请求保存数据。每当您要保存任何数据前,首先要考虑它是否来自隐身窗口。默认情况下,应用不在隐身窗口中运行。当浏览器处于隐身模式时,您需要考虑用户对您的应用的需求。
<!---ecms @Incognito mode promises that the window will leave no tracks.When dealing with data from incognito windows,do your best to honor this promise.For example, if your extension normallysaves browsing history to the cloud,don't save history from incognito windows.On the other hand, you can storeyour extension's settings from any window,incognito or not.-->隐身模式确保不会留下任何痕迹。当处理来自隐身窗口的数据时,尽可能地遵守这一约定。例如,如果您的应用通常将浏览器历史记录保存至云端,不要保存来自隐身窗口的历史记录。另一方面,您可以在任何窗口中保存您的应用设置,无论隐身与否。
准则:如果某些数据可能显示用户在网上的访问记录或者用户所做的事情,千万不要保存这些来自隐身窗口的数据。
<!---ecms @To detect whether a window is in incognito mode,check the incognito property of the relevanttabs.Tab orwindows.Window object.For example:-->要确定窗口是否处于隐身模式,检查相关的 tabs.Tab 或windows.Window 对象的
icognito 属性。例如:
function saveTabData(tab, data) { if (tab.incognito) { chrome.runtime.getBackgroundPage(function(bgPage) { bgPage[tab.url] = data; // 仅在内存中保留数据 }); } else { localStorage[tab.url] = data; // 可以保存数据 }}
现在做什么呢?
现在您已经大致了解应用了,您应该准备好编写您自己的应用了。您接下来可以参考以下内容:
来源: https://chajian.baidu.com/developer/extensions/overview.html