AIR 中的 JavaScript

Flash Player 9 和更高版本,Adobe AIR 1.0 和更高版本

AIR 对通用 JavaScript 对象的典型行为进行了若干更改。其中,很多更改都是为了在 AIR 中更方便地编写安全应用程序。同时,这些行为差异表示某些通用 JavaScript 编码模式和使用这些模式的现有 Web 应用程序在 AIR 中可能始终不会按预期方式执行。有关更正这些问题类型的信息,请参阅 避免与安全相关的 JavaScript 错误

HTML 沙箱

AIR 根据内容的原始位置将该内容放置到隔离沙箱中。沙箱规则与大多数 Web 浏览器实现的具有相同原始位置的策略一致,并且与 Adobe Flash Player 实现的沙箱规则一致。此外,AIR 还提供了一个包含并保护应用程序内容的新 应用程序 沙箱类型。有关在开发 AIR 应用程序时可能遇到的沙箱类型的详细信息,请参阅 安全沙箱

只有在应用程序沙箱中运行的 HTML 和 JavaScript 才能访问运行时环境和 AIR API。但同时,出于安全原因,动态计算和执行各种形式的 JavaScript 在应用程序沙箱内大幅受限。无论您的应用程序实际上是否从服务器直接加载信息,这些限制都将发挥作用。(即使是文件内容、粘贴的字符串和直接用户输入也可能不可靠。)

页内容的原始位置确定要将该内容放置到哪个沙箱。只能将从应用程序目录( app: URL 方案引用的安装目录)加载的内容放置到应用程序沙箱中。从文件系统加载的内容则放置到 与本地文件系统内容交互的 沙箱或 受信任的本地 沙箱中,以便访问本地文件系统上的内容(而不是远程内容),并与其进行交互。从网络加载的内容则放置到与其原始域对应的远程沙箱中。

若要使应用程序页与远程沙箱中的内容自由交互,则可以将该页映射到远程内容所在的相同域中。例如,如果编写显示 Internet 服务的映射数据的应用程序,则可以将加载和显示该服务内容的应用程序页映射到该服务域中。用于将页映射到远程沙箱和域的属性是 frame 和 iframe HTML 元素的新增属性。

若要使非应用程序沙箱中的内容安全地使用 AIR 功能,则可以设置父沙箱桥。若要使应用程序内容安全地调用其他沙箱中的内容的方法并访问其属性,则可以设置子沙箱桥。此处所述的安全性意味着远程内容不能意外获取对未明确公开的对象、属性或方法的引用。通过沙箱桥只能传递简单数据类型、函数和匿名对象。但是,您仍然必须避免明确公开潜在的危险函数。例如,如果公开的接口允许远程内容读取或写入用户系统中任意位置的文件,则可能会使远程内容严重危害用户。

JavaScript eval() 函数

完成加载页之后,将在应用程序沙箱中限制使用 eval() 函数。在某些情况下允许使用该函数,以便可以安全地分析 JSON 格式数据,但是,生成可执行语句的任何计算将生成错误。 对不同沙箱中的内容的代码限制 介绍了允许使用 eval() 函数的情况。

函数构造函数

在应用程序沙箱中,可以在完成加载页之前使用函数构造函数。在所有页 load 事件处理函数完成之后,无法创建新的函数。

加载外部脚本

应用程序沙箱中的 HTML 页无法使用 script 标签从应用程序目录外部加载 JavaScript 文件。为使应用程序中的页能够从应用程序目录外部加载脚本,必须将该页映射到非应用程序沙箱。

XMLHttpRequest 对象

AIR 提供了应用程序可用于执行数据请求的 XMLHttpRequest (XHR) 对象。下面的示例演示简单数据请求:

xmlhttp = new XMLHttpRequest(); 
xmlhttp.open("GET", "http:/www.example.com/file.data", true); 
xmlhttp.onreadystatechange = function() { 
    if (xmlhttp.readyState == 4) { 
        //do something with data... 
    } 
} 
xmlhttp.send(null); 

与浏览器不同,AIR 允许在应用程序沙箱中运行的内容请求任何域中的数据。对于包含 JSON 字符串的 XHR 结果,除非该结果还包含可执行代码,否则可以计算出该结果的数据对象。如果 XHR 结果中存在可执行语句,则会引发错误,且计算尝试失败。

