使用 WebAPI 使网页层更强大

为了使 Firefox OS 和网络平台成为开发人员更强大的层级和替代方案,我们正在开发一系列WebAPI。我想在此向您介绍它们!

本博客文章中涵盖的许多内容也出现在我关于此主题的演讲中。

标准化

当您谈论新技术、想法和解决方案时,人们往往会保持谨慎。他们可能会将其视为“非我所创”综合征,但这并非我们的意图(正如我们在此之前写过的那样,并且正如我们的首席技术官 Brendan Eich 提及的那样)。

我们的意图是,我们所做的一切都是或将要成为标准化的。在开放的环境中开发。

本博客文章重点介绍了各种 WebAPI、它们的安全性级别以及如何使用它们。在以后的文章中,我们将专门关注标准化及其进展。

API 类型

基本上有三种类型的 WebAPI

常规 API
任何应用程序都可以使用的 API,无论是托管的还是打包的
特权 API
仅在特权应用程序中可用。特权应用程序是指:

认证 API
认证 API 仅适用于系统本身(对于 Firefox OS 来说是 Mozilla),这意味着它们非常敏感,需要严格控制。

常规 API

常规 API 的完整列表:

  • 振动 API
  • 屏幕方向
  • 地理位置 API
  • 鼠标锁定 API
  • 开放式 Web 应用程序
  • 网络信息 API
  • 电池状态 API
  • 闹钟 API
  • 网络活动
  • 推送通知 API
  • WebFM API
  • 网络支付
  • IndexedDB
  • 环境光线传感器
  • 接近传感器
  • 通知
  • FMRadio

以下是如何使用其中一些 API

电池状态 API

此 API 用于检测计算机/设备的当前电量级别、剩余电量以及是否正在充电。在桌面、Android 和 Firefox OS 三种平台上均有效。

var battery = navigator.battery;

if (battery) {

    var batteryLevel = Math.round(battery.level * 100) + "%",

        charging = (battery.charging)? "" : "not ",

        chargingTime = parseInt(battery.chargingTime / 60, 10),

        dischargingTime = parseInt(battery.dischargingTime / 60, 10);

        // Set events

        battery.addEventListener("levelchange", showStatus);
        battery.addEventListener("chargingchange", showStatus);
        battery.addEventListener("chargingtimechange", showStatus);
        battery.addEventListener("dischargingtimechange", showStatus);

}

振动 API

使设备振动,可以振动一次或以特定模式振动。

// Vibrate for one second

navigator.vibrate(1000);

// Vibration pattern [vibrationTime, pause,…]

navigator.vibrate([200, 100, 200, 100]);

// Vibrate for 5 seconds

navigator.vibrate(5000);

// Turn off vibration

navigator.vibrate(0);

屏幕方向

使您作为开发人员有机会锁定方向,或指定所需的初始方向体验。

/*
    Possible values:
        "landscape",
        "portrait"
        "landscape-primary"
        "landscape-secondary"
        "portrait-primary"
        "portrait-secondary"

*/
var portraitLock = screen.mozLockOrientation("portrait");
if (portraitLock) {
    console.log("Orientation locked to portrait");
}

地理位置 API

查找用户当前的位置 - 需要用户同意才能共享此信息。

