Firefox OS 是一个基于 Firefox 网页浏览器引擎构建的操作系统,该引擎称为 Gecko。Firefox OS 上的浏览器应用程序提供了一个使用 HTML5 技术编写的用户界面,并使用 浏览器 API 管理网页浏览。它还根据实现管理选项卡、浏览历史记录、书签等。
虽然 Firefox OS 已经包含一个浏览器,但您可以使用浏览器 API 来创建自己的浏览器或将浏览器功能添加到您的应用程序。本文介绍了如何为 Firefox OS 设备构建浏览器应用程序。按照这些步骤,您将获得一个基本的 Firefox OS 浏览器应用程序,其中包含一个地址栏和后退/前进按钮以浏览网页。
源代码可以在 https://github.com/begeeben/firefox-os-browser-sample 下载。
先决条件:WebIDE
您可以通过 Firefox 34 或更高版本使用 WebIDE。开发、构建或测试浏览器应用程序不需要 Firefox OS 设备。通过使用 WebIDE,我们可以轻松地引导一个 Web 应用程序,进行 HTML/CSS/JS 修改,并在 Firefox OS 模拟器之一上运行应用程序。要在 Firefox 中打开 WebIDE,请从顶部菜单中选择**工具 > Web 开发者 > WebIDE**
从模板创建应用程序
首先,使用 WebIDE 空模板引导一个 Web 应用程序。应用程序类型需要是特权的,以便可以设置browser
权限。为了使用 浏览器 API,需要此权限。 浏览器 API 提供了管理 iframe 的附加方法和事件。
以下是应用程序的外观截图。接下来我们将开始添加代码以制作一个简单的浏览器应用程序。
编辑 manifest.webapp
让我们开始进行一些代码更改。模板已经在 manifest.webapp 中将应用程序类型设置为privileged
。
"type": "privileged",
要允许我们的应用程序使用浏览器 API,我们需要指定“browser
”权限。
"permissions": {
"browser": {}
},
HTML 结构
我们正在构建的浏览器应用程序将在顶部有一个工具栏,以及一个作为 iframe 容器的 div,默认情况下它显示“Hello myBrowser!”。浏览器 iframe 将稍后使用 JavaScript 创建。我们可以在 HTML 中添加 iframe,但在本示例中,将动态创建新的浏览器 iframe。
Hello myBrowser!
以下是简单浏览器应用程序的截图
管理浏览器 iframe
浏览器应用程序必须处理mozbrowser
事件,这些事件在应用程序具有browser
权限时可用。为了分离 UI 和mozbrowser
事件处理,并保留将来支持多个选项卡的灵活性,我们添加了一个 tab.js 文件。以下是 tab.js 中的代码,该代码使用“mozbrowser
”属性创建了一个 iframe 以启用 浏览器 API 的使用。
/**
* Returns an iframe which runs in a child process with Browser API enabled
* and fullscreen is allowed
*
* @param {String} [url] Optional URL
* @return {iframe} An OOP mozbrowser iframe
*/
function createIFrame (url) {
var iframe = document.createElement('iframe');
iframe.setAttribute('mozbrowser', true);
iframe.setAttribute('mozallowfullscreen', true);
iframe.setAttribute('remote', true);
if (url) {
iframe.src = url;
}
return iframe;
}
mozallowfullscreen
属性使 iframe 的嵌入网页能够使用全屏模式。网页可以通过调用Element.mozRequestFullscreen()
来请求全屏模式。
“remote
”属性将嵌入的 iframe 分隔到另一个子进程中。出于安全原因,需要这样做,以防止恶意网站破坏浏览器应用程序。目前,此属性在此示例浏览器应用程序中没有任何作用,因为嵌套 OOP 尚未实现。请参阅 错误 1020135 – (nested-oop) [meta] 允许嵌套 oop <iframe mozbrowser>.
接下来,将“Tab
”对象构造函数添加到 tab.js。此构造函数处理浏览器 iframe 创建和浏览器事件处理。当构造一个 Tab 时,它会创建一个浏览器 iframe 并将mozbrowser
事件侦听器附加到它。
/**
* The browser tab constructor.
*
* Creates an iframe and attaches mozbrowser events for web browsing.
*
* Implements EventListener Interface.
*
* @param {String} url An optional plaintext URL
*/
function Tab (url) {
this.iframe = createIFrame(url);
this.title = null;
this.url = url;
this.iframe.addEventListener('mozbrowserloadstart', this);
this.iframe.addEventListener('mozbrowserlocationchange', this);
this.iframe.addEventListener('mozbrowsertitlechange', this);
this.iframe.addEventListener('mozbrowserloadend', this);
this.iframe.addEventListener('mozbrowsererror', this);
};
还有其他未在此简单浏览器应用程序中使用的mozbrowser
事件。在此示例中使用的事件可以访问有关 iframe 的有用信息,而我们的浏览器应用程序使用它们来提供网页详细信息,例如标题、URL、加载进度、上下文菜单等。
例如,要在工具栏上显示页面标题,我们使用mozbrowsertitlechange
事件来检索网页的标题。更新标题后,会分发一个带有 Tab 本身的详细信息的CustomEvent
'tab:titlechange'
,以通知其他组件更新标题。
Tab.prototype.mozbrowsertitlechange = function _mozbrowsertitlechange (e) {
if (e.detail) {
this.title = e.detail;
}
var event = new CustomEvent('tab:titlechange', { detail: this });
window.dispatchEvent(event);
};
现在可以在主 app.js 中添加代码来处理此自定义事件,该事件将更新标题。
/**
* Display the title of the currentTab on titlechange event.
*/
window.addEventListener('tab:titlechange', function (e) {
if (currentTab === e.detail) {
urlInput.value = currentTab.title;
}
});
在提交事件中浏览网页
在浏览器中使用地址栏作为搜索栏是一种常见的实用做法。当用户提交输入时,首先我们会检查它是否是有效的 URL。如果不是,则输入被视为搜索词,并将其附加到搜索引擎 URI。请注意,可以以多种方式处理 URL 的验证。示例应用程序使用了一个类型属性设置为 URL 的输入元素。还可以使用一个 URL 对象,并将 URL 字符串作为第一个参数传递给构造函数。如果 URL 无效,则会抛出 DOM 异常。然后可以捕获此异常,并假定 URL 字符串是搜索词。
/**
* The default search engine URI
*
* @type {String}
*/
var searchEngineUri = 'https://search.yahoo.com/search?p={searchTerms}';
/**
* Using an input element to check the validity of the input URL. If the input
* is not valid, returns a search URL.
*
* @param {String} input A plaintext URL or search terms
* @param {String} searchEngineUri The search engine to be used
* @return {String} A valid URL
*/
function getUrlFromInput(input, searchEngineUri) {
var urlValidate = document.createElement('input');
urlValidate.setAttribute('type', 'url');
urlValidate.setAttribute('value', input);
if (!urlValidate.validity.valid) {
var uri = searchEngineUri.replace('{searchTerms}', input);
return uri;
}
return input;
}
然后可以在主 app.js 中添加代码来处理提交按钮。此代码检查是否存在当前活动的Tab
对象,如果存在,则加载 URL 或如果 URL 未更改则重新加载 URL。如果不存在,则创建该对象并加载 URL。
/**
* Check the input and browse the address with a Tab object on url submit.
*/
window.addEventListener('submit', function (e) {
e.preventDefault();
if (!currentUrlInput.trim()) {
return;
}
if (frameContainer.classList.contains('empty')) {
frameContainer.classList.remove('empty');
}
var url = getUrlFromInput(currentUrlInput.trim(), searchEngineUri);
if (!currentTab) {
currentTab = new Tab(url);
frameContainer.appendChild(currentTab.iframe);
} else if (currentUrlInput === currentTab.title) {
currentTab.reload();
} else {
currentTab.goToUrl(url);
}
});
currentTab.reload
函数使用Browser API
提供的iframe.reload
函数来重新加载页面。以下代码添加到 tab.js 文件中以处理重新加载。
/**
* Reload the current page.
*/
Tab.prototype.reload = function _reload () {
this.iframe.reload();
};
启用/禁用后退和前进按钮
最后,可以使用 浏览器 API 来检查页面是否可以在导航历史记录中后退或前进。iframe.getCanGoBack
方法返回一个DOMRequest
对象,该对象在其onsuccess
回调中指示页面是否可以后退。我们使用Promise
来包装此函数,以便更轻松地访问。此代码添加到 tab.js 文件中。
/**
* Check if the iframe can go backward in the navigation history.
*
* @return {Promise} Resolve with true if it can go backward.
*/
Tab.prototype.getCanGoBack = function _getCanGoBack () {
var self = this;
return new Promise(function (resolve, reject) {
var request = self.iframe.getCanGoBack();
request.onsuccess = function () {
if (this.result) {
resolve(true);
} else {
resolve(false);
}
};
});
};
当页面加载时,将在 app.js 文件中执行检查。当 iframe 接收mozbrowserloadend
事件时,就会发生这种情况。
/**
* Enable/disable goback and goforward buttons accordingly when the
* currentTab is loaded.
*/
window.addEventListener('tab:loadend', function (e) {
if (currentTab === e.detail) {
currentTab.getCanGoBack().then(function(canGoBack) {
gobackButton.disabled = !canGoBack;
});
currentTab.getCanGoForward().then(function(canGoForward) {
goforwardButton.disabled = !canGoForward;
});
}
});
运行应用程序
现在可以使用 Firefox OS 模拟器之一来测试示例浏览器应用程序。
在 WebIDE 的右上角,单击**选择运行时**以选择一个 Firefox OS 手机或模拟器
选择并启动 Firefox OS 运行时后,您可以通过单击 WebIDE 中的播放按钮来安装并运行该应用程序。有关构建、调试和部署 Firefox OS 应用程序的更多信息,请参阅 WebIDE 文档。
最后的想法
您可以向这个简单的浏览器添加更多功能以使其真正有用,包括书签、设置、搜索建议和共享。随意扩展此代码并享受使用乐趣。让我们知道您的想法,并务必传播 Firefox OS 的信息!
其他信息
https://hacks.mozilla.ac.cn/2014/08/building-the-firefox-browser-for-firefox-os/
https://mdn.org.cn/en-US/docs/Web/API/Using_the_Browser_API
2 评论