1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
|
---
title: XPCNativeWrapper
slug: XPCNativeWrapper
---
<p><strong><code>XPCNativeWrapper</code></strong>是一種<a href="/en-US/docs/XPConnect_wrappers">包裝</a>物件讓他可以<a href="/en-US/docs/Safely_accessing_content_DOM_from_chrome">安全的存取特權程式</a>的方法。It can be used in all Firefox versions, though the behavior changed somewhat starting with Firefox 1.5 (Gecko 1.8)。請看<a href="http://kb.mozillazine.org/XPCNativeWrapper"><code>XPCNativeWrapper</code> at the Mozilla knowledgeBase</a>有更多在Firefox 1.5之前的版本的<code>XPCNativeWrapper</code>的行為。這個文件是對Firefox 版本1.5以上的。</p>
<h2 id="XPCNativeWrapper做了什麼?"><code>XPCNativeWrapper</code>做了什麼?</h2>
<p>一個<code>XPCNativeWrapper</code>限制他偽裝之屬性的存取以及物件的方法。惟一經由<code>XPCNativeWrapper</code>存取的屬性與方法是那些定義在IDL中,或是由DOM level 0所定義的(雖然有些DOM level 0的屬性跟方法不能在<code>XPCNativeWrapper</code>中作用)。實務上,經由Javascript所增加的屬性不會被<code>XPCNativeWrapper</code>顯露,and nor are getters and setters defined with <code>__defineGetter__</code> and <code>__defineSetter__</code>。這個目的是要允許對物件的IDL定義方法安全的存取。</p>
<p>請確定閱讀know bugs章節,特別是當寫的程式是針對1.5.0.x的firefox版本。</p>
<h2 id="Types_of_XPCNativeWrapper">Types of <code>XPCNativeWrapper</code></h2>
<p>這裡有三種不同類型的<code>XPCNativeWrapper</code>在Firefox 1.5。三種類型都包裝一個可能不安全(possibly-unsafe)的物件以及提供對他的屬性及方法的安全存取。</p>
<p>三種不同類型的<code>XPCNativeWrapper</code>的行為的差異是由兩個XPCNativeWrpper偽裝器所擁有的特色來決定。一個<code>XPCNativeWrapper</code>可以是明示的Explicit(或是相反的,暗示的Implicit),並且可以是徹底的deep(反之,表面的shallow)。偽裝器創造的類型是由他們被創造的方式所決定,如下:</p>
<table>
<colgroup>
<col>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td>
<p>創造</p>
</td>
<td>
<p>明示/暗示</p>
</td>
<td>
<p>徹底/表面</p>
</td>
</tr>
<tr>
<td>
<p>被保護的script存取未信任的物件</p>
</td>
<td>
<p>暗示</p>
</td>
<td>
<p>徹底</p>
</td>
</tr>
<tr>
<td>
<p>由字串參數呼叫的建構元</p>
</td>
<td>
<p>明示</p>
</td>
<td>
<p>表面</p>
</td>
</tr>
<tr>
<td>
<p>由非字串參數所呼叫的建構元</p>
</td>
<td>
<p>明示</p>
</td>
<td>
<p>徹底</p>
</td>
</tr>
</tbody>
</table>
<p><strong>Explicit vs. Implicit</strong></p>
<p>介於explicit與Implicit的<code>XPCNativeWrapper</code>行為的不同是,由非保護的script對Implicit <code>XPCNativeWrapper</code>屬性的存取是不安全的。屬性的存取將經由<code>XPCNativeWrapper</code>的wrappedJSObject被轉交。</p>
<p>這意味著非保護的script不需要擔心關於bug出現因為其他的code會把他們當作是Implicit來處理。換句話說,這些scripts確實需要注意不安全的物件存取。</p>
<p>對explicit的<code>XPCNativeWrapper</code>的屬性存取不論是否由被保護的呼叫者呼叫,都是安全的。</p>
<p><strong>Deep vs. Shallow</strong></p>
<p>Deep和Shallow的<code>XPCNativeWrapper</code>行為的差異是在於一個deep wrapper的屬性被存取或是函式被呼叫時,傳回值也將會被以他自己的<code>XPCNativeWrapper</code>來包裝。新的<code>XPCNativeWrapper</code>也會是deep並且也會是explicit,若且為若屬性被存取的<code>XPCNativeWrapper</code>是explicit。反之,當被存取的屬性或是函式是用shallow wrapper來呼叫,回傳直也許會是不安全的物件。</p>
<p>舉例來說,我們給3個<code>XPCNativeWrapper</code>的實例給同樣的<code>window</code>物件。讓我們叫他們做deepExplicit<code>window</code>,deepImplicit<code>window</code>和shallow<code>window</code>。那我們有:</p>
<pre>var doc1 = deepExplicitwindow.<code>document</code>; // doc1現在是<code>document</code>物件的一個deep explicit XPCNativeWrapper //存取doc1.open()是安全的 var doc2 = deepImplicitwindow.<code>document</code>; //假如呼叫者有設定.XPCNativeWrappers=yes, 那doc2現在是<code>document</code> object的deep implicit XPCNativeWrapper //否則doc2現在是不安全的<code>document</code> object, 因為屬性存取是簡單的從不安全的window object被傳送 var doc3 = shallowwindow.<code>document</code>; //doc3現在是不安全的<code>document</code> object <strong>創造</strong><strong>XPCNativeWrapper</strong><strong>物件</strong> 有三種創造XPCNativeWrapper的方式;每種方法對應一種類型的XPCNativeWrapper <strong>被保護的</strong><strong>script</strong><strong>存取未信任的物件</strong> 任何時候一個保護的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決定。 預設<strong>所有的</strong><strong>content package</strong><strong>是被保護的</strong>,這意味著所有的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物件。</pre>
<p>因為所有的DOM物件有<code>window</code>物件在他的_parent_串裡面,所以他們是被信任的若且唯若他的<code>window</code>是被信任的。</p>
<p>什麼是被信任的<code>window</code>?</p>
<p>一個<code>window</code>物見是否被信任是依據他的容器。一個<code>window</code>是被信任的假如有以下任何一項:</p>
<p>1.他是頂層<code>window</code>(e.g.<xul:<code>window</code>>, <xul:dialog>, 或是某些用命令列flag -chrome被傳送的URI)</p>
<p>2.他的parent是被信任的,且符合以下三種之一:</p>
<p style="margin-left: 1.25cm;">1.他不是在<xul:iframe>或是<xul:browser>中被讀取</p>
<p style="margin-left: 1.25cm;">2.<xul:iframe>或<xul:browser>沒有用type屬性讀取他</p>
<p style="margin-left: 1.25cm;">3.<xul:iframe>或<xul:browser>讀取他的type屬性執不是'content'且沒有用'content-'開頭</p>
<p>注意一個視窗是否是被信任的<strong>不</strong>依據在<code>window</code>被讀取的URI。所以舉例來說,當在<code>window</code>已經是信任的<code>document</code>內,以下將會件創造信任的視窗</p>
<p><xul:browser></p>
<p><xul:browser type=”chrome”></p>
<p><xul:browser type=”rabid_dog”></p>
<p><xul:iframe type=”foofy”></p>
<p><html:iframe></p>
<p><html:iframe type=”content”></p>
<p>以下不會建立信任的<code>window</code>s:</p>
<p><xul:browser type=”content”></p>
<p><html:iframe type=”content_primary”></p>
<p>進一步注意任何未信任的<code>window</code>的child <code>window</code>自動是未信任的。</p>
<p>當script存取物件時什麼會發生?</p>
<p>下面這個表描述當一個script存取物件時會發生什麼,以及偽裝器是如何的參與。</p>
<table>
<colgroup>
<col>
<col>
<col>
</colgroup>
<tbody>
<tr>
<td>
<p>Script</p>
</td>
<td>
<p>Object</p>
</td>
<td>
<p>Effects</p>
</td>
</tr>
<tr>
<td>
<p>保護的</p>
</td>
<td>
<p>信任的</p>
</td>
<td>
<p>沒有偽裝器被創造,所以script可以完全存取Object</p>
</td>
</tr>
<tr>
<td>
<p>保護的</p>
</td>
<td>
<p>未信任的</p>
</td>
<td>
<p>Implicit deep <code>XPCNativeWrapper</code>被建立</p>
</td>
</tr>
<tr>
<td>
<p>未保護的</p>
</td>
<td>
<p>信任的</p>
</td>
<td>
<p>沒有偽裝器被建立,就像protected/trusted的狀況</p>
</td>
</tr>
<tr>
<td>
<p>未保護的</p>
</td>
<td>
<p>未信任的</p>
</td>
<td>
<p>沒有偽裝器被建立,就像protected/trusted的狀況</p>
</td>
</tr>
</tbody>
</table>
<p><strong>使用<code>XPCNativeWrapper</code></strong><strong>建構元</strong></p>
<p>以上描述,預設在新的Firefox版本<code>XPCNativeWrapper</code>被自動建立。你不需要使用<code>XPCNativeWrapper</code>建構元,除非你打算讓你的code用在舊版本的瀏覽器或者你關閉了<code>XPCNativeWrapper</code>。</p>
<p>用字串參數呼叫<code>XPCNativeWrapper</code>建構元</p>
<p>舉例來說:</p>
<p>var contentWinWrapper = new <code>XPCNativeWrapper</code>(content, '<code>document</code>');</p>
<p>這會創造出一個explicit shallow <code>XPCNativeWrapper</code>。這語法被保留為了Firefox 1.5之前的相容性。當contentWinWrapper所有的屬性可以被安全的存取,這些屬性的回傳值不是安全的去存取(就像在版本小於Firefox 1.5裡),因為<code>XPCNativeWrapper</code>是shallow。所以去比較內容文件標題到現在的內容區段,必須要:</p>
<p>var winWrapper = new <code>XPCNativeWrapper</code>(content, '<code>document</code>', 'getSelection()');</p>
<p>var docWrapper = new <code>XPCNativeWrapper</code>(winWrapper.<code>document</code>, 'title');</p>
<p>return docWrapper.title == winWrapper.getSelection();</p>
<p>沒有字串參數呼叫<code>XPCNativeWrapper</code>建構元</p>
<p>舉例來說:</p>
<p>var contentWinWrapper = new <code>XPCNativeWrapper</code>(content);</p>
<p>這創造了explicit deep <code>XPCNativeWrapper</code>。<code>XPCNativeWrapper</code>存取屬性是安全的,並且回傳值也將會是用explicit deep <code>XPCNativeWrapper</code>包裝的物件。</p>
<p>(譯注: 可參閱http://kb.mozillazine.org/<code>XPCNativeWrapper</code>)</p>
<p><strong><code>XPCNativeWrapper</code>生命週期</strong></p>
<p>Explicit <code>XPCNativeWrapper</code>物件存在當他們被參考到。建立一個新的explicit <code>XPCNativeWrapper</code>給一樣的可能不安全的物件將會建立一個新的偽裝器物件;當設定'expando'參數時,有時要注意。</p>
<p>Implicit <code>XPCNativeWrapper</code>物件跟他包裝的物件有相同的生命週期。</p>
<p><strong>設定<code>XPCNativeWrapper</code></strong><strong>的expando</strong><strong>屬性</strong></p>
<p>為<code>XPCNativeWrapper</code>物件設定expando屬性是可能的。假如這樣做了,那chrome將可以看到他們expando屬性,但內容不行。沒有安全的方式從chrome去設定expando屬性並且讓他從content可讀取。</p>
<p>存取不安全的屬性</p>
<p>假如為了某些理由,不安全的屬性存取是必要的,這可以經由偽裝器的wrappedJSObject屬性去來完成。舉例,假如docWrapper是一個doc的偽裝器,那</p>
<p>docWrapper.wrappedJSObject.prop</p>
<p>等同於</p>
<p>doc.prop</p>
<p>就像這節的名稱,這樣做是<strong>不安全</strong>的。你不因該使用wrappedJSObject去傳遞<code>XPCNativeWrapper</code>在產品的code裡面。</p>
<p>在firefox3,wrappedJSObject回傳另外一個包覆JS Object的偽裝器(XPCSafeJSObjectWrapper),這允許你安全的觀察內容物件。請見XPCSafeJSObjectWrapper。</p>
<p>請見Interaction between privileged and non-priviledged pages有另外更好的。</p>
<p><strong>已知Bugs</strong></p>
<p>在1.5.0.x版本有兩個已知的bug在<code>XPCNativeWrapper</code></p>
<p>1.Firefox versions 1.5 through 1.5.0.4 have <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=337095">bug 337095</a>, 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 <strong>not</strong> be created. Functions that expect to be called in this way need to <a href="/en-US/docs/XPCNativeWrapper#XPCNativeWrapper_constructor_call_with_no_string_arguments">do their own wrapping</a>. This bug is fixed in Firefox 1.5.0.5 and later.</p>
<p>2.Firefox versions 1.5 through 1.5.0.5 have <a class="link-https" href="https://bugzilla.mozilla.org/show_bug.cgi?id=345991">bug 345991</a>, which causes components written in JavaScript to not be protected scripts. This bug is fixed in Firefox 1.5.0.6 and later.</p>
<p><strong><code>XPCNativeWrapper</code>的限制</strong></p>
<p>這裡有一些不能被用在<code>XPCNativeWrapper</code>的一般使用的屬性跟程式風格。</p>
<p>1.對一個DOM node或是<code>window</code>物件的<code>XPCNativeWrapper</code>給予或是讀取一個on*屬性將會丟出Exception。(使用addEventListener取代,並且用event.preventDefault();在你的處理器內假如你之前用了return false;)</p>
<p>2.不能夠在<code>XPCNativeWrapper</code>內用<code>window</code>名稱存取iframe(e.g. <code>window</code>.framename)。</p>
<p>3.<code>document</code>.all 在<code>XPCNativeWrapper</code>內不能用。</p>
<p>4.在<code>XPCNativeWrapper</code>內不行對HTML文件用name存取命名的東西。舉例,假如你有<form name=”foo”>並且docWrapper是一個對HTML文件doc的偽裝器,那當docWrapper為定義時,doc.foo是一個HTMLFormElement。希望這樣做的程式能夠使用docWrapper.forms.namedItem('foo')取代。</p>
<p>5.對HTML文件,在<code>XPCNativeWrapper</code>內用id存取node是不行的。因該用getElementById()取代。</p>
<p>6.對HTML form,在<code>XPCNativeWrapper</code>內用name存取input是不行的。想這樣做的程式必須使用form.elements.namedItem('foo')取代。</p>
<p>7.對HTMLCollection,在<code>XPCNativeWrapper</code>內用name存取元素是步行的。想這樣做的程式碼必須使用namedItem()方法。注意這個namedItem只回傳第一個有name的input元素,即使有很多個有相同名稱的元素(e.g. Radio buttons)。</p>
<p>8.同樣的,對plugin、pluginArray、或是MimeTypeArray,在<code>XPCNativeWrapper</code>內用name存取items是不行的。你必須使用namedItem()取代。</p>
<p>9.不能經由<code>XPCNativeWrapper</code>呼叫由NPAPI plugin實作的方法。</p>
<p>10.不能夠經由<code>XPCNativeWrapper</code>取得(getting)或是設定(setting)由NPAPI plugin實作的屬性。</p>
<p>11.不能夠經由<code>XPCNativeWrapper</code>呼叫經由XBL binding附加到node上的方法。</p>
<p>12.不能夠經由<code>XPCNativeWrapper</code>取得(getting)或是設定(setting)經由XBL binding附加到node上的屬性。</p>
<p>13.經由'for(var p in wrapper)'列舉<code>XPCNativeWrapper</code>的屬性不會列舉IDL定義的屬性。</p>
<p>14.Object.prototype不在<code>XPCNativeWrapper</code>的原型鍊裡面。As a result,變異的Object.prototype被定義在<code>XPCNativeWrapper</code>(更準確一點,這裡有__proto__,__parent__,__count__,toSource,toLocalString,valueOf,watch,unwatch,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,<code>__defineGetter__</code>,<code>__defineSetter__</code>,__lookupGetter__,and__lookupSetter__)。</p>
<p>15.沒有實作舊的<code>XPCNativeWrapper</code>有的importXPCNative,</p>
<p>16.不能經由<code>XPCNativeWrapper</code>存取標準類別(例如Function)。要對特定的<code>window</code>的parent建立function和物件,使用<code>window</code>的eval() function。</p>
<p>17.對'expando'的屬性使用刪除操作元在<code>XPCNativeWrapper</code>會丟出安全性Exceprion。</p>
|