navigator.geolocation.getCurrentPosition(function (position) {
    /*
        Getting latitude and longitude:
            position.coords.latitude
            position.coords.longitude
};

鼠标锁定 API

锁定鼠标移动并自行控制体验。当您不希望鼠标指针/交互在到达网页浏览器窗口边缘时结束,而是希望继续滚动时,尤其有用 - 例如完成环境的 360 度旋转或类似操作。

var docElm = document.documentElement;

// Requesting Pointer Lock

docElm.requestPointerLock = elem.requestPointerLock ||
                            elem.mozRequestPointerLock ||
                            elem.webkitRequestPointerLock;

docElm.requestPointerLock();

document.addEventListener("mousemove", function(e) {
    var movementX = e.movementX       ||
                    e.mozMovementX    ||
                    e.webkitMovementX ||
                    0,
        movementY = e.movementY       ||
                    e.mozMovementY    ||
                    e.webkitMovementY ||
                    0;

    // Get the mouse movement delta values
    console.log("movementX=" + movementX, "movementY=" + movementY);  
}
);

开放式 Web 应用程序

通常情况下,API 需要安装和处理开放式 Web 应用程序。

var installApp = navigator.mozApps.install(manifestURL);

// Successful install
installApp.onsuccess = function(data) {
    console.log("Success, app installed!");
};

// Install failed
installApp.onerror = function() {
    console.log("Install failedn:" + installApp.error.name);
};

网络信息 API

用于获取网络连接信息。

var connection = window.navigator.mozConnection,
    online = connection.bandwidth,
    metered = connection.metered;

// online can return:
    0 when offline
    Infinity when the bandwidth isn't known
    Estimation of MB/s

// metered implies if the connection is being metered,
   meaning limited in some way from the ISP

闹钟 API

使设置闹钟成为可能。

request = navigator.mozAlarms.add(
    new Date("May 15, 2012 16:20:00"),
    "honorTimezone",
    {
        mydata: "my event"
    }
);

网络活动

通过网络活动,您可以指定对要执行的操作或应用程序可以处理的操作的意图。

var pick = new MozActivity({
     name: "pick",
     data: {
         type: ["image/png", "image/jpg", "image/jpeg"]
     
}
 });

pick.onsuccess = function () {

    var img = document.createElement("img");
    img.src = window.URL.createObjectURL(this.result.blob);
    document.body.appendChild(img);
};

我在另一篇博客文章中详细介绍了网络活动

推送通知 API

网站向用户发送消息的方式,即使用户不在其网站上。API 处于草案阶段,尚未实施。有关更多信息,请参阅PushAPI 文档。

function getPushURL() {
    var push = navigator.push ||
                navigator.mozPush ||
                navigator.webkitPush;

    // Ask the user to allow notifications
    var request = push.requestURL(watoken, PbK);

    request.onsuccess = function () {
        var url = request.result.url;
        console.log('Push URL: ' + url);
    };
}

WebFM API

在网页层中实现 FM 收音机。

var fmRadio = navigator.fm || navigator.mozFMRadio || navigator.mozFM;
fmRadio.frequency = 106.7;

网络支付

用于通过 JSON Web Token (JWT) 启用应用程序内支付。

var request = navigator.mozPay(JWTs);
request.onsuccess = function () {
    // Money!
};

IndexedDB

结构化的客户端存储,具有高性能搜索支持。在使用 IndexedDB在 IndexedDB 中存储图像和文件 中进行了详细介绍。

// Create/open database
var request = indexedDB.open("elephantFiles", 1),
     createObjectStore = function (dataBase) {
        console.log("Creating objectStore")
        dataBase.createObjectStore("elephants");
};

request.onsuccess = function (event) {
    console.log("Success creating/accessing IndexedDB database");
    db = request.result;

    db.onerror = function (event) {
        console.log("Error creating/accessing IndexedDB database");
    };
}

// Needed for creating database/upgrading to a new version
request.onupgradeneeded = function (event) {
    createObjectStore(event.target.result);
};

环境光线传感器

检测环境光线级别,以便根据用户当前所在的环境提供不同的版本。

window.addEventListener("devicelight", function (event) {

    /* The level of the ambient light in lux

       A lux value for "dim" typically begin below 50,
       and a value for "bright" begin above 10000
    */
    console.log(event.value);

});

window.addEventListener("lightlevel", function (event) {
    // Possible values: "normal", "bright", "dim"
    console.log(event.value);

});

接近传感器

获取设备与另一个物体之间距离的指示。

