--- title: XPCNativeWrapper slug: orphaned/XPCNativeWrapper original_slug: XPCNativeWrapper ---

XPCNativeWrapper是一種包裝物件讓他可以安全的存取特權程式的方法。It can be used in all Firefox versions, though the behavior changed somewhat starting with Firefox 1.5 (Gecko 1.8)。請看XPCNativeWrapper at the Mozilla knowledgeBase有更多在Firefox 1.5之前的版本的XPCNativeWrapper的行為。這個文件是對Firefox 版本1.5以上的。

XPCNativeWrapper做了什麼?

一個XPCNativeWrapper限制他偽裝之屬性的存取以及物件的方法。惟一經由XPCNativeWrapper存取的屬性與方法是那些定義在IDL中,或是由DOM level 0所定義的(雖然有些DOM level 0的屬性跟方法不能在XPCNativeWrapper中作用)。實務上,經由Javascript所增加的屬性不會被XPCNativeWrapper顯露,and nor are getters and setters defined with __defineGetter__ and __defineSetter__。這個目的是要允許對物件的IDL定義方法安全的存取。

請確定閱讀know bugs章節,特別是當寫的程式是針對1.5.0.x的firefox版本。

Types of XPCNativeWrapper

這裡有三種不同類型的XPCNativeWrapper在Firefox 1.5。三種類型都包裝一個可能不安全(possibly-unsafe)的物件以及提供對他的屬性及方法的安全存取。

三種不同類型的XPCNativeWrapper的行為的差異是由兩個XPCNativeWrpper偽裝器所擁有的特色來決定。一個XPCNativeWrapper可以是明示的Explicit(或是相反的,暗示的Implicit),並且可以是徹底的deep(反之,表面的shallow)。偽裝器創造的類型是由他們被創造的方式所決定,如下:

創造

明示/暗示

徹底/表面

被保護的script存取未信任的物件

暗示

徹底

由字串參數呼叫的建構元

明示

表面

由非字串參數所呼叫的建構元

明示

徹底

Explicit vs. Implicit

介於explicit與Implicit的XPCNativeWrapper行為的不同是,由非保護的script對Implicit XPCNativeWrapper屬性的存取是不安全的。屬性的存取將經由XPCNativeWrapper的wrappedJSObject被轉交。

這意味著非保護的script不需要擔心關於bug出現因為其他的code會把他們當作是Implicit來處理。換句話說,這些scripts確實需要注意不安全的物件存取。

對explicit的XPCNativeWrapper的屬性存取不論是否由被保護的呼叫者呼叫,都是安全的。

Deep vs. Shallow

Deep和Shallow的XPCNativeWrapper行為的差異是在於一個deep wrapper的屬性被存取或是函式被呼叫時,傳回值也將會被以他自己的XPCNativeWrapper來包裝。新的XPCNativeWrapper也會是deep並且也會是explicit,若且為若屬性被存取的XPCNativeWrapper是explicit。反之,當被存取的屬性或是函式是用shallow wrapper來呼叫,回傳直也許會是不安全的物件。

舉例來說,我們給3個XPCNativeWrapper的實例給同樣的window物件。讓我們叫他們做deepExplicitwindow,deepImplicitwindow和shallowwindow。那我們有:

var doc1 = deepExplicitwindow.document; // doc1現在是document物件的一個deep explicit XPCNativeWrapper //存取doc1.open()是安全的  var doc2 = deepImplicitwindow.document; //假如呼叫者有設定.XPCNativeWrappers=yes, 那doc2現在是document object的deep implicit XPCNativeWrapper //否則doc2現在是不安全的document object, 因為屬性存取是簡單的從不安全的window object被傳送  var doc3 = shallowwindow.document; //doc3現在是不安全的document object  創造XPCNativeWrapper物件 有三種創造XPCNativeWrapper的方式;每種方法對應一種類型的XPCNativeWrapper  被保護的script存取未信任的物件 任何時候一個保護的script存取存取一個未信任的物件將會得到一個implicit deep XPCNativeWrapper。從被保護的script存取這個XPCNativeWrapper的屬性是安全的。  一但物件被包裝,一個用這種方式建立的包裝將會逗留(stick around),另外在一行內存取物件兩次也會拿到相同的XPCNativeWrapper  什麼是被保護的script? 在firefox版本1.5到1.5.0.5, 一個script是被保護的或是不被保護是單獨基於他的URI。一個script是被保護的只有當他的URI由已知被保護的前綴開頭;不是由UR被讀取的script(e.g. 由javascript實作的元件)不是被保護的。在Firefox 1.5內被保護的前綴由Chrome Registry決定。  預設所有的content package是被保護的,這意味著所有的URI開頭是"chrome:// <package name>/content/"(對任何package)是被保護的。單獨的package用flag覆寫在他們的chrome manifest檔案。  從firefox 1.5.0.6開始,Javascript實作的元件是被保護的script。所以一個script不論是由被URI開頭是保護的前綴所讀取或者是Javascript實作的元件都是被保護的。  什麼是未信任的物件? 所有的物件都是信任或是未信任的。一個物件是被信任的假如有以下任何一項: 1.他的parent(Javascript中的_parent_屬性)是一個信任的物件。 2.他是Javascript元件的根範圍(root scope)物件。 3.他是信任的視窗的window物件。

