AIR 中的 JavaScript

Flash Player 9 以及更新的版本,Adobe AIR 1.0 以及更新的版本

AIR 針對 JavaScript 常用物件的典型行為做了多項改變。這些改變多數是為了讓您能更輕鬆地使用 AIR 編寫安全的應用程式。然而,行為上的此等差異也意味著某些常用的 JavaScript 程式碼編寫模式未必能如預期般在 AIR 中執行,包括採用這些模式的現有網路應用程式在內。如需如何修正這類問題的詳細資訊,請參閱 避免發生與安全性有關的 JavaScript 錯誤

HTML 安全執行程序

AIR 會根據內容來自於何處,將該內容置入隔離的安全執行程序內。其安全執行程序規則與大多數網頁瀏覽器實作的同源原則以及 Adobe Flash Player 實作安全執行程序的規則相一致。此外,AIR 更提供新的「應用程式」安全執行程序類型,以容納及保護應用程式內容。請參閱 安全執行程序 以取得開發 AIR 應用程式時可能面臨的安全執行程序類型。

只有在應用程式安全執行程序內執行的 HTML 和 JavaScript 能夠存取執行階段環境和 AIR API。不過,基於安全考量,JavaScript 多數形式的動態評估與執行也將侷限於應用程式安全執行程序內。即使應用程式確實直接從伺服器載入資訊,這些限制依然存在 (就算是檔案內容、貼上的字串和使用者直接輸入的文字也未必可信任)。

網頁內容的來源決定了其所處的安全執行程序。唯有從應用程式目錄 (由 app: URL 配置所參考的安裝目錄) 載入的內容會放置於應用程式安全執行程序內。從檔案系統載入的內容會位於「具有檔案系統的本機」或「本機信任」的安全執行程序,其允許對本機檔案系統內容進行存取與互動,但無法對遠端內容進行這些動作。 從網路載入的內容將依其來源網域,放入對應的遠端安全執行程序。

若要讓應用程式頁面能夠任意與遠端安全執行程序中的內容互動,則可將該頁面對應到與遠端內容相同的網域。例如,假設您所編寫的應用程式要顯示網際網路服務提供的地圖資料,就可以將負責載入及顯示服務傳送內容的應用程式頁面對應到該服務網域。將頁面對應到遠端安全執行程序及網域時所用的特質,屬於 HTML frame 和 iframe 元素新增的特質。

為了促使非應用程式安全執行程序中的內容得以安全地使用 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 或 iframe 元素的 allowCrossDomainXHR 特質 (此乃 AIR 所新增) 設定為 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 的子目錄,切勿對應到根目錄。即使該目錄不存在亦無妨。例如,若將上述 iframe 改為如下所示,對 www.example.com 發出要求時便會從遠端伺服器載入,而非從應用程式目錄載入:

<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 。傳入這些事件的 event 物件提供了 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"

重要事項: 只有位於應用程式安全執行程序中的內容能夠存取剪貼簿上的檔案資料。非應用程式的內容若嘗試存取剪貼簿上的檔案物件,便會擲回安全性錯誤。

如需有關使用剪貼簿的詳細資訊,請參閱 複製和貼上 和「 使用 JavaScript 貼上板 (Apple Developer Center) 」。

拖放

若有拖放手勢進出 HTML,便會產生下列 DOM 事件: dragstart drag dragend dragenter dragover dragleave drop 。傳入這些事件的 event 物件提供了 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 類型。

types

字串陣列,內含 dataTransfer 物件中目前所有可用資料形式的 MIME 類型。

effectsAllowed

指定是否允許複製、移動或連結拖曳的資料,包括這三種動作的任意組合。請在 dragstart 事件的處理常式中設定 effectsAllowed 屬性。

dropEffect

指定拖曳目標支援哪些允許的放下效果。請在 dragEnter 事件的處理常式中設定 dropEffect 屬性。在拖曳期間,游標會變更形狀以指出當使用者放開滑鼠時將發生何種效果。若未指定 dropEffect ,將選用其中一種 effectsAllowed 屬性效果。優先順序為:複製效果 > 移動效果 > 連結效果。使用者可以利用鍵盤修改預設的優先順序。

如需有關 AIR 應用程式如何加入拖放支援的詳細資訊,請參閱 在 AIR 中拖放 和「 使用 JavaScript 拖放功能 (Apple Developer Center) 」。

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() ,便會如同大多數網頁瀏覽器般,清空目前頁面或是開啟新的空白頁面。

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."); 
}

不過,Script「仍能」成功回應因瀏覽 frame、iframe 或最上層視窗內容而造成的 unload 事件。

備註: 未來的 Adobe AIR 版本可能會去除這些限制。

JavaScript Window 物件

Window 物件仍是 JavaScript 執行環境中的全域物件。在應用程式安全執行程序中,AIR 為 JavaScript Window 物件增加了一些新屬性,讓您能夠存取 AIR 內建類別以及重要的主控物件。此外,某些方法和屬性會依其是否位於應用程式安全執行程序內而有不同的行為。

Window.runtime 屬性
runtime 屬性讓您能在應用程式安全執行程序內,將內建執行階段類別實體化加以使用。這些類別包含了 AIR 和 Flash Player API (但未提供 Flex 架構等)。例如,下列陳述式會建立 AIR file 物件:
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.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')" ) 將遭封鎖而無法執行,但是不會擲回錯誤。