window.addEventListener("deviceproximity", function (event) {

    // Current device proximity, in centimeters

    console.log(event.value);



    // The maximum sensing distance the sensor is 

    // able to report, in centimeters

    console.log(event.max);



    // The minimum sensing distance the sensor is 

    // able to report, in centimeters

    console.log(event.min);
});

通知

能够向用户显示通知。

var notification = navigator.mozNotification;

notification.createNotification(
    "See this",
    "This is a notification"
);
// You could send an optional third parameter,
// which would be the URL to an icon

特权 API

这些 API 只能在特权应用程序中使用。

特权 API 的完整列表:

  • 设备存储 API
  • 浏览器 API
  • TCP 套接字 API
  • 联系人 API
  • systemXHR

设备存储 API

访问存储在设备上的文件。

var storage = navigator.getDeviceStorage("videos"),

    cursor = storage.enumerate();



cursor.onerror = function() {
    console.error("Error in DeviceStorage.enumerate()", cursor.error.name);

};



cursor.onsuccess = function() {

    if (!cursor.result)

        return;

    }


    var file = cursor.result;

    // If this isn't a video, skip it

    if (file.type.substring(0, 6) !== "video/") {

        cursor.continue();

        return;
    }

    // If it isn't playable, skip it

    var testplayer = document.createElement("video");

    if (!testplayer.canPlayType(file.type)) {

        cursor.continue();

        return;
    }

    // Show file
    console.log(file.name);
};

浏览器 API

使用网络技术完全实现您自己的网络浏览器。在BrowserAPI 中有更多介绍。

iframe.addEventListener("mozbrowserlocationchange", function(e) {
    console.log(e.detail);
});

iframe.addEventListener("mozbrowsersecuritychange", function(e) {
    // "secure", "insecure", or "broken".  "broken" indicates mixed content.
    console.log(e.detail.state);
});

iframe.addEventListener("mozbrowsercontextmenu", function(e) {
    // Show context menu
});

TCP 套接字 API

低级 TCP 套接字 API,还将包括 SSL 支持。

var TCPSocket = navigator.mozTCPSocket.open(
    host,
    port,
    {
        useSSL: crypto,
        binaryType: "arraybuffer"
    }
);

联系人 API

访问设备上的联系人 - 添加、读取或修改。

var contact = new mozContact();

contact.init({name: "Tom"});



var request = navigator.mozContacts.save(contact);

request.onsuccess = function() {
    console.log("Success");

};



request.onerror = function() {
    console.log("Error")

};

systemXHR

使跨域 XMLHTTPRequest 成为可能。在清单文件的权限部分中指定您要访问它 - "systemXHR":{} - 然后只需执行请求即可。

var xhr = new XMLHttpRequest();
xhr.open("GET", anyURL, true);

认证 API

认证 API 仅适用于系统本身/预安装的应用程序。对于 Firefox OS 来说,这意味着仅限 Mozilla。

认证 API 的完整列表:

  • 网络电话
  • 网络短信
  • 空闲 API
  • 设置 API
  • 电源管理 API
  • 移动连接 API
  • Wi-Fi 信息 API
  • 网络蓝牙
  • 权限 API
  • 网络统计信息 API
  • 相机 API
  • 时间/时钟 API
  • 注意屏幕
  • 语音邮件

如果您有兴趣测试或为Gaia(Firefox OS 的 UI)贡献,我将在此列出其中一些 API。

网络电话

用于拨打、接听和处理电话。

// Telephony object
var tel = navigator.mozTelephony;

// Check if the phone is muted (read/write property)
console.log(tel.muted);

// Check if the speaker is enabled (read/write property)
console.log(tel.speakerEnabled);

// Place a call
var call = tel.dial("123456789");

// Events for that call
call.onstatechange = function (event) {
    /*
        Possible values for state:
        "dialing", "ringing", "busy", "connecting", "connected",
        "disconnecting", "disconnected", "incoming"
    */
    console.log(event.state);
};