若要防止从远程源意外注入代码,在完成加载页之前执行同步 XHR 时将返回空结果。异步 XHR 将始终在加载页之后返回。

默认情况下,AIR 阻止在非应用程序沙箱中执行跨域 XMLHttpRequest。应用程序沙箱中的父窗口可以选择在包含非应用程序沙箱内容的子 frame 中允许跨域请求,方法是在包含非应用程序沙箱内容的 frame 或 iframe 元素中将 AIR 添加的 allowCrossDomainXHR 属性设置为 true

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    allowCrossDomainXHR="true" 
</iframe>
注: 还可以根据需要使用 AIR URLStream 类下载数据。

如果从包含已映射到远程沙箱的应用程序内容的 frame 或 iframe 对远程服务器调度 XMLHttpRequest,请确保映射 URL 不会遮蔽在 XHR 中使用的服务器地址。例如,请考虑以下 iframe 定义,该定义将应用程序内容映射到 example.com 域所对应的远程沙箱:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/" 
    allowCrossDomainXHR="true" 
</iframe>

由于 sandboxRoot 属性重新映射 www.example.com 地址的根 URL,因此所有请求都将从应用程序目录加载,而不是从远程服务器加载。无论请求是派生自页导航还是 XMLHttpRequest,都将重新映射这些请求。

若要避免意外阻止对远程服务器的数据请求,请将 sandboxRoot 映射到远程 URL 的子目录,而不是根目录。该目录不一定存在。例如,若要允许从远程服务器加载对 www.example.com 的请求,而不是从应用程序目录加载,请将上面的 iframe 更改为以下内容:

<iframe id="mashup" 
    src="http://www.example.com/map.html" 
    documentRoot="app:/sandbox/" 
    sandboxRoot="http://www.example.com/air/" 
    allowCrossDomainXHR="true" 
</iframe>

在本例中,仅在本地加载 air 子目录中的内容。

有关沙箱映射的详细信息,请参阅 HTML frame 和 iframe 元素 以及 Adobe AIR 中的 HTML 安全性

Cookie

在 AIR 应用程序中,只有远程沙箱中的内容(从 http: 和 https: 源加载的内容)才能使用 cookie(即 document.cookie 属性)。在应用程序沙箱中,还提供了存储永久性数据的其他方法,包括 EncryptedLocalStore、SharedObject 和 FileStream 类。

Clipboard 对象

WebKit Clipboard API 由以下事件驱动: copy cut paste 。在这些事件中传递的事件对象通过 clipboardData 属性提供对剪贴板的访问。使用 clipboardData 对象的以下方法可以读取或写入剪贴板数据:

方法

说明

clearData(mimeType)

清除剪贴板数据。将 mimeType 参数设置为要清除的数据的 MIME 类型。

getData(mimeType)

获取剪贴板数据。该方法只能在 paste 事件的处理函数中调用。将 mimeType 参数设置为要返回的数据的 MIME 类型。

setData(mimeType, data)

将数据复制到剪贴板。将 mimeType 参数设置为数据的 MIME 类型。

应用程序沙箱外部的 JavaScript 代码只能通过上述事件访问剪贴板。但是,应用程序沙箱中的内容可以使用 AIR Clipboard 类直接访问系统剪贴板。例如,您可以使用以下语句获取剪贴板上的文本格式数据:

var clipping = air.Clipboard.generalClipboard.getData("text/plain", 
                                air.ClipboardTransferMode.ORIGINAL_ONLY);

有效的数据 MIME 类型为:

MIME 类型

文本

"text/plain"

HTML

"text/html"

URL

"text/uri-list"

位图

"image/x-vnd.adobe.air.bitmap"

文件列表

"application/x-vnd.adobe.air.file-list"

重要说明: 只有应用程序沙箱中的内容才能访问剪贴板上的文件数据。如果非应用程序内容尝试访问剪贴板上的文件对象,则会引发安全错误。

有关使用剪贴板的详细信息,请参阅 复制和粘贴 以及 Using the Pasteboard from JavaScript(Apple 开发人员中心)

拖放