因為所有的DOM物件有window物件在他的_parent_串裡面,所以他們是被信任的若且唯若他的window是被信任的。

什麼是被信任的window?

一個window物見是否被信任是依據他的容器。一個window是被信任的假如有以下任何一項:

1.他是頂層window(e.g.<xul:window>, <xul:dialog>, 或是某些用命令列flag -chrome被傳送的URI)

2.他的parent是被信任的,且符合以下三種之一:

1.他不是在<xul:iframe>或是<xul:browser>中被讀取

2.<xul:iframe>或<xul:browser>沒有用type屬性讀取他

3.<xul:iframe>或<xul:browser>讀取他的type屬性執不是'content'且沒有用'content-'開頭

注意一個視窗是否是被信任的依據在window被讀取的URI。所以舉例來說,當在window已經是信任的document內,以下將會件創造信任的視窗

<xul:browser>

<xul:browser type=”chrome”>

<xul:browser type=”rabid_dog”>

<xul:iframe type=”foofy”>

<html:iframe>

<html:iframe type=”content”>

以下不會建立信任的windows:

<xul:browser type=”content”>

<html:iframe type=”content_primary”>

進一步注意任何未信任的window的child window自動是未信任的。

當script存取物件時什麼會發生?

下面這個表描述當一個script存取物件時會發生什麼,以及偽裝器是如何的參與。

Script

Object

Effects

保護的

信任的

沒有偽裝器被創造,所以script可以完全存取Object

保護的

未信任的

Implicit deep XPCNativeWrapper被建立

未保護的

信任的

沒有偽裝器被建立,就像protected/trusted的狀況

未保護的

未信任的

沒有偽裝器被建立,就像protected/trusted的狀況

使用XPCNativeWrapper建構元

以上描述,預設在新的Firefox版本XPCNativeWrapper被自動建立。你不需要使用XPCNativeWrapper建構元,除非你打算讓你的code用在舊版本的瀏覽器或者你關閉了XPCNativeWrapper

用字串參數呼叫XPCNativeWrapper建構元

舉例來說:

var contentWinWrapper = new XPCNativeWrapper(content, 'document');

這會創造出一個explicit shallow XPCNativeWrapper。這語法被保留為了Firefox 1.5之前的相容性。當contentWinWrapper所有的屬性可以被安全的存取,這些屬性的回傳值不是安全的去存取(就像在版本小於Firefox 1.5裡),因為XPCNativeWrapper是shallow。所以去比較內容文件標題到現在的內容區段,必須要:

var winWrapper = new XPCNativeWrapper(content, 'document', 'getSelection()');

var docWrapper = new XPCNativeWrapper(winWrapper.document, 'title');

return docWrapper.title == winWrapper.getSelection();

沒有字串參數呼叫XPCNativeWrapper建構元

舉例來說:

var contentWinWrapper = new XPCNativeWrapper(content);

這創造了explicit deep XPCNativeWrapperXPCNativeWrapper存取屬性是安全的,並且回傳值也將會是用explicit deep XPCNativeWrapper包裝的物件。