// Above options as direct events
call.onconnected = function () {
    // Call was connected
};

call.ondisconnected = function () {
    // Call was disconnected
};

// Receiving a call
tel.onincoming = function (event) {
    var incomingCall = event.call;

    // Get the number of the incoming call
    console.log(incomingCall.number);

    // Answer the call
    incomingCall.answer();
};

// Disconnect a call
call.hangUp();

网络短信

用于发送和接收短信。

// SMS object
var sms = navigator.mozSMS;

// Send a message
sms.send("123456789", "Hello world!");

// Receive a message
sms.onreceived = function (event) {
    // Read message
    console.log(event.message);
};

权限

要在开放式 Web 应用程序环境中访问某些 API,您需要在清单文件中为要访问的 API 指定权限。

"permissions": {
    "contacts": {
        "description": "Required for autocompletion in the share screen",
        "access": "readcreate"
    },
    "alarms": {
        "description": "Required to schedule notifications"
    }

}

对于所有被视为特权或认证的 API,都适用此规则。

对于常规 API,只有地理位置和通知会受到影响(对于地理位置,在常规网页浏览器环境中,系统会向用户显示一个对话框,让他们批准/拒绝)。

此外,相机 API 目前作为认证 API 受限,但长期目标是使其对所有应用程序可用。目前,如果您想访问相机,请通过网络活动进行访问。

请查看所有需要权限的 API 列表

平台支持

我相信您知道,许多 WebAPI 都在经历一个充满进展、迭代和改进的过程。上面提到的某些 API 将按预期运行,而其他 API 在目前可能无法运行。

要跟踪当前的实施状态,请查看计划在 Firefox OS 首次发布时使用的 API 列表

三列分别表示:

  • D = Firefox 中的桌面支持
  • A = Firefox 中的 Android 支持
  • B = Firefox OS 支持
  • 绿色 = 已实施并启用
  • 橙色 = 已实施,但需要明确启用
  • 红色 = 未实施
  • 蓝色 = 仅作为认证 API 可用
  • 灰色 = 未计划在该平台上使用

计划在未来使用的 API

虽然目前没有正在开发中,但我还是想列出计划在未来使用的 API。为了向您展示我们的意图以及我们想要实施和支持的事项,以及展示我们前进的方向。

  • 资源锁定 API
  • UDP 数据报套接字 API
  • 点对点 API
  • 网络 NFC
  • 网络 USB
  • HTTP 缓存 API
  • 日历 API
  • 拼写检查 API
  • LogAPI
  • 键盘/输入法 API
  • WebRTC
  • 文件句柄 API
  • 同步 API

测试这些新的 API

您可以随意将本博客文章中的代码复制粘贴到您感兴趣的 API 中进行测试。我还已经在Firefox OS 样板应用程序中实现了对其中一些 API 的支持,这些支持在webapp.js 文件中(我计划在未来添加更多 API)。

关于 Robert Nyman [资深编辑]

Mozilla Hacks 的技术布道者和编辑。为 HTML5、JavaScript 和开放式网络进行演讲和博客撰写。Robert 是 HTML5 和开放式网络的坚定支持者,自 1999 年以来一直从事网页前端开发工作 - 在瑞典和纽约市。他还定期在http://robertnyman.com 上撰写博客,喜欢旅行和结识新朋友。

Robert Nyman [资深编辑] 的更多文章…