进出 HTML 的拖放手势生成下列 DOM 事件: dragstart drag dragend dragenter dragover dragleave drop 。在这些事件中传递的事件对象通过 dataTransfer 属性提供对被拖动数据的访问。 dataTransfer 属性引用的对象提供与剪贴板事件关联的 clipboardData 对象相同的方法。例如,您可以使用以下函数获取 drop 事件中的文本格式数据:

function onDrop(dragEvent){ 
    return dragEvent.dataTransfer.getData("text/plain",  
            air.ClipboardTransferMode.ORIGINAL_ONLY); 
}

dataTransfer 对象包含下列重要成员:

成员

说明

clearData(mimeType)

清除数据。将 mimeType 参数设置为要清除的数据表示形式的 MIME 类型。

getData(mimeType)

获取拖动的数据。该方法只能在 drop 事件的处理函数中调用。将 mimeType 参数设置为要获取的数据的 MIME 类型。

setData(mimeType, data)

设置要拖动的数据。将 mimeType 参数设置为数据的 MIME 类型。

类型

一个字符串数组,其中包含 dataTransfer 对象中当前可用的所有数据表示形式的 MIME 类型。

effectsAllowed

指定是否可以复制、移动、链接拖动数据,或者是否可以对拖动数据执行任何组合操作。设置 dragstart 事件的处理函数中的 effectsAllowed 属性。

dropEffect

指定拖动目标支持哪些允许的拖动效果。设置 dragEnter 事件的处理函数中的 dropEffect 属性。拖动期间,光标将发生更改,以便指示在用户释放鼠标后将产生的效果。如果未指定任何 dropEffect ,则选择 effectsAllowed 属性效果。复制效果的优先级高于移动效果,而移动效果自身的优先级又高于链接效果。用户可以使用键盘修改默认优先级。

有关向 AIR 应用程序添加拖放支持的详细信息,请参阅 AIR 中的拖放 Using the Drag-and-Drop from JavaScript(Apple 开发人员中心)

innerHTML 和 outerHTML 属性

对于在应用程序沙箱中运行的内容,AIR 会对 innerHTML outerHTML 属性的使用施加一些安全限制。在执行页 load 事件之前以及在执行任何 load 事件处理函数期间, innerHTML outerHTML 属性的使用不受限制。但是,一旦完成页加载,则只能使用 innerHTML outerHTML 属性向文档添加静态内容。分配给 innerHTML outerHTML 的字符串中计算结果为可执行代码的任何语句都将被忽略。例如,如果在元素定义中包含事件回调属性,则不会添加事件侦听器。同样,不会计算嵌入的 <script> 标签。有关详细信息,请参阅 Adobe AIR 中的 HTML 安全性

Document.write() 和 Document.writeln() 方法

在执行页的 load 事件之前,可以在应用程序沙箱中不受限制地使用 write() writeln() 方法。但是,一旦完成页加载,调用上述任一方法将不会清除页或创建新页。在非应用程序沙箱中,在完成页加载之后调用 document.write() writeln() 将清除当前页或打开一个新的空白页,这与在大多数 Web 浏览器中相同。

Document.designMode 属性

document.designMode 属性设置为值 on 可以编辑文档中的所有元素。内置编辑器支持包括文本编辑、复制、粘贴和拖放。将 designMode 设置为 on 等效于将 body 元素的 contentEditable 属性设置为 true 。您可以对大多数 HTML 元素使用 contentEditable 属性,以便定义可以编辑文档的哪些部分。有关其他信息,请参阅 HTML contentEditable 属性

unload 事件(对于 body 和 frameset 对象)

在窗口(包括应用程序主窗口)的顶级 frameset body 标签中,切勿使用 unload 事件响应要关闭的窗口(或应用程序),而应使用 NativeApplication 对象的 exiting 事件检测关闭某一应用程序的时间。或者使用 NativeWindow 对象的 closing 事件检测关闭某一窗口的时间。例如,以下 JavaScript 代码将在用户关闭应用程序时显示 ( "Goodbye." ) 消息:

var app = air.NativeApplication.nativeApplication; 
app.addEventListener(air.Event.EXITING, closeHandler); 
function closeHandler(event) 
{ 
    alert("Goodbye."); 
}

但是,脚本 能够 成功响应因导航 frame、iframe 或顶级窗口内容而引起的 unload 事件。

注: Adobe AIR 的将来版本可能会删除这些限制。

JavaScript Window 对象