(譯注: 可參閱http://kb.mozillazine.org/XPCNativeWrapper)

XPCNativeWrapper生命週期

Explicit XPCNativeWrapper物件存在當他們被參考到。建立一個新的explicit XPCNativeWrapper給一樣的可能不安全的物件將會建立一個新的偽裝器物件;當設定'expando'參數時,有時要注意。

Implicit XPCNativeWrapper物件跟他包裝的物件有相同的生命週期。

設定XPCNativeWrapper的expando屬性

XPCNativeWrapper物件設定expando屬性是可能的。假如這樣做了,那chrome將可以看到他們expando屬性,但內容不行。沒有安全的方式從chrome去設定expando屬性並且讓他從content可讀取。

存取不安全的屬性

假如為了某些理由,不安全的屬性存取是必要的,這可以經由偽裝器的wrappedJSObject屬性去來完成。舉例,假如docWrapper是一個doc的偽裝器,那

docWrapper.wrappedJSObject.prop

等同於

doc.prop

就像這節的名稱,這樣做是不安全的。你不因該使用wrappedJSObject去傳遞XPCNativeWrapper在產品的code裡面。

在firefox3,wrappedJSObject回傳另外一個包覆JS Object的偽裝器(XPCSafeJSObjectWrapper),這允許你安全的觀察內容物件。請見XPCSafeJSObjectWrapper。

請見Interaction between privileged and non-priviledged pages有另外更好的。

已知Bugs

在1.5.0.x版本有兩個已知的bug在XPCNativeWrapper

1.Firefox versions 1.5 through 1.5.0.4 have bug 337095, which causes wrappers to not be created for protected scripts in some cases. Specifically, if a protected script makes a property access or function call that returns an untrusted object, a wrapper will be created. However, if a function in a protected script is called from C++ and an untrusted object is passed as an argument to this function, a wrapper will not be created. Functions that expect to be called in this way need to do their own wrapping. This bug is fixed in Firefox 1.5.0.5 and later.

2.Firefox versions 1.5 through 1.5.0.5 have bug 345991, which causes components written in JavaScript to not be protected scripts. This bug is fixed in Firefox 1.5.0.6 and later.

XPCNativeWrapper的限制

這裡有一些不能被用在XPCNativeWrapper的一般使用的屬性跟程式風格。

1.對一個DOM node或是window物件的XPCNativeWrapper給予或是讀取一個on*屬性將會丟出Exception。(使用addEventListener取代,並且用event.preventDefault();在你的處理器內假如你之前用了return false;)

2.不能夠在XPCNativeWrapper內用window名稱存取iframe(e.g. window.framename)。

3.document.all 在XPCNativeWrapper內不能用。

4.在XPCNativeWrapper內不行對HTML文件用name存取命名的東西。舉例,假如你有<form name=”foo”>並且docWrapper是一個對HTML文件doc的偽裝器,那當docWrapper為定義時,doc.foo是一個HTMLFormElement。希望這樣做的程式能夠使用docWrapper.forms.namedItem('foo')取代。

5.對HTML文件,在XPCNativeWrapper內用id存取node是不行的。因該用getElementById()取代。

6.對HTML form,在XPCNativeWrapper內用name存取input是不行的。想這樣做的程式必須使用form.elements.namedItem('foo')取代。

7.對HTMLCollection,在XPCNativeWrapper內用name存取元素是步行的。想這樣做的程式碼必須使用namedItem()方法。注意這個namedItem只回傳第一個有name的input元素,即使有很多個有相同名稱的元素(e.g. Radio buttons)。

8.同樣的,對plugin、pluginArray、或是MimeTypeArray,在XPCNativeWrapper內用name存取items是不行的。你必須使用namedItem()取代。

9.不能經由XPCNativeWrapper呼叫由NPAPI plugin實作的方法。

10.不能夠經由XPCNativeWrapper取得(getting)或是設定(setting)由NPAPI plugin實作的屬性。

11.不能夠經由XPCNativeWrapper呼叫經由XBL binding附加到node上的方法。

12.不能夠經由XPCNativeWrapper取得(getting)或是設定(setting)經由XBL binding附加到node上的屬性。

13.經由'for(var p in wrapper)'列舉XPCNativeWrapper的屬性不會列舉IDL定義的屬性。

14.Object.prototype不在XPCNativeWrapper的原型鍊裡面。As a result,變異的Object.prototype被定義在XPCNativeWrapper(更準確一點,這裡有__proto__,__parent__,__count__,toSource,toLocalString,valueOf,watch,unwatch,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,__defineGetter____defineSetter__,__lookupGetter__,and__lookupSetter__)。

15.沒有實作舊的XPCNativeWrapper有的importXPCNative,

16.不能經由XPCNativeWrapper存取標準類別(例如Function)。要對特定的window的parent建立function和物件,使用window的eval() function。

17.對'expando'的屬性使用刪除操作元在XPCNativeWrapper會丟出安全性Exceprion。