16 条评论

  1. Joshua Ols

    所以如果我理解正确的话,我们无法制作自定义拨号器、短信等应用,因为所需的 API 仅供认证应用使用?我理解需要保护这些 API,防止出现秘密拨打付费短信/等的应用。我是否应该假设您已经权衡了风险,并决定恶意利用的可能性过大?

    2013 年 2 月 7 日 下午 09:34

    1. Marcelo

      没错。
      为了避免让任何人进行通话或发送短信的风险,Mozilla 仅允许其自有应用使用这些资源。
      但您可以帮助 Mozilla 增强短信应用或拨号器。它是开源的,任何人都可以提出补丁。

      2013 年 2 月 7 日 下午 10:09

    2. Robert Nyman [编辑]

      感谢您的提问!
      正如 Marcelo 所说,这是这些 API 目前的安全状态。但随着时间的推移,情况可能会发生变化,可能会有其他方法来实现。

      2013 年 2 月 7 日 下午 13:45

  2. Ahmed Nefzaoui

    嗨 Robert :) 抱歉,但……我们在电池状态 API 中是否遗漏了什么?
    chargingTime = parseInt(battery.chargingTime / 60, 10,

    比如
    chargingTime = parseInt(battery.chargingTime / 60, 10),

    也许?:S

    干杯 :)

    2013 年 2 月 7 日 下午 10:29

    1. Robert Nyman [编辑]

      谢谢!看来最后一个括号在某处掉了。:-)

      2013 年 2 月 7 日 下午 13:42

  3. Alber

    好吧,这个新的操作系统看起来很有希望,我迫不及待地想要体验它。

    顺便说一句,这些 API 的工作很棒。

    2013 年 2 月 7 日 下午 22:27

    1. Robert Nyman [编辑]

      谢谢,很高兴您喜欢!

      2013 年 2 月 8 日 上午 01:35

  4. Paul Rouget

    (我认为“打包/特权应用”是错误的)

    2013 年 2 月 8 日 上午 03:34

    1. Robert Nyman [编辑]

      已更新,使其更清晰,并附带更好的链接。

      2013 年 2 月 8 日 上午 03:47

  5. Asdrubal Heredia

    离题 – 我想。

    大家好,我叫 Asdrubal。

    首先,我为我的英语道歉。(我来自哥伦比亚)

    其次,您如何看待这种移动概念?它是“Mozilla Seabird”,它是 Mozilla Labs 于 2009 年提出的概念。

    一张图片。
    http://www.geek.com/wp-content/uploads/2010/09/seabird_2.jpg

    这是视频。
    http://www.youtube.com/watch?v=oG3tLxEQEdg

    这可能是 Firefox OS 的未来吗?您如何看待它?

    2013 年 2 月 9 日 下午 12:17

    1. Robert Nyman [编辑]

      是的,我知道 Mozilla Seabird。:-)
      我认为这是一个有趣的想法,我们拭目以待 Firefox OS 的发展。

      2013 年 2 月 12 日 上午 03:28

  6. markg

    很棒的文章 Robert!这是一个新的 MDN 页面,涵盖了 Open Web App 清单支持的 WebAPI

    https://mdn.org.cn/en-US/docs/Apps/App_permissions

    2013 年 3 月 3 日 下午 22:22

    1. Robert Nyman [编辑]

      太棒了!我会把它编织到这篇文章中。

      2013 年 3 月 4 日 上午 03:46

  7. Batwana

    是否会提供“开发者模式”,以便我们可以为自己的设备制作自己的“认证”应用?

    我理解您不希望来自未知第三方下载的应用访问敏感的设备功能,但我们肯定应该能够按照自己的意愿调整自己的设备。

    2013 年 3 月 13 日 下午 12:14

    1. Robert Nyman [编辑]

      我认为 Hacking Gaia 涵盖了您想要做的事情。

      2013 年 3 月 13 日 下午 17:02

  8. Brock

    Mozilla 公司通过为人们提供许多用户友好且开源的项目而获得了赞誉。Firefox 网页浏览器、Thunderbird 邮件和众多出色的附加组件正在变得越来越流行。现在即将发布的操作系统看起来非常令人兴奋。如果其中包含一个 Web 短信发送接收 (sms envoyer recevoir web) 应用,我会非常高兴。

    2013 年 3 月 13 日 下午 22:11

本文的评论已关闭。