Window 对象在 JavaScript 执行上下文中保持为全局对象。在应用程序沙箱中,AIR 向 JavaScript Window 对象添加了新属性,以便提供对 AIR 内置类和重要主机对象的访问。此外,某些方法和属性的行为会有所不同,这取决于它们是否位于应用程序沙箱中。

Window.runtime 属性
通过 runtime 属性,您可以从应用程序沙箱内部实例化和使用内置运行时类。这些类包括 AIR 和 Flash Player API,但不包括 Flex 框架等。例如,以下语句可创建一个 AIR 文件对象:
var preferencesFile = new window.runtime.flash.filesystem.File();

AIR SDK 提供的 AIRAliases.js 文件所包含的别名定义使您可以缩短这些引用。例如,将 AIRAliases.js 导入到页后,可以使用以下语句创建 File 对象:

var preferencesFile = new air.File();

window.runtime 属性仅针对应用程序沙箱中的内容和带有 frame 或 iframe 的父页文档定义。

请参阅 使用 AIRAliases.js 文件

Window.nativeWindow 属性
nativeWindow 属性提供对基础本机 Window 对象的引用。使用该属性,您可以为屏幕位置、大小和可见性等窗口函数和属性撰写脚本,并处理关闭、调整大小和移动等窗口事件。例如,以下语句可关闭窗口:
window.nativeWindow.close();
注: NativeWindow 对象提供的窗口控制功能与 JavaScript Window 对象提供的功能重叠。在这种情况下,您可以根据需要选择其中一种方法。

window.nativeWindow 属性仅针对应用程序沙箱中的内容和带有 frame 或 iframe 的父页文档定义。

Window.htmlLoader 属性
htmlLoader 属性提供对包含 HTML 内容的 AIR HTMLLoader 对象的引用。使用该属性,您可以为 HTML 环境的外观和行为撰写脚本。例如,您可以使用 htmlLoader.paintsDefaultBackground 属性确定该控件是否绘制默认的白色背景:
window.htmlLoader.paintsDefaultBackground = false;
注: HTMLLoader 对象自身具有一个 window 属性,该属性引用该对象包含的 HTML 内容的 JavaScript Window 对象。您可以使用该属性通过对包含 HTMLLoader 的引用来访问 JavaScript 环境。

window.htmlLoader 属性仅针对应用程序沙箱中的内容和带有 frame 或 iframe 的父页文档定义。

Window.parentSandboxBridge 和 Window.childSandboxBridge 属性
使用 parentSandboxBridge childSandboxBridge 属性,您可以定义父帧和子帧之间的接口。有关详细信息,请参阅 跨脚本访问不同安全沙箱中的内容

Window.setTimeout() 和 Window.setInterval() 函数
AIR 对 setTimeout() setInterval() 函数在应用程序沙箱内的使用施加了一些安全限制。当调用 setTimeout() setInterval() 时,您不能定义作为字符串执行的代码。您必须使用函数引用。有关详细信息,请参阅 setTimeout() 和 setInterval()

Window.open() 函数
当在非应用程序沙箱中运行的代码调用 open() 方法时,该方法在调用时仅打开一个窗口,以作为用户交互(例如鼠标单击或按键)的结果。此外,窗口标题采用应用程序标题作为前缀,以免远程内容打开的窗口模拟应用程序打开的窗口。有关详细信息,请参阅 调用 JavaScript window.open() 方法的限制

air.NativeApplication 对象

NativeApplication 对象提供有关应用程序状态的信息,调度若干重要应用程序级别的事件,并提供用于控制应用程序行为的有用函数。将自动创建 NativeApplication 对象的单个实例,并且可通过用户定义的 NativeApplication.nativeApplication 属性访问该实例。

若要通过 JavaScript 代码访问该对象,您可以使用:

var app = window.runtime.flash.desktop.NativeApplication.nativeApplication;

或者,如果已导入 AIRAliases.js 脚本,则可以使用以下简短形式:

var app = air.NativeApplication.nativeApplication;

NativeApplication 对象只能从应用程序沙箱内部访问。有关 NativeApplication 对象的详细信息,请参阅 处理 AIR 运行时和操作系统信息

JavaScript URL 方案

在应用程序沙箱内部阻止执行在 JavaScript URL 方案(如在 href="javascript:alert('Test')" 中)定义的代码。不引发错误。