|
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* vim: set ts=2 sw=2 et tw=78: */ |
|
3 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
4 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
6 |
|
7 #include "mozilla/ArrayUtils.h" |
|
8 // On top because they include basictypes.h: |
|
9 #include "mozilla/dom/SmsFilter.h" |
|
10 |
|
11 #ifdef XP_WIN |
|
12 #undef GetClassName |
|
13 #endif |
|
14 |
|
15 // JavaScript includes |
|
16 #include "jsapi.h" |
|
17 #include "jsfriendapi.h" |
|
18 #include "WrapperFactory.h" |
|
19 #include "AccessCheck.h" |
|
20 #include "XrayWrapper.h" |
|
21 |
|
22 #include "xpcpublic.h" |
|
23 #include "xpcprivate.h" |
|
24 #include "XPCWrapper.h" |
|
25 |
|
26 #include "mozilla/DOMEventTargetHelper.h" |
|
27 #include "mozilla/dom/RegisterBindings.h" |
|
28 |
|
29 #include "nscore.h" |
|
30 #include "nsDOMClassInfo.h" |
|
31 #include "nsCRT.h" |
|
32 #include "nsCRTGlue.h" |
|
33 #include "nsICategoryManager.h" |
|
34 #include "nsIComponentRegistrar.h" |
|
35 #include "nsXPCOM.h" |
|
36 #include "nsISupportsPrimitives.h" |
|
37 #include "nsIXPConnect.h" |
|
38 #include "nsIXPCSecurityManager.h" |
|
39 #include "xptcall.h" |
|
40 #include "nsTArray.h" |
|
41 #include "nsDocument.h" // nsDOMStyleSheetList |
|
42 #include "nsDOMBlobBuilder.h" |
|
43 |
|
44 // General helper includes |
|
45 #include "nsGlobalWindow.h" |
|
46 #include "nsIContent.h" |
|
47 #include "nsIDocument.h" |
|
48 #include "nsIDOMDocument.h" |
|
49 #include "nsIDOMEvent.h" |
|
50 #include "nsIDOMEventListener.h" |
|
51 #include "nsContentUtils.h" |
|
52 #include "nsCxPusher.h" |
|
53 #include "nsIDOMWindowUtils.h" |
|
54 #include "nsIDOMGlobalPropertyInitializer.h" |
|
55 #include "nsLocation.h" |
|
56 #include "mozilla/Attributes.h" |
|
57 #include "mozilla/Telemetry.h" |
|
58 |
|
59 // Window scriptable helper includes |
|
60 #include "nsIDocShell.h" |
|
61 #include "nsIScriptExternalNameSet.h" |
|
62 #include "nsJSUtils.h" |
|
63 #include "nsScriptNameSpaceManager.h" |
|
64 #include "nsIJSNativeInitializer.h" |
|
65 #include "nsJSEnvironment.h" |
|
66 |
|
67 // DOM base includes |
|
68 #include "nsIDOMLocation.h" |
|
69 #include "nsIDOMWindow.h" |
|
70 #include "nsPIDOMWindow.h" |
|
71 #include "nsIDOMJSWindow.h" |
|
72 #include "nsIDOMChromeWindow.h" |
|
73 #include "nsIDOMConstructor.h" |
|
74 |
|
75 // DOM core includes |
|
76 #include "nsError.h" |
|
77 #include "nsIDOMUserDataHandler.h" |
|
78 #include "nsIDOMXULButtonElement.h" |
|
79 #include "nsIDOMXULCheckboxElement.h" |
|
80 #include "nsIDOMXULPopupElement.h" |
|
81 |
|
82 // Event related includes |
|
83 #include "nsIDOMEventTarget.h" |
|
84 |
|
85 // CSS related includes |
|
86 #include "nsCSSRules.h" |
|
87 #include "nsIDOMCSSRule.h" |
|
88 #include "nsICSSRuleList.h" |
|
89 #include "nsAutoPtr.h" |
|
90 #include "nsMemory.h" |
|
91 |
|
92 // Tranformiix |
|
93 #include "nsIXSLTProcessor.h" |
|
94 #include "nsIXSLTProcessorPrivate.h" |
|
95 |
|
96 // includes needed for the prototype chain interfaces |
|
97 #include "nsIDOMCSSCharsetRule.h" |
|
98 #include "nsIDOMCSSImportRule.h" |
|
99 #include "nsIDOMCSSMediaRule.h" |
|
100 #include "nsIDOMCSSFontFaceRule.h" |
|
101 #include "nsIDOMCSSMozDocumentRule.h" |
|
102 #include "nsIDOMCSSSupportsRule.h" |
|
103 #include "nsIDOMMozCSSKeyframeRule.h" |
|
104 #include "nsIDOMMozCSSKeyframesRule.h" |
|
105 #include "nsIDOMCSSPageRule.h" |
|
106 #include "nsIDOMCSSStyleRule.h" |
|
107 #include "nsIDOMCSSStyleSheet.h" |
|
108 #include "nsIDOMXULCommandDispatcher.h" |
|
109 #include "nsIControllers.h" |
|
110 #include "nsIBoxObject.h" |
|
111 #ifdef MOZ_XUL |
|
112 #include "nsITreeSelection.h" |
|
113 #include "nsITreeContentView.h" |
|
114 #include "nsITreeView.h" |
|
115 #include "nsIXULTemplateBuilder.h" |
|
116 #include "nsITreeColumns.h" |
|
117 #endif |
|
118 #include "nsIDOMXPathExpression.h" |
|
119 #include "nsIDOMNSXPathExpression.h" |
|
120 #include "nsIDOMXPathNSResolver.h" |
|
121 #include "nsIDOMXPathResult.h" |
|
122 |
|
123 #include "nsIDOMSVGNumber.h" |
|
124 |
|
125 // Storage includes |
|
126 #include "nsIDOMStorage.h" |
|
127 #include "nsPIDOMStorage.h" |
|
128 |
|
129 // Drag and drop |
|
130 #include "nsIDOMFile.h" |
|
131 #include "nsDOMBlobBuilder.h" // nsDOMMultipartFile |
|
132 |
|
133 #include "nsIEventListenerService.h" |
|
134 #include "nsIMessageManager.h" |
|
135 |
|
136 #include "mozilla/dom/TouchEvent.h" |
|
137 |
|
138 #include "nsWrapperCacheInlines.h" |
|
139 #include "mozilla/dom/HTMLCollectionBinding.h" |
|
140 |
|
141 #include "nsIDOMMobileMessageManager.h" |
|
142 #include "nsIDOMMozSmsMessage.h" |
|
143 #include "nsIDOMMozMmsMessage.h" |
|
144 #include "nsIDOMSmsFilter.h" |
|
145 #include "nsIDOMSmsSegmentInfo.h" |
|
146 #include "nsIDOMMozMobileMessageThread.h" |
|
147 |
|
148 #ifdef MOZ_B2G_RIL |
|
149 #include "nsIDOMMobileConnection.h" |
|
150 #endif // MOZ_B2G_RIL |
|
151 |
|
152 #ifdef MOZ_B2G_FM |
|
153 #include "FMRadio.h" |
|
154 #endif |
|
155 |
|
156 #include "nsIDOMGlobalObjectConstructor.h" |
|
157 #include "nsDebug.h" |
|
158 |
|
159 #include "mozilla/dom/BindingUtils.h" |
|
160 #include "mozilla/Likely.h" |
|
161 #include "WindowNamedPropertiesHandler.h" |
|
162 #include "nsIInterfaceInfoManager.h" |
|
163 #include "mozilla/dom/EventTargetBinding.h" |
|
164 #include "mozilla/dom/WindowBinding.h" |
|
165 |
|
166 #ifdef MOZ_TIME_MANAGER |
|
167 #include "TimeManager.h" |
|
168 #endif |
|
169 |
|
170 using namespace mozilla; |
|
171 using namespace mozilla::dom; |
|
172 |
|
173 static NS_DEFINE_CID(kDOMSOF_CID, NS_DOM_SCRIPT_OBJECT_FACTORY_CID); |
|
174 |
|
175 // NOTE: DEFAULT_SCRIPTABLE_FLAGS and DOM_DEFAULT_SCRIPTABLE_FLAGS |
|
176 // are defined in nsIDOMClassInfo.h. |
|
177 |
|
178 #define WINDOW_SCRIPTABLE_FLAGS \ |
|
179 (nsIXPCScriptable::WANT_PRECREATE | \ |
|
180 nsIXPCScriptable::WANT_POSTCREATE | \ |
|
181 nsIXPCScriptable::WANT_ENUMERATE | \ |
|
182 nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE | \ |
|
183 nsIXPCScriptable::IS_GLOBAL_OBJECT | \ |
|
184 nsIXPCScriptable::WANT_OUTER_OBJECT) |
|
185 |
|
186 #define ARRAY_SCRIPTABLE_FLAGS \ |
|
187 (DOM_DEFAULT_SCRIPTABLE_FLAGS | \ |
|
188 nsIXPCScriptable::WANT_GETPROPERTY | \ |
|
189 nsIXPCScriptable::WANT_ENUMERATE) |
|
190 |
|
191 #define EVENTTARGET_SCRIPTABLE_FLAGS \ |
|
192 (DOM_DEFAULT_SCRIPTABLE_FLAGS | \ |
|
193 nsIXPCScriptable::WANT_ADDPROPERTY) |
|
194 |
|
195 #define DOMCLASSINFO_STANDARD_FLAGS \ |
|
196 (nsIClassInfo::MAIN_THREAD_ONLY | \ |
|
197 nsIClassInfo::DOM_OBJECT | \ |
|
198 nsIClassInfo::SINGLETON_CLASSINFO) |
|
199 |
|
200 |
|
201 #ifdef DEBUG |
|
202 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \ |
|
203 eDOMClassInfo_##_class##_id, |
|
204 #else |
|
205 #define NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \ |
|
206 // nothing |
|
207 #endif |
|
208 |
|
209 /** |
|
210 * To generate the bitmap for a class that we're sure doesn't implement any of |
|
211 * the interfaces in DOMCI_CASTABLE_INTERFACES. |
|
212 */ |
|
213 #define DOMCI_DATA_NO_CLASS(_dom_class) \ |
|
214 const uint32_t kDOMClassInfo_##_dom_class##_interfaces = \ |
|
215 0; |
|
216 |
|
217 DOMCI_DATA_NO_CLASS(ContentFrameMessageManager) |
|
218 DOMCI_DATA_NO_CLASS(ChromeMessageBroadcaster) |
|
219 DOMCI_DATA_NO_CLASS(ChromeMessageSender) |
|
220 |
|
221 DOMCI_DATA_NO_CLASS(DOMPrototype) |
|
222 DOMCI_DATA_NO_CLASS(DOMConstructor) |
|
223 |
|
224 DOMCI_DATA_NO_CLASS(UserDataHandler) |
|
225 DOMCI_DATA_NO_CLASS(XULControlElement) |
|
226 DOMCI_DATA_NO_CLASS(XULLabeledControlElement) |
|
227 DOMCI_DATA_NO_CLASS(XULButtonElement) |
|
228 DOMCI_DATA_NO_CLASS(XULCheckboxElement) |
|
229 DOMCI_DATA_NO_CLASS(XULPopupElement) |
|
230 |
|
231 #define NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, \ |
|
232 _chromeOnly, _allowXBL) \ |
|
233 { #_class, \ |
|
234 nullptr, \ |
|
235 { _helper::doCreate }, \ |
|
236 nullptr, \ |
|
237 nullptr, \ |
|
238 nullptr, \ |
|
239 _flags, \ |
|
240 true, \ |
|
241 0, \ |
|
242 _chromeOnly, \ |
|
243 _allowXBL, \ |
|
244 false, \ |
|
245 NS_DEFINE_CLASSINFO_DATA_DEBUG(_class) \ |
|
246 }, |
|
247 |
|
248 #define NS_DEFINE_CLASSINFO_DATA(_class, _helper, _flags) \ |
|
249 NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, false, false) |
|
250 |
|
251 #define NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(_class, _helper, _flags) \ |
|
252 NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, false) |
|
253 |
|
254 #define NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(_class, _helper, _flags) \ |
|
255 NS_DEFINE_CLASSINFO_DATA_HELPER(_class, _helper, _flags, true, true) |
|
256 |
|
257 |
|
258 // This list of NS_DEFINE_CLASSINFO_DATA macros is what gives the DOM |
|
259 // classes their correct behavior when used through XPConnect. The |
|
260 // arguments that are passed to NS_DEFINE_CLASSINFO_DATA are |
|
261 // |
|
262 // 1. Class name as it should appear in JavaScript, this name is also |
|
263 // used to find the id of the class in nsDOMClassInfo |
|
264 // (i.e. e<classname>_id) |
|
265 // 2. Scriptable helper class |
|
266 // 3. nsIClassInfo/nsIXPCScriptable flags (i.e. for GetScriptableFlags) |
|
267 |
|
268 static nsDOMClassInfoData sClassInfoData[] = { |
|
269 // Base classes |
|
270 |
|
271 // The Window class lets you QI into interfaces that are not in the |
|
272 // flattened set (i.e. nsIXPCScriptable::CLASSINFO_INTERFACES_ONLY |
|
273 // is not set), because of this make sure all scriptable interfaces |
|
274 // that are implemented by nsGlobalWindow can securely be exposed |
|
275 // to JS. |
|
276 |
|
277 |
|
278 NS_DEFINE_CLASSINFO_DATA(Window, nsWindowSH, |
|
279 DEFAULT_SCRIPTABLE_FLAGS | |
|
280 WINDOW_SCRIPTABLE_FLAGS) |
|
281 |
|
282 NS_DEFINE_CLASSINFO_DATA(Location, nsLocationSH, |
|
283 ((DOM_DEFAULT_SCRIPTABLE_FLAGS | |
|
284 nsIXPCScriptable::WANT_ADDPROPERTY) & |
|
285 ~nsIXPCScriptable::ALLOW_PROP_MODS_TO_PROTOTYPE)) |
|
286 |
|
287 NS_DEFINE_CLASSINFO_DATA(DOMPrototype, nsDOMConstructorSH, |
|
288 DOM_BASE_SCRIPTABLE_FLAGS | |
|
289 nsIXPCScriptable::WANT_PRECREATE | |
|
290 nsIXPCScriptable::WANT_NEWRESOLVE | |
|
291 nsIXPCScriptable::WANT_HASINSTANCE | |
|
292 nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE) |
|
293 NS_DEFINE_CLASSINFO_DATA(DOMConstructor, nsDOMConstructorSH, |
|
294 DOM_BASE_SCRIPTABLE_FLAGS | |
|
295 nsIXPCScriptable::WANT_PRECREATE | |
|
296 nsIXPCScriptable::WANT_NEWRESOLVE | |
|
297 nsIXPCScriptable::WANT_HASINSTANCE | |
|
298 nsIXPCScriptable::WANT_CALL | |
|
299 nsIXPCScriptable::WANT_CONSTRUCT | |
|
300 nsIXPCScriptable::DONT_ENUM_QUERY_INTERFACE) |
|
301 |
|
302 // Misc Core related classes |
|
303 |
|
304 // CSS classes |
|
305 NS_DEFINE_CLASSINFO_DATA(CSSStyleRule, nsDOMGenericSH, |
|
306 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
307 NS_DEFINE_CLASSINFO_DATA(CSSCharsetRule, nsDOMGenericSH, |
|
308 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
309 NS_DEFINE_CLASSINFO_DATA(CSSImportRule, nsDOMGenericSH, |
|
310 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
311 NS_DEFINE_CLASSINFO_DATA(CSSMediaRule, nsDOMGenericSH, |
|
312 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
313 NS_DEFINE_CLASSINFO_DATA(CSSNameSpaceRule, nsDOMGenericSH, |
|
314 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
315 NS_DEFINE_CLASSINFO_DATA(CSSRuleList, nsCSSRuleListSH, |
|
316 ARRAY_SCRIPTABLE_FLAGS) |
|
317 NS_DEFINE_CLASSINFO_DATA(CSSStyleSheet, nsDOMGenericSH, |
|
318 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
319 |
|
320 // XUL classes |
|
321 #ifdef MOZ_XUL |
|
322 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCommandDispatcher, nsDOMGenericSH, |
|
323 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
324 #endif |
|
325 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControllers, nsNonDOMObjectSH, |
|
326 DEFAULT_SCRIPTABLE_FLAGS) |
|
327 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(BoxObject, nsDOMGenericSH, |
|
328 DEFAULT_SCRIPTABLE_FLAGS) |
|
329 #ifdef MOZ_XUL |
|
330 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeSelection, nsDOMGenericSH, |
|
331 DEFAULT_SCRIPTABLE_FLAGS) |
|
332 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeContentView, nsDOMGenericSH, |
|
333 DEFAULT_SCRIPTABLE_FLAGS) |
|
334 #endif |
|
335 |
|
336 // DOM Chrome Window class. |
|
337 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(ChromeWindow, nsWindowSH, |
|
338 DEFAULT_SCRIPTABLE_FLAGS | |
|
339 WINDOW_SCRIPTABLE_FLAGS) |
|
340 |
|
341 #ifdef MOZ_XUL |
|
342 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTemplateBuilder, nsDOMGenericSH, |
|
343 DEFAULT_SCRIPTABLE_FLAGS) |
|
344 |
|
345 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULTreeBuilder, nsDOMGenericSH, |
|
346 DEFAULT_SCRIPTABLE_FLAGS) |
|
347 #endif |
|
348 |
|
349 #ifdef MOZ_XUL |
|
350 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(TreeColumn, nsDOMGenericSH, |
|
351 DEFAULT_SCRIPTABLE_FLAGS) |
|
352 #endif |
|
353 |
|
354 NS_DEFINE_CLASSINFO_DATA(CSSMozDocumentRule, nsDOMGenericSH, |
|
355 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
356 |
|
357 NS_DEFINE_CLASSINFO_DATA(CSSSupportsRule, nsDOMGenericSH, |
|
358 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
359 |
|
360 // other SVG classes |
|
361 NS_DEFINE_CLASSINFO_DATA(SVGNumber, nsDOMGenericSH, |
|
362 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
363 |
|
364 NS_DEFINE_CLASSINFO_DATA(WindowUtils, nsDOMGenericSH, |
|
365 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
366 |
|
367 NS_DEFINE_CLASSINFO_DATA(XSLTProcessor, nsDOMGenericSH, |
|
368 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
369 |
|
370 NS_DEFINE_CLASSINFO_DATA(XPathExpression, nsDOMGenericSH, |
|
371 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
372 NS_DEFINE_CLASSINFO_DATA(XPathNSResolver, nsDOMGenericSH, |
|
373 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
374 NS_DEFINE_CLASSINFO_DATA(XPathResult, nsDOMGenericSH, |
|
375 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
376 |
|
377 // WhatWG Storage |
|
378 |
|
379 // mrbkap says we don't need WANT_ADDPROPERTY on Storage objects |
|
380 // since a call to addProperty() is always followed by a call to |
|
381 // setProperty(), except in the case when a getter or setter is set |
|
382 // for a property. But we don't care about getters or setters here. |
|
383 NS_DEFINE_CLASSINFO_DATA(Storage, nsStorage2SH, |
|
384 DOM_DEFAULT_SCRIPTABLE_FLAGS | |
|
385 nsIXPCScriptable::WANT_NEWRESOLVE | |
|
386 nsIXPCScriptable::WANT_GETPROPERTY | |
|
387 nsIXPCScriptable::WANT_SETPROPERTY | |
|
388 nsIXPCScriptable::WANT_DELPROPERTY | |
|
389 nsIXPCScriptable::DONT_ENUM_STATIC_PROPS | |
|
390 nsIXPCScriptable::WANT_NEWENUMERATE) |
|
391 |
|
392 NS_DEFINE_CLASSINFO_DATA(Blob, nsDOMGenericSH, |
|
393 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
394 NS_DEFINE_CLASSINFO_DATA(File, nsDOMGenericSH, |
|
395 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
396 |
|
397 NS_DEFINE_CLASSINFO_DATA(ModalContentWindow, nsWindowSH, |
|
398 DEFAULT_SCRIPTABLE_FLAGS | |
|
399 WINDOW_SCRIPTABLE_FLAGS) |
|
400 |
|
401 NS_DEFINE_CLASSINFO_DATA(MozMobileMessageManager, nsDOMGenericSH, |
|
402 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
403 |
|
404 NS_DEFINE_CLASSINFO_DATA(MozSmsMessage, nsDOMGenericSH, |
|
405 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
406 |
|
407 NS_DEFINE_CLASSINFO_DATA(MozMmsMessage, nsDOMGenericSH, |
|
408 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
409 |
|
410 NS_DEFINE_CLASSINFO_DATA(MozSmsFilter, nsDOMGenericSH, |
|
411 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
412 |
|
413 NS_DEFINE_CLASSINFO_DATA(MozSmsSegmentInfo, nsDOMGenericSH, |
|
414 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
415 |
|
416 NS_DEFINE_CLASSINFO_DATA(MozMobileMessageThread, nsDOMGenericSH, |
|
417 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
418 |
|
419 #ifdef MOZ_B2G_RIL |
|
420 NS_DEFINE_CLASSINFO_DATA(MozMobileConnection, nsDOMGenericSH, |
|
421 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
422 #endif |
|
423 |
|
424 NS_DEFINE_CLASSINFO_DATA(CSSFontFaceRule, nsDOMGenericSH, |
|
425 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
426 |
|
427 NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ContentFrameMessageManager, nsEventTargetSH, |
|
428 DOM_DEFAULT_SCRIPTABLE_FLAGS | |
|
429 nsIXPCScriptable::IS_GLOBAL_OBJECT) |
|
430 NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageBroadcaster, nsDOMGenericSH, |
|
431 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
432 NS_DEFINE_CHROME_ONLY_CLASSINFO_DATA(ChromeMessageSender, nsDOMGenericSH, |
|
433 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
434 |
|
435 |
|
436 NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframeRule, nsDOMGenericSH, |
|
437 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
438 NS_DEFINE_CLASSINFO_DATA(MozCSSKeyframesRule, nsDOMGenericSH, |
|
439 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
440 |
|
441 NS_DEFINE_CLASSINFO_DATA(CSSPageRule, nsDOMGenericSH, |
|
442 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
443 |
|
444 NS_DEFINE_CLASSINFO_DATA(CSSFontFeatureValuesRule, nsDOMGenericSH, |
|
445 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
446 |
|
447 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(UserDataHandler, nsDOMGenericSH, |
|
448 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
449 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULControlElement, nsDOMGenericSH, |
|
450 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
451 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULLabeledControlElement, nsDOMGenericSH, |
|
452 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
453 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULButtonElement, nsDOMGenericSH, |
|
454 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
455 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULCheckboxElement, nsDOMGenericSH, |
|
456 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
457 NS_DEFINE_CHROME_XBL_CLASSINFO_DATA(XULPopupElement, nsDOMGenericSH, |
|
458 DOM_DEFAULT_SCRIPTABLE_FLAGS) |
|
459 }; |
|
460 |
|
461 #define NS_DEFINE_CONTRACT_CTOR(_class, _contract_id) \ |
|
462 static nsresult \ |
|
463 _class##Ctor(nsISupports** aInstancePtrResult) \ |
|
464 { \ |
|
465 nsresult rv = NS_OK; \ |
|
466 nsCOMPtr<nsISupports> native = do_CreateInstance(_contract_id, &rv); \ |
|
467 native.forget(aInstancePtrResult); \ |
|
468 return rv; \ |
|
469 } |
|
470 |
|
471 NS_DEFINE_CONTRACT_CTOR(XSLTProcessor, |
|
472 "@mozilla.org/document-transformer;1?type=xslt") |
|
473 |
|
474 #undef NS_DEFINE_CONTRACT_CTOR |
|
475 |
|
476 struct nsConstructorFuncMapData |
|
477 { |
|
478 int32_t mDOMClassInfoID; |
|
479 nsDOMConstructorFunc mConstructorFunc; |
|
480 }; |
|
481 |
|
482 #define NS_DEFINE_CONSTRUCTOR_FUNC_DATA(_class, _func) \ |
|
483 { eDOMClassInfo_##_class##_id, _func }, |
|
484 |
|
485 static const nsConstructorFuncMapData kConstructorFuncMap[] = |
|
486 { |
|
487 NS_DEFINE_CONSTRUCTOR_FUNC_DATA(Blob, nsDOMMultipartFile::NewBlob) |
|
488 NS_DEFINE_CONSTRUCTOR_FUNC_DATA(File, nsDOMMultipartFile::NewFile) |
|
489 NS_DEFINE_CONSTRUCTOR_FUNC_DATA(MozSmsFilter, SmsFilter::NewSmsFilter) |
|
490 NS_DEFINE_CONSTRUCTOR_FUNC_DATA(XSLTProcessor, XSLTProcessorCtor) |
|
491 }; |
|
492 #undef NS_DEFINE_CONSTRUCTOR_FUNC_DATA |
|
493 |
|
494 nsIXPConnect *nsDOMClassInfo::sXPConnect = nullptr; |
|
495 nsIScriptSecurityManager *nsDOMClassInfo::sSecMan = nullptr; |
|
496 bool nsDOMClassInfo::sIsInitialized = false; |
|
497 |
|
498 |
|
499 jsid nsDOMClassInfo::sLocation_id = JSID_VOID; |
|
500 jsid nsDOMClassInfo::sConstructor_id = JSID_VOID; |
|
501 jsid nsDOMClassInfo::sLength_id = JSID_VOID; |
|
502 jsid nsDOMClassInfo::sItem_id = JSID_VOID; |
|
503 jsid nsDOMClassInfo::sNamedItem_id = JSID_VOID; |
|
504 jsid nsDOMClassInfo::sEnumerate_id = JSID_VOID; |
|
505 jsid nsDOMClassInfo::sTop_id = JSID_VOID; |
|
506 jsid nsDOMClassInfo::sDocument_id = JSID_VOID; |
|
507 jsid nsDOMClassInfo::sWrappedJSObject_id = JSID_VOID; |
|
508 |
|
509 static const JSClass *sObjectClass = nullptr; |
|
510 |
|
511 /** |
|
512 * Set our JSClass pointer for the Object class |
|
513 */ |
|
514 static void |
|
515 FindObjectClass(JSContext* cx, JSObject* aGlobalObject) |
|
516 { |
|
517 NS_ASSERTION(!sObjectClass, |
|
518 "Double set of sObjectClass"); |
|
519 JS::Rooted<JSObject*> obj(cx), proto(cx, aGlobalObject); |
|
520 do { |
|
521 obj = proto; |
|
522 js::GetObjectProto(cx, obj, &proto); |
|
523 } while (proto); |
|
524 |
|
525 sObjectClass = js::GetObjectJSClass(obj); |
|
526 } |
|
527 |
|
528 static inline JSString * |
|
529 IdToString(JSContext *cx, jsid id) |
|
530 { |
|
531 if (JSID_IS_STRING(id)) |
|
532 return JSID_TO_STRING(id); |
|
533 JS::Rooted<JS::Value> idval(cx); |
|
534 if (!::JS_IdToValue(cx, id, &idval)) |
|
535 return nullptr; |
|
536 return JS::ToString(cx, idval); |
|
537 } |
|
538 |
|
539 static inline nsresult |
|
540 WrapNative(JSContext *cx, nsISupports *native, |
|
541 nsWrapperCache *cache, const nsIID* aIID, JS::MutableHandle<JS::Value> vp, |
|
542 bool aAllowWrapping) |
|
543 { |
|
544 if (!native) { |
|
545 vp.setNull(); |
|
546 |
|
547 return NS_OK; |
|
548 } |
|
549 |
|
550 JSObject *wrapper = xpc_FastGetCachedWrapper(cx, cache, vp); |
|
551 if (wrapper) { |
|
552 return NS_OK; |
|
553 } |
|
554 |
|
555 JS::Rooted<JSObject*> scope(cx, JS::CurrentGlobalOrNull(cx)); |
|
556 return nsDOMClassInfo::XPConnect()->WrapNativeToJSVal(cx, scope, native, |
|
557 cache, aIID, |
|
558 aAllowWrapping, vp); |
|
559 } |
|
560 |
|
561 static inline nsresult |
|
562 WrapNative(JSContext *cx, nsISupports *native, const nsIID* aIID, |
|
563 bool aAllowWrapping, JS::MutableHandle<JS::Value> vp) |
|
564 { |
|
565 return WrapNative(cx, native, nullptr, aIID, vp, aAllowWrapping); |
|
566 } |
|
567 |
|
568 // Same as the WrapNative above, but use these if aIID is nsISupports' IID. |
|
569 static inline nsresult |
|
570 WrapNative(JSContext *cx, nsISupports *native, |
|
571 bool aAllowWrapping, JS::MutableHandle<JS::Value> vp) |
|
572 { |
|
573 return WrapNative(cx, native, nullptr, nullptr, vp, aAllowWrapping); |
|
574 } |
|
575 |
|
576 static inline nsresult |
|
577 WrapNative(JSContext *cx, nsISupports *native, |
|
578 nsWrapperCache *cache, bool aAllowWrapping, |
|
579 JS::MutableHandle<JS::Value> vp) |
|
580 { |
|
581 return WrapNative(cx, native, cache, nullptr, vp, aAllowWrapping); |
|
582 } |
|
583 |
|
584 // Helper to handle torn-down inner windows. |
|
585 static inline nsresult |
|
586 SetParentToWindow(nsGlobalWindow *win, JSObject **parent) |
|
587 { |
|
588 MOZ_ASSERT(win); |
|
589 MOZ_ASSERT(win->IsInnerWindow()); |
|
590 *parent = win->FastGetGlobalJSObject(); |
|
591 |
|
592 if (MOZ_UNLIKELY(!*parent)) { |
|
593 // The inner window has been torn down. The scope is dying, so don't create |
|
594 // any new wrappers. |
|
595 return NS_ERROR_FAILURE; |
|
596 } |
|
597 return NS_OK; |
|
598 } |
|
599 |
|
600 // static |
|
601 |
|
602 nsISupports * |
|
603 nsDOMClassInfo::GetNative(nsIXPConnectWrappedNative *wrapper, JSObject *obj) |
|
604 { |
|
605 return wrapper ? wrapper->Native() : static_cast<nsISupports*>(js::GetObjectPrivate(obj)); |
|
606 } |
|
607 |
|
608 nsresult |
|
609 nsDOMClassInfo::DefineStaticJSVals(JSContext *cx) |
|
610 { |
|
611 #define SET_JSID_TO_STRING(_id, _cx, _str) \ |
|
612 if (JSString *str = ::JS_InternString(_cx, _str)) \ |
|
613 _id = INTERNED_STRING_TO_JSID(_cx, str); \ |
|
614 else \ |
|
615 return NS_ERROR_OUT_OF_MEMORY; |
|
616 |
|
617 SET_JSID_TO_STRING(sLocation_id, cx, "location"); |
|
618 SET_JSID_TO_STRING(sConstructor_id, cx, "constructor"); |
|
619 SET_JSID_TO_STRING(sLength_id, cx, "length"); |
|
620 SET_JSID_TO_STRING(sItem_id, cx, "item"); |
|
621 SET_JSID_TO_STRING(sNamedItem_id, cx, "namedItem"); |
|
622 SET_JSID_TO_STRING(sEnumerate_id, cx, "enumerateProperties"); |
|
623 SET_JSID_TO_STRING(sTop_id, cx, "top"); |
|
624 SET_JSID_TO_STRING(sDocument_id, cx, "document"); |
|
625 SET_JSID_TO_STRING(sWrappedJSObject_id, cx, "wrappedJSObject"); |
|
626 |
|
627 return NS_OK; |
|
628 } |
|
629 |
|
630 // static |
|
631 bool |
|
632 nsDOMClassInfo::ObjectIsNativeWrapper(JSContext* cx, JSObject* obj) |
|
633 { |
|
634 return xpc::WrapperFactory::IsXrayWrapper(obj) && |
|
635 xpc::AccessCheck::wrapperSubsumes(obj); |
|
636 } |
|
637 |
|
638 nsDOMClassInfo::nsDOMClassInfo(nsDOMClassInfoData* aData) : mData(aData) |
|
639 { |
|
640 } |
|
641 |
|
642 nsDOMClassInfo::~nsDOMClassInfo() |
|
643 { |
|
644 if (IS_EXTERNAL(mData->mCachedClassInfo)) { |
|
645 // Some compilers don't like delete'ing a const nsDOMClassInfo* |
|
646 nsDOMClassInfoData* data = const_cast<nsDOMClassInfoData*>(mData); |
|
647 delete static_cast<nsExternalDOMClassInfoData*>(data); |
|
648 } |
|
649 } |
|
650 |
|
651 NS_IMPL_ADDREF(nsDOMClassInfo) |
|
652 NS_IMPL_RELEASE(nsDOMClassInfo) |
|
653 |
|
654 NS_INTERFACE_MAP_BEGIN(nsDOMClassInfo) |
|
655 if (aIID.Equals(NS_GET_IID(nsXPCClassInfo))) |
|
656 foundInterface = static_cast<nsIClassInfo*>( |
|
657 static_cast<nsXPCClassInfo*>(this)); |
|
658 else |
|
659 NS_INTERFACE_MAP_ENTRY(nsIXPCScriptable) |
|
660 NS_INTERFACE_MAP_ENTRY(nsIClassInfo) |
|
661 NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIClassInfo) |
|
662 NS_INTERFACE_MAP_END |
|
663 |
|
664 |
|
665 static const JSClass sDOMConstructorProtoClass = { |
|
666 "DOM Constructor.prototype", 0, |
|
667 JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, |
|
668 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr |
|
669 }; |
|
670 |
|
671 |
|
672 static const char * |
|
673 CutPrefix(const char *aName) { |
|
674 static const char prefix_nsIDOM[] = "nsIDOM"; |
|
675 static const char prefix_nsI[] = "nsI"; |
|
676 |
|
677 if (strncmp(aName, prefix_nsIDOM, sizeof(prefix_nsIDOM) - 1) == 0) { |
|
678 return aName + sizeof(prefix_nsIDOM) - 1; |
|
679 } |
|
680 |
|
681 if (strncmp(aName, prefix_nsI, sizeof(prefix_nsI) - 1) == 0) { |
|
682 return aName + sizeof(prefix_nsI) - 1; |
|
683 } |
|
684 |
|
685 return aName; |
|
686 } |
|
687 |
|
688 // static |
|
689 nsresult |
|
690 nsDOMClassInfo::RegisterClassProtos(int32_t aClassInfoID) |
|
691 { |
|
692 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
693 NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); |
|
694 bool found_old; |
|
695 |
|
696 const nsIID *primary_iid = sClassInfoData[aClassInfoID].mProtoChainInterface; |
|
697 |
|
698 if (!primary_iid || primary_iid == &NS_GET_IID(nsISupports)) { |
|
699 return NS_OK; |
|
700 } |
|
701 |
|
702 nsCOMPtr<nsIInterfaceInfoManager> |
|
703 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); |
|
704 NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE); |
|
705 |
|
706 nsCOMPtr<nsIInterfaceInfo> if_info; |
|
707 bool first = true; |
|
708 |
|
709 iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info)); |
|
710 |
|
711 while (if_info) { |
|
712 const nsIID *iid = nullptr; |
|
713 |
|
714 if_info->GetIIDShared(&iid); |
|
715 NS_ENSURE_TRUE(iid, NS_ERROR_UNEXPECTED); |
|
716 |
|
717 if (iid->Equals(NS_GET_IID(nsISupports))) { |
|
718 break; |
|
719 } |
|
720 |
|
721 const char *name = nullptr; |
|
722 if_info->GetNameShared(&name); |
|
723 NS_ENSURE_TRUE(name, NS_ERROR_UNEXPECTED); |
|
724 |
|
725 nameSpaceManager->RegisterClassProto(CutPrefix(name), iid, &found_old); |
|
726 |
|
727 if (first) { |
|
728 first = false; |
|
729 } else if (found_old) { |
|
730 break; |
|
731 } |
|
732 |
|
733 nsCOMPtr<nsIInterfaceInfo> tmp(if_info); |
|
734 tmp->GetParent(getter_AddRefs(if_info)); |
|
735 } |
|
736 |
|
737 return NS_OK; |
|
738 } |
|
739 |
|
740 // static |
|
741 nsresult |
|
742 nsDOMClassInfo::RegisterExternalClasses() |
|
743 { |
|
744 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
745 NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); |
|
746 |
|
747 nsCOMPtr<nsIComponentRegistrar> registrar; |
|
748 nsresult rv = NS_GetComponentRegistrar(getter_AddRefs(registrar)); |
|
749 NS_ENSURE_SUCCESS(rv, rv); |
|
750 |
|
751 nsCOMPtr<nsICategoryManager> cm = |
|
752 do_GetService(NS_CATEGORYMANAGER_CONTRACTID, &rv); |
|
753 NS_ENSURE_SUCCESS(rv, rv); |
|
754 |
|
755 nsCOMPtr<nsISimpleEnumerator> e; |
|
756 rv = cm->EnumerateCategory(JAVASCRIPT_DOM_CLASS, getter_AddRefs(e)); |
|
757 NS_ENSURE_SUCCESS(rv, rv); |
|
758 |
|
759 nsXPIDLCString contractId; |
|
760 nsAutoCString categoryEntry; |
|
761 nsCOMPtr<nsISupports> entry; |
|
762 |
|
763 while (NS_SUCCEEDED(e->GetNext(getter_AddRefs(entry)))) { |
|
764 nsCOMPtr<nsISupportsCString> category(do_QueryInterface(entry)); |
|
765 |
|
766 if (!category) { |
|
767 NS_WARNING("Category entry not an nsISupportsCString!"); |
|
768 continue; |
|
769 } |
|
770 |
|
771 rv = category->GetData(categoryEntry); |
|
772 |
|
773 cm->GetCategoryEntry(JAVASCRIPT_DOM_CLASS, categoryEntry.get(), |
|
774 getter_Copies(contractId)); |
|
775 NS_ENSURE_SUCCESS(rv, rv); |
|
776 |
|
777 nsCID *cid; |
|
778 rv = registrar->ContractIDToCID(contractId, &cid); |
|
779 if (NS_FAILED(rv)) { |
|
780 NS_WARNING("Bad contract id registered with the script namespace manager"); |
|
781 continue; |
|
782 } |
|
783 |
|
784 rv = nameSpaceManager->RegisterExternalClassName(categoryEntry.get(), *cid); |
|
785 nsMemory::Free(cid); |
|
786 NS_ENSURE_SUCCESS(rv, rv); |
|
787 } |
|
788 |
|
789 return nameSpaceManager->RegisterExternalInterfaces(true); |
|
790 } |
|
791 |
|
792 #define _DOM_CLASSINFO_MAP_BEGIN(_class, _ifptr, _has_class_if) \ |
|
793 { \ |
|
794 nsDOMClassInfoData &d = sClassInfoData[eDOMClassInfo_##_class##_id]; \ |
|
795 d.mProtoChainInterface = _ifptr; \ |
|
796 d.mHasClassInterface = _has_class_if; \ |
|
797 d.mInterfacesBitmap = kDOMClassInfo_##_class##_interfaces; \ |
|
798 static const nsIID *interface_list[] = { |
|
799 |
|
800 #define DOM_CLASSINFO_MAP_BEGIN(_class, _interface) \ |
|
801 _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), true) |
|
802 |
|
803 #define DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(_class, _interface) \ |
|
804 _DOM_CLASSINFO_MAP_BEGIN(_class, &NS_GET_IID(_interface), false) |
|
805 |
|
806 #define DOM_CLASSINFO_MAP_ENTRY(_if) \ |
|
807 &NS_GET_IID(_if), |
|
808 |
|
809 #define DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(_if, _cond) \ |
|
810 (_cond) ? &NS_GET_IID(_if) : nullptr, |
|
811 |
|
812 #define DOM_CLASSINFO_MAP_END \ |
|
813 nullptr \ |
|
814 }; \ |
|
815 \ |
|
816 /* Compact the interface list */ \ |
|
817 size_t count = ArrayLength(interface_list); \ |
|
818 /* count is the number of array entries, which is one greater than the */ \ |
|
819 /* number of interfaces due to the terminating null */ \ |
|
820 for (size_t i = 0; i < count - 1; ++i) { \ |
|
821 if (!interface_list[i]) { \ |
|
822 /* We are moving the element at index i+1 and successors, */ \ |
|
823 /* so we must move only count - (i+1) elements total. */ \ |
|
824 memmove(&interface_list[i], &interface_list[i+1], \ |
|
825 sizeof(nsIID*) * (count - (i+1))); \ |
|
826 /* Make sure to examine the new pointer we ended up with at this */ \ |
|
827 /* slot, since it may be null too */ \ |
|
828 --i; \ |
|
829 --count; \ |
|
830 } \ |
|
831 } \ |
|
832 \ |
|
833 d.mInterfaces = interface_list; \ |
|
834 } |
|
835 |
|
836 #ifdef MOZ_B2G |
|
837 #define DOM_CLASSINFO_WINDOW_MAP_ENTRIES \ |
|
838 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow) \ |
|
839 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowB2G) \ |
|
840 DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow) \ |
|
841 DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \ |
|
842 DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers) \ |
|
843 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance) \ |
|
844 DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor) \ |
|
845 DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver, \ |
|
846 TouchEvent::PrefEnabled()) |
|
847 #else // !MOZ_B2G |
|
848 #define DOM_CLASSINFO_WINDOW_MAP_ENTRIES \ |
|
849 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindow) \ |
|
850 DOM_CLASSINFO_MAP_ENTRY(nsIDOMJSWindow) \ |
|
851 DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) \ |
|
852 DOM_CLASSINFO_MAP_ENTRY(nsIInlineEventHandlers) \ |
|
853 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowPerformance) \ |
|
854 DOM_CLASSINFO_MAP_ENTRY(nsIInterfaceRequestor) \ |
|
855 DOM_CLASSINFO_MAP_CONDITIONAL_ENTRY(nsITouchEventReceiver, \ |
|
856 TouchEvent::PrefEnabled()) |
|
857 #endif // MOZ_B2G |
|
858 |
|
859 nsresult |
|
860 nsDOMClassInfo::Init() |
|
861 { |
|
862 /* Errors that can trigger early returns are done first, |
|
863 otherwise nsDOMClassInfo is left in a half inited state. */ |
|
864 static_assert(sizeof(uintptr_t) == sizeof(void*), |
|
865 "BAD! You'll need to adjust the size of uintptr_t to the " |
|
866 "size of a pointer on your platform."); |
|
867 |
|
868 NS_ENSURE_TRUE(!sIsInitialized, NS_ERROR_ALREADY_INITIALIZED); |
|
869 |
|
870 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
871 NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); |
|
872 |
|
873 nsresult rv = CallGetService(nsIXPConnect::GetCID(), &sXPConnect); |
|
874 NS_ENSURE_SUCCESS(rv, rv); |
|
875 |
|
876 nsCOMPtr<nsIXPCFunctionThisTranslator> elt = new nsEventListenerThisTranslator(); |
|
877 sXPConnect->SetFunctionThisTranslator(NS_GET_IID(nsIDOMEventListener), elt); |
|
878 |
|
879 nsCOMPtr<nsIScriptSecurityManager> sm = |
|
880 do_GetService("@mozilla.org/scriptsecuritymanager;1", &rv); |
|
881 NS_ENSURE_SUCCESS(rv, rv); |
|
882 |
|
883 sSecMan = sm; |
|
884 NS_ADDREF(sSecMan); |
|
885 |
|
886 AutoSafeJSContext cx; |
|
887 |
|
888 DOM_CLASSINFO_MAP_BEGIN(Window, nsIDOMWindow) |
|
889 DOM_CLASSINFO_WINDOW_MAP_ENTRIES |
|
890 #ifdef MOZ_WEBSPEECH |
|
891 DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter) |
|
892 #endif |
|
893 DOM_CLASSINFO_MAP_END |
|
894 |
|
895 DOM_CLASSINFO_MAP_BEGIN(WindowUtils, nsIDOMWindowUtils) |
|
896 DOM_CLASSINFO_MAP_ENTRY(nsIDOMWindowUtils) |
|
897 DOM_CLASSINFO_MAP_END |
|
898 |
|
899 DOM_CLASSINFO_MAP_BEGIN(Location, nsIDOMLocation) |
|
900 DOM_CLASSINFO_MAP_ENTRY(nsIDOMLocation) |
|
901 DOM_CLASSINFO_MAP_END |
|
902 |
|
903 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(DOMPrototype, nsIDOMDOMConstructor) |
|
904 DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor) |
|
905 DOM_CLASSINFO_MAP_END |
|
906 |
|
907 DOM_CLASSINFO_MAP_BEGIN(DOMConstructor, nsIDOMDOMConstructor) |
|
908 DOM_CLASSINFO_MAP_ENTRY(nsIDOMDOMConstructor) |
|
909 DOM_CLASSINFO_MAP_END |
|
910 |
|
911 DOM_CLASSINFO_MAP_BEGIN(CSSStyleRule, nsIDOMCSSStyleRule) |
|
912 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleRule) |
|
913 DOM_CLASSINFO_MAP_END |
|
914 |
|
915 DOM_CLASSINFO_MAP_BEGIN(CSSCharsetRule, nsIDOMCSSCharsetRule) |
|
916 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSCharsetRule) |
|
917 DOM_CLASSINFO_MAP_END |
|
918 |
|
919 DOM_CLASSINFO_MAP_BEGIN(CSSImportRule, nsIDOMCSSImportRule) |
|
920 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSImportRule) |
|
921 DOM_CLASSINFO_MAP_END |
|
922 |
|
923 DOM_CLASSINFO_MAP_BEGIN(CSSMediaRule, nsIDOMCSSMediaRule) |
|
924 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMediaRule) |
|
925 DOM_CLASSINFO_MAP_END |
|
926 |
|
927 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(CSSNameSpaceRule, nsIDOMCSSRule) |
|
928 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRule) |
|
929 DOM_CLASSINFO_MAP_END |
|
930 |
|
931 DOM_CLASSINFO_MAP_BEGIN(CSSRuleList, nsIDOMCSSRuleList) |
|
932 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSRuleList) |
|
933 DOM_CLASSINFO_MAP_END |
|
934 |
|
935 DOM_CLASSINFO_MAP_BEGIN(CSSStyleSheet, nsIDOMCSSStyleSheet) |
|
936 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSStyleSheet) |
|
937 DOM_CLASSINFO_MAP_END |
|
938 |
|
939 #ifdef MOZ_XUL |
|
940 DOM_CLASSINFO_MAP_BEGIN(XULCommandDispatcher, nsIDOMXULCommandDispatcher) |
|
941 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCommandDispatcher) |
|
942 DOM_CLASSINFO_MAP_END |
|
943 #endif |
|
944 |
|
945 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControllers, nsIControllers) |
|
946 DOM_CLASSINFO_MAP_ENTRY(nsIControllers) |
|
947 DOM_CLASSINFO_MAP_END |
|
948 |
|
949 DOM_CLASSINFO_MAP_BEGIN(BoxObject, nsIBoxObject) |
|
950 DOM_CLASSINFO_MAP_ENTRY(nsIBoxObject) |
|
951 DOM_CLASSINFO_MAP_END |
|
952 |
|
953 #ifdef MOZ_XUL |
|
954 DOM_CLASSINFO_MAP_BEGIN(TreeSelection, nsITreeSelection) |
|
955 DOM_CLASSINFO_MAP_ENTRY(nsITreeSelection) |
|
956 DOM_CLASSINFO_MAP_END |
|
957 |
|
958 DOM_CLASSINFO_MAP_BEGIN(TreeContentView, nsITreeContentView) |
|
959 DOM_CLASSINFO_MAP_ENTRY(nsITreeContentView) |
|
960 DOM_CLASSINFO_MAP_ENTRY(nsITreeView) |
|
961 DOM_CLASSINFO_MAP_END |
|
962 #endif |
|
963 |
|
964 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeWindow, nsIDOMWindow) |
|
965 DOM_CLASSINFO_WINDOW_MAP_ENTRIES |
|
966 DOM_CLASSINFO_MAP_ENTRY(nsIDOMChromeWindow) |
|
967 #ifdef MOZ_WEBSPEECH |
|
968 DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter) |
|
969 #endif |
|
970 DOM_CLASSINFO_MAP_END |
|
971 |
|
972 #ifdef MOZ_XUL |
|
973 DOM_CLASSINFO_MAP_BEGIN(XULTemplateBuilder, nsIXULTemplateBuilder) |
|
974 DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder) |
|
975 DOM_CLASSINFO_MAP_END |
|
976 |
|
977 DOM_CLASSINFO_MAP_BEGIN(XULTreeBuilder, nsIXULTreeBuilder) |
|
978 DOM_CLASSINFO_MAP_ENTRY(nsIXULTreeBuilder) |
|
979 DOM_CLASSINFO_MAP_ENTRY(nsIXULTemplateBuilder) |
|
980 DOM_CLASSINFO_MAP_ENTRY(nsITreeView) |
|
981 DOM_CLASSINFO_MAP_END |
|
982 #endif |
|
983 |
|
984 #ifdef MOZ_XUL |
|
985 DOM_CLASSINFO_MAP_BEGIN(TreeColumn, nsITreeColumn) |
|
986 DOM_CLASSINFO_MAP_ENTRY(nsITreeColumn) |
|
987 DOM_CLASSINFO_MAP_END |
|
988 #endif |
|
989 |
|
990 DOM_CLASSINFO_MAP_BEGIN(CSSMozDocumentRule, nsIDOMCSSMozDocumentRule) |
|
991 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSMozDocumentRule) |
|
992 DOM_CLASSINFO_MAP_END |
|
993 |
|
994 DOM_CLASSINFO_MAP_BEGIN(CSSSupportsRule, nsIDOMCSSSupportsRule) |
|
995 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSSupportsRule) |
|
996 DOM_CLASSINFO_MAP_END |
|
997 |
|
998 // The SVG document |
|
999 |
|
1000 // other SVG classes |
|
1001 DOM_CLASSINFO_MAP_BEGIN(SVGNumber, nsIDOMSVGNumber) |
|
1002 DOM_CLASSINFO_MAP_ENTRY(nsIDOMSVGNumber) |
|
1003 DOM_CLASSINFO_MAP_END |
|
1004 |
|
1005 DOM_CLASSINFO_MAP_BEGIN(XSLTProcessor, nsIXSLTProcessor) |
|
1006 DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessor) |
|
1007 DOM_CLASSINFO_MAP_ENTRY(nsIXSLTProcessorPrivate) |
|
1008 DOM_CLASSINFO_MAP_END |
|
1009 |
|
1010 DOM_CLASSINFO_MAP_BEGIN(XPathExpression, nsIDOMXPathExpression) |
|
1011 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathExpression) |
|
1012 DOM_CLASSINFO_MAP_ENTRY(nsIDOMNSXPathExpression) |
|
1013 DOM_CLASSINFO_MAP_END |
|
1014 |
|
1015 DOM_CLASSINFO_MAP_BEGIN(XPathNSResolver, nsIDOMXPathNSResolver) |
|
1016 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathNSResolver) |
|
1017 DOM_CLASSINFO_MAP_END |
|
1018 |
|
1019 DOM_CLASSINFO_MAP_BEGIN(XPathResult, nsIDOMXPathResult) |
|
1020 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXPathResult) |
|
1021 DOM_CLASSINFO_MAP_END |
|
1022 |
|
1023 DOM_CLASSINFO_MAP_BEGIN(Storage, nsIDOMStorage) |
|
1024 DOM_CLASSINFO_MAP_ENTRY(nsIDOMStorage) |
|
1025 DOM_CLASSINFO_MAP_END |
|
1026 |
|
1027 DOM_CLASSINFO_MAP_BEGIN(Blob, nsIDOMBlob) |
|
1028 DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) |
|
1029 DOM_CLASSINFO_MAP_END |
|
1030 |
|
1031 DOM_CLASSINFO_MAP_BEGIN(File, nsIDOMFile) |
|
1032 DOM_CLASSINFO_MAP_ENTRY(nsIDOMBlob) |
|
1033 DOM_CLASSINFO_MAP_ENTRY(nsIDOMFile) |
|
1034 DOM_CLASSINFO_MAP_END |
|
1035 |
|
1036 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ModalContentWindow, nsIDOMWindow) |
|
1037 DOM_CLASSINFO_WINDOW_MAP_ENTRIES |
|
1038 DOM_CLASSINFO_MAP_ENTRY(nsIDOMModalContentWindow) |
|
1039 #ifdef MOZ_WEBSPEECH |
|
1040 DOM_CLASSINFO_MAP_ENTRY(nsISpeechSynthesisGetter) |
|
1041 #endif |
|
1042 DOM_CLASSINFO_MAP_END |
|
1043 |
|
1044 DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageManager, nsIDOMMozMobileMessageManager) |
|
1045 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageManager) |
|
1046 DOM_CLASSINFO_MAP_END |
|
1047 |
|
1048 DOM_CLASSINFO_MAP_BEGIN(MozSmsMessage, nsIDOMMozSmsMessage) |
|
1049 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsMessage) |
|
1050 DOM_CLASSINFO_MAP_END |
|
1051 |
|
1052 DOM_CLASSINFO_MAP_BEGIN(MozMmsMessage, nsIDOMMozMmsMessage) |
|
1053 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMmsMessage) |
|
1054 DOM_CLASSINFO_MAP_END |
|
1055 |
|
1056 DOM_CLASSINFO_MAP_BEGIN(MozSmsFilter, nsIDOMMozSmsFilter) |
|
1057 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsFilter) |
|
1058 DOM_CLASSINFO_MAP_END |
|
1059 |
|
1060 DOM_CLASSINFO_MAP_BEGIN(MozSmsSegmentInfo, nsIDOMMozSmsSegmentInfo) |
|
1061 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozSmsSegmentInfo) |
|
1062 DOM_CLASSINFO_MAP_END |
|
1063 |
|
1064 DOM_CLASSINFO_MAP_BEGIN(MozMobileMessageThread, nsIDOMMozMobileMessageThread) |
|
1065 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileMessageThread) |
|
1066 DOM_CLASSINFO_MAP_END |
|
1067 |
|
1068 #ifdef MOZ_B2G_RIL |
|
1069 DOM_CLASSINFO_MAP_BEGIN(MozMobileConnection, nsIDOMMozMobileConnection) |
|
1070 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozMobileConnection) |
|
1071 DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) |
|
1072 DOM_CLASSINFO_MAP_END |
|
1073 #endif // MOZ_B2G_RIL |
|
1074 |
|
1075 DOM_CLASSINFO_MAP_BEGIN(CSSFontFaceRule, nsIDOMCSSFontFaceRule) |
|
1076 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFaceRule) |
|
1077 DOM_CLASSINFO_MAP_END |
|
1078 |
|
1079 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ContentFrameMessageManager, nsISupports) |
|
1080 DOM_CLASSINFO_MAP_ENTRY(nsIDOMEventTarget) |
|
1081 DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager) |
|
1082 DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender) |
|
1083 DOM_CLASSINFO_MAP_ENTRY(nsISyncMessageSender) |
|
1084 DOM_CLASSINFO_MAP_ENTRY(nsIContentFrameMessageManager) |
|
1085 DOM_CLASSINFO_MAP_END |
|
1086 |
|
1087 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageBroadcaster, nsISupports) |
|
1088 DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader) |
|
1089 DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager) |
|
1090 DOM_CLASSINFO_MAP_ENTRY(nsIMessageBroadcaster) |
|
1091 DOM_CLASSINFO_MAP_END |
|
1092 |
|
1093 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(ChromeMessageSender, nsISupports) |
|
1094 DOM_CLASSINFO_MAP_ENTRY(nsIProcessChecker) |
|
1095 DOM_CLASSINFO_MAP_ENTRY(nsIFrameScriptLoader) |
|
1096 DOM_CLASSINFO_MAP_ENTRY(nsIMessageListenerManager) |
|
1097 DOM_CLASSINFO_MAP_ENTRY(nsIMessageSender) |
|
1098 DOM_CLASSINFO_MAP_END |
|
1099 |
|
1100 DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframeRule, nsIDOMMozCSSKeyframeRule) |
|
1101 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframeRule) |
|
1102 DOM_CLASSINFO_MAP_END |
|
1103 |
|
1104 DOM_CLASSINFO_MAP_BEGIN(MozCSSKeyframesRule, nsIDOMMozCSSKeyframesRule) |
|
1105 DOM_CLASSINFO_MAP_ENTRY(nsIDOMMozCSSKeyframesRule) |
|
1106 DOM_CLASSINFO_MAP_END |
|
1107 |
|
1108 DOM_CLASSINFO_MAP_BEGIN(CSSPageRule, nsIDOMCSSPageRule) |
|
1109 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSPageRule) |
|
1110 DOM_CLASSINFO_MAP_END |
|
1111 |
|
1112 DOM_CLASSINFO_MAP_BEGIN(CSSFontFeatureValuesRule, nsIDOMCSSFontFeatureValuesRule) |
|
1113 DOM_CLASSINFO_MAP_ENTRY(nsIDOMCSSFontFeatureValuesRule) |
|
1114 DOM_CLASSINFO_MAP_END |
|
1115 |
|
1116 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(UserDataHandler, nsIDOMUserDataHandler) |
|
1117 DOM_CLASSINFO_MAP_ENTRY(nsIDOMUserDataHandler) |
|
1118 DOM_CLASSINFO_MAP_END |
|
1119 |
|
1120 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULControlElement, nsIDOMXULControlElement) |
|
1121 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULControlElement) |
|
1122 DOM_CLASSINFO_MAP_END |
|
1123 |
|
1124 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULLabeledControlElement, nsIDOMXULLabeledControlElement) |
|
1125 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULLabeledControlElement) |
|
1126 DOM_CLASSINFO_MAP_END |
|
1127 |
|
1128 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULButtonElement, nsIDOMXULButtonElement) |
|
1129 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULButtonElement) |
|
1130 DOM_CLASSINFO_MAP_END |
|
1131 |
|
1132 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULCheckboxElement, nsIDOMXULCheckboxElement) |
|
1133 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULCheckboxElement) |
|
1134 DOM_CLASSINFO_MAP_END |
|
1135 |
|
1136 DOM_CLASSINFO_MAP_BEGIN_NO_CLASS_IF(XULPopupElement, nsIDOMXULPopupElement) |
|
1137 DOM_CLASSINFO_MAP_ENTRY(nsIDOMXULPopupElement) |
|
1138 DOM_CLASSINFO_MAP_END |
|
1139 |
|
1140 static_assert(MOZ_ARRAY_LENGTH(sClassInfoData) == eDOMClassInfoIDCount, |
|
1141 "The number of items in sClassInfoData doesn't match the " |
|
1142 "number of nsIDOMClassInfo ID's, this is bad! Fix it!"); |
|
1143 |
|
1144 #ifdef DEBUG |
|
1145 for (size_t i = 0; i < eDOMClassInfoIDCount; i++) { |
|
1146 if (!sClassInfoData[i].u.mConstructorFptr || |
|
1147 sClassInfoData[i].mDebugID != i) { |
|
1148 MOZ_CRASH("Class info data out of sync, you forgot to update " |
|
1149 "nsDOMClassInfo.h and nsDOMClassInfo.cpp! Fix this, " |
|
1150 "mozilla will not work without this fixed!"); |
|
1151 } |
|
1152 } |
|
1153 |
|
1154 for (size_t i = 0; i < eDOMClassInfoIDCount; i++) { |
|
1155 if (!sClassInfoData[i].mInterfaces) { |
|
1156 MOZ_CRASH("Class info data without an interface list! Fix this, " |
|
1157 "mozilla will not work without this fixed!"); |
|
1158 } |
|
1159 } |
|
1160 #endif |
|
1161 |
|
1162 // Initialize static JSString's |
|
1163 DefineStaticJSVals(cx); |
|
1164 |
|
1165 int32_t i; |
|
1166 |
|
1167 for (i = 0; i < eDOMClassInfoIDCount; ++i) { |
|
1168 if (i == eDOMClassInfo_DOMPrototype_id) { |
|
1169 continue; |
|
1170 } |
|
1171 |
|
1172 nsDOMClassInfoData& data = sClassInfoData[i]; |
|
1173 nameSpaceManager->RegisterClassName(data.mName, i, data.mChromeOnly, |
|
1174 data.mAllowXBL, &data.mNameUTF16); |
|
1175 } |
|
1176 |
|
1177 for (i = 0; i < eDOMClassInfoIDCount; ++i) { |
|
1178 RegisterClassProtos(i); |
|
1179 } |
|
1180 |
|
1181 RegisterExternalClasses(); |
|
1182 |
|
1183 // Register new DOM bindings |
|
1184 mozilla::dom::Register(nameSpaceManager); |
|
1185 |
|
1186 sIsInitialized = true; |
|
1187 |
|
1188 return NS_OK; |
|
1189 } |
|
1190 |
|
1191 // static |
|
1192 int32_t |
|
1193 nsDOMClassInfo::GetArrayIndexFromId(JSContext *cx, JS::Handle<jsid> id, bool *aIsNumber) |
|
1194 { |
|
1195 if (aIsNumber) { |
|
1196 *aIsNumber = false; |
|
1197 } |
|
1198 |
|
1199 int i; |
|
1200 if (JSID_IS_INT(id)) { |
|
1201 i = JSID_TO_INT(id); |
|
1202 } else { |
|
1203 JS::Rooted<JS::Value> idval(cx); |
|
1204 double array_index; |
|
1205 if (!::JS_IdToValue(cx, id, &idval) || |
|
1206 !JS::ToNumber(cx, idval, &array_index) || |
|
1207 !::JS_DoubleIsInt32(array_index, &i)) { |
|
1208 return -1; |
|
1209 } |
|
1210 } |
|
1211 |
|
1212 if (aIsNumber) { |
|
1213 *aIsNumber = true; |
|
1214 } |
|
1215 |
|
1216 return i; |
|
1217 } |
|
1218 |
|
1219 NS_IMETHODIMP |
|
1220 nsDOMClassInfo::GetInterfaces(uint32_t *aCount, nsIID ***aArray) |
|
1221 { |
|
1222 uint32_t count = 0; |
|
1223 |
|
1224 while (mData->mInterfaces[count]) { |
|
1225 count++; |
|
1226 } |
|
1227 |
|
1228 *aCount = count; |
|
1229 |
|
1230 if (!count) { |
|
1231 *aArray = nullptr; |
|
1232 |
|
1233 return NS_OK; |
|
1234 } |
|
1235 |
|
1236 *aArray = static_cast<nsIID **>(nsMemory::Alloc(count * sizeof(nsIID *))); |
|
1237 NS_ENSURE_TRUE(*aArray, NS_ERROR_OUT_OF_MEMORY); |
|
1238 |
|
1239 uint32_t i; |
|
1240 for (i = 0; i < count; i++) { |
|
1241 nsIID *iid = static_cast<nsIID *>(nsMemory::Clone(mData->mInterfaces[i], |
|
1242 sizeof(nsIID))); |
|
1243 |
|
1244 if (!iid) { |
|
1245 NS_FREE_XPCOM_ALLOCATED_POINTER_ARRAY(i, *aArray); |
|
1246 |
|
1247 return NS_ERROR_OUT_OF_MEMORY; |
|
1248 } |
|
1249 |
|
1250 *((*aArray) + i) = iid; |
|
1251 } |
|
1252 |
|
1253 return NS_OK; |
|
1254 } |
|
1255 |
|
1256 NS_IMETHODIMP |
|
1257 nsDOMClassInfo::GetHelperForLanguage(uint32_t language, nsISupports **_retval) |
|
1258 { |
|
1259 if (language == nsIProgrammingLanguage::JAVASCRIPT) { |
|
1260 *_retval = static_cast<nsIXPCScriptable *>(this); |
|
1261 |
|
1262 NS_ADDREF(*_retval); |
|
1263 } else { |
|
1264 *_retval = nullptr; |
|
1265 } |
|
1266 |
|
1267 return NS_OK; |
|
1268 } |
|
1269 |
|
1270 NS_IMETHODIMP |
|
1271 nsDOMClassInfo::GetContractID(char **aContractID) |
|
1272 { |
|
1273 *aContractID = nullptr; |
|
1274 |
|
1275 return NS_OK; |
|
1276 } |
|
1277 |
|
1278 NS_IMETHODIMP |
|
1279 nsDOMClassInfo::GetClassDescription(char **aClassDescription) |
|
1280 { |
|
1281 return GetClassName(aClassDescription); |
|
1282 } |
|
1283 |
|
1284 NS_IMETHODIMP |
|
1285 nsDOMClassInfo::GetClassID(nsCID **aClassID) |
|
1286 { |
|
1287 *aClassID = nullptr; |
|
1288 return NS_OK; |
|
1289 } |
|
1290 |
|
1291 NS_IMETHODIMP |
|
1292 nsDOMClassInfo::GetClassIDNoAlloc(nsCID *aClassID) |
|
1293 { |
|
1294 return NS_ERROR_NOT_AVAILABLE; |
|
1295 } |
|
1296 |
|
1297 NS_IMETHODIMP |
|
1298 nsDOMClassInfo::GetImplementationLanguage(uint32_t *aImplLanguage) |
|
1299 { |
|
1300 *aImplLanguage = nsIProgrammingLanguage::CPLUSPLUS; |
|
1301 |
|
1302 return NS_OK; |
|
1303 } |
|
1304 |
|
1305 NS_IMETHODIMP |
|
1306 nsDOMClassInfo::GetFlags(uint32_t *aFlags) |
|
1307 { |
|
1308 *aFlags = DOMCLASSINFO_STANDARD_FLAGS; |
|
1309 |
|
1310 return NS_OK; |
|
1311 } |
|
1312 |
|
1313 // nsIXPCScriptable |
|
1314 |
|
1315 NS_IMETHODIMP |
|
1316 nsDOMClassInfo::GetClassName(char **aClassName) |
|
1317 { |
|
1318 *aClassName = NS_strdup(mData->mName); |
|
1319 |
|
1320 return NS_OK; |
|
1321 } |
|
1322 |
|
1323 // virtual |
|
1324 uint32_t |
|
1325 nsDOMClassInfo::GetScriptableFlags() |
|
1326 { |
|
1327 return mData->mScriptableFlags; |
|
1328 } |
|
1329 |
|
1330 NS_IMETHODIMP |
|
1331 nsDOMClassInfo::PreCreate(nsISupports *nativeObj, JSContext *cx, |
|
1332 JSObject *globalObj, JSObject **parentObj) |
|
1333 { |
|
1334 *parentObj = globalObj; |
|
1335 return NS_OK; |
|
1336 } |
|
1337 |
|
1338 NS_IMETHODIMP |
|
1339 nsDOMClassInfo::Create(nsIXPConnectWrappedNative *wrapper, |
|
1340 JSContext *cx, JSObject *obj) |
|
1341 { |
|
1342 NS_WARNING("nsDOMClassInfo::Create Don't call me!"); |
|
1343 |
|
1344 return NS_ERROR_UNEXPECTED; |
|
1345 } |
|
1346 |
|
1347 NS_IMETHODIMP |
|
1348 nsDOMClassInfo::PostCreate(nsIXPConnectWrappedNative *wrapper, |
|
1349 JSContext *cx, JSObject *obj) |
|
1350 { |
|
1351 NS_WARNING("nsDOMClassInfo::PostCreate Don't call me!"); |
|
1352 |
|
1353 return NS_ERROR_UNEXPECTED; |
|
1354 } |
|
1355 |
|
1356 NS_IMETHODIMP |
|
1357 nsDOMClassInfo::PostTransplant(nsIXPConnectWrappedNative *wrapper, |
|
1358 JSContext *cx, JSObject *obj) |
|
1359 { |
|
1360 MOZ_CRASH("nsDOMClassInfo::PostTransplant Don't call me!"); |
|
1361 } |
|
1362 |
|
1363 NS_IMETHODIMP |
|
1364 nsDOMClassInfo::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1365 JSObject *obj, jsid id, jsval *vp, |
|
1366 bool *_retval) |
|
1367 { |
|
1368 NS_WARNING("nsDOMClassInfo::AddProperty Don't call me!"); |
|
1369 |
|
1370 return NS_ERROR_UNEXPECTED; |
|
1371 } |
|
1372 |
|
1373 NS_IMETHODIMP |
|
1374 nsDOMClassInfo::DelProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1375 JSObject *obj, jsid id, bool *_retval) |
|
1376 { |
|
1377 NS_WARNING("nsDOMClassInfo::DelProperty Don't call me!"); |
|
1378 |
|
1379 return NS_ERROR_UNEXPECTED; |
|
1380 } |
|
1381 |
|
1382 NS_IMETHODIMP |
|
1383 nsDOMClassInfo::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1384 JSObject *obj, jsid id, jsval *vp, |
|
1385 bool *_retval) |
|
1386 { |
|
1387 NS_WARNING("nsDOMClassInfo::GetProperty Don't call me!"); |
|
1388 |
|
1389 return NS_OK; |
|
1390 } |
|
1391 |
|
1392 NS_IMETHODIMP |
|
1393 nsDOMClassInfo::SetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1394 JSObject *obj, jsid id, jsval *vp, |
|
1395 bool *_retval) |
|
1396 { |
|
1397 NS_WARNING("nsDOMClassInfo::SetProperty Don't call me!"); |
|
1398 |
|
1399 return NS_ERROR_UNEXPECTED; |
|
1400 } |
|
1401 |
|
1402 NS_IMETHODIMP |
|
1403 nsDOMClassInfo::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1404 JSObject *obj, bool *_retval) |
|
1405 { |
|
1406 return NS_OK; |
|
1407 } |
|
1408 |
|
1409 NS_IMETHODIMP |
|
1410 nsDOMClassInfo::NewEnumerate(nsIXPConnectWrappedNative *wrapper, |
|
1411 JSContext *cx, JSObject *obj, uint32_t enum_op, |
|
1412 jsval *statep, jsid *idp, bool *_retval) |
|
1413 { |
|
1414 NS_WARNING("nsDOMClassInfo::NewEnumerate Don't call me!"); |
|
1415 |
|
1416 return NS_ERROR_UNEXPECTED; |
|
1417 } |
|
1418 |
|
1419 nsresult |
|
1420 nsDOMClassInfo::ResolveConstructor(JSContext *cx, JSObject *aObj, |
|
1421 JSObject **objp) |
|
1422 { |
|
1423 JS::Rooted<JSObject*> obj(cx, aObj); |
|
1424 JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, obj)); |
|
1425 |
|
1426 JS::Rooted<JS::Value> val(cx); |
|
1427 if (!::JS_LookupProperty(cx, global, mData->mName, &val)) { |
|
1428 return NS_ERROR_UNEXPECTED; |
|
1429 } |
|
1430 |
|
1431 if (!JSVAL_IS_PRIMITIVE(val)) { |
|
1432 // If val is not an (non-null) object there either is no |
|
1433 // constructor for this class, or someone messed with |
|
1434 // window.classname, just fall through and let the JS engine |
|
1435 // return the Object constructor. |
|
1436 |
|
1437 if (!::JS_DefinePropertyById(cx, obj, sConstructor_id, val, JS_PropertyStub, |
|
1438 JS_StrictPropertyStub, JSPROP_ENUMERATE)) { |
|
1439 return NS_ERROR_UNEXPECTED; |
|
1440 } |
|
1441 |
|
1442 *objp = obj; |
|
1443 } |
|
1444 |
|
1445 return NS_OK; |
|
1446 } |
|
1447 |
|
1448 NS_IMETHODIMP |
|
1449 nsDOMClassInfo::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1450 JSObject *obj, jsid id, JSObject **objp, |
|
1451 bool *_retval) |
|
1452 { |
|
1453 if (id == sConstructor_id) { |
|
1454 return ResolveConstructor(cx, obj, objp); |
|
1455 } |
|
1456 |
|
1457 return NS_OK; |
|
1458 } |
|
1459 |
|
1460 NS_IMETHODIMP |
|
1461 nsDOMClassInfo::Convert(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1462 JSObject *obj, uint32_t type, jsval *vp, |
|
1463 bool *_retval) |
|
1464 { |
|
1465 NS_WARNING("nsDOMClassInfo::Convert Don't call me!"); |
|
1466 |
|
1467 return NS_ERROR_UNEXPECTED; |
|
1468 } |
|
1469 |
|
1470 NS_IMETHODIMP |
|
1471 nsDOMClassInfo::Finalize(nsIXPConnectWrappedNative *wrapper, JSFreeOp *fop, |
|
1472 JSObject *obj) |
|
1473 { |
|
1474 NS_WARNING("nsDOMClassInfo::Finalize Don't call me!"); |
|
1475 |
|
1476 return NS_ERROR_UNEXPECTED; |
|
1477 } |
|
1478 |
|
1479 NS_IMETHODIMP |
|
1480 nsDOMClassInfo::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1481 JSObject *obj, const JS::CallArgs &args, bool *_retval) |
|
1482 { |
|
1483 NS_WARNING("nsDOMClassInfo::Call Don't call me!"); |
|
1484 |
|
1485 return NS_ERROR_UNEXPECTED; |
|
1486 } |
|
1487 |
|
1488 NS_IMETHODIMP |
|
1489 nsDOMClassInfo::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1490 JSObject *obj, const JS::CallArgs &args, |
|
1491 bool *_retval) |
|
1492 { |
|
1493 NS_WARNING("nsDOMClassInfo::Construct Don't call me!"); |
|
1494 |
|
1495 return NS_ERROR_UNEXPECTED; |
|
1496 } |
|
1497 |
|
1498 NS_IMETHODIMP |
|
1499 nsDOMClassInfo::HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1500 JSObject *obj, JS::Handle<JS::Value> val, bool *bp, |
|
1501 bool *_retval) |
|
1502 { |
|
1503 NS_WARNING("nsDOMClassInfo::HasInstance Don't call me!"); |
|
1504 |
|
1505 return NS_ERROR_UNEXPECTED; |
|
1506 } |
|
1507 |
|
1508 NS_IMETHODIMP |
|
1509 nsDOMClassInfo::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, |
|
1510 JSObject * obj, JSObject * *_retval) |
|
1511 { |
|
1512 NS_WARNING("nsDOMClassInfo::OuterObject Don't call me!"); |
|
1513 |
|
1514 return NS_ERROR_UNEXPECTED; |
|
1515 } |
|
1516 |
|
1517 static nsresult |
|
1518 GetExternalClassInfo(nsScriptNameSpaceManager *aNameSpaceManager, |
|
1519 const nsAString &aName, |
|
1520 const nsGlobalNameStruct *aStruct, |
|
1521 const nsGlobalNameStruct **aResult) |
|
1522 { |
|
1523 NS_ASSERTION(aStruct->mType == |
|
1524 nsGlobalNameStruct::eTypeExternalClassInfoCreator, |
|
1525 "Wrong type!"); |
|
1526 |
|
1527 nsresult rv; |
|
1528 nsCOMPtr<nsIDOMCIExtension> creator(do_CreateInstance(aStruct->mCID, &rv)); |
|
1529 NS_ENSURE_SUCCESS(rv, rv); |
|
1530 |
|
1531 nsCOMPtr<nsIDOMScriptObjectFactory> sof(do_GetService(kDOMSOF_CID)); |
|
1532 NS_ENSURE_TRUE(sof, NS_ERROR_FAILURE); |
|
1533 |
|
1534 rv = creator->RegisterDOMCI(NS_ConvertUTF16toUTF8(aName).get(), sof); |
|
1535 NS_ENSURE_SUCCESS(rv, rv); |
|
1536 |
|
1537 const nsGlobalNameStruct *name_struct = aNameSpaceManager->LookupName(aName); |
|
1538 if (name_struct && |
|
1539 name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
1540 *aResult = name_struct; |
|
1541 } |
|
1542 else { |
|
1543 NS_ERROR("Couldn't get the DOM ClassInfo data."); |
|
1544 |
|
1545 *aResult = nullptr; |
|
1546 } |
|
1547 |
|
1548 return NS_OK; |
|
1549 } |
|
1550 |
|
1551 |
|
1552 static nsresult |
|
1553 ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, |
|
1554 JS::Handle<JSObject*> obj, const char16_t *name, |
|
1555 const nsDOMClassInfoData *ci_data, |
|
1556 const nsGlobalNameStruct *name_struct, |
|
1557 nsScriptNameSpaceManager *nameSpaceManager, |
|
1558 JSObject *dot_prototype, |
|
1559 JS::MutableHandle<JSPropertyDescriptor> ctorDesc); |
|
1560 |
|
1561 NS_IMETHODIMP |
|
1562 nsDOMClassInfo::PostCreatePrototype(JSContext * cx, JSObject * aProto) |
|
1563 { |
|
1564 uint32_t flags = (mData->mScriptableFlags & DONT_ENUM_STATIC_PROPS) |
|
1565 ? 0 |
|
1566 : JSPROP_ENUMERATE; |
|
1567 |
|
1568 uint32_t count = 0; |
|
1569 while (mData->mInterfaces[count]) { |
|
1570 count++; |
|
1571 } |
|
1572 |
|
1573 JS::Rooted<JSObject*> proto(cx, aProto); |
|
1574 if (!xpc::DOM_DefineQuickStubs(cx, proto, flags, count, mData->mInterfaces)) { |
|
1575 JS_ClearPendingException(cx); |
|
1576 } |
|
1577 |
|
1578 // This is called before any other location that requires |
|
1579 // sObjectClass, so compute it here. We assume that nobody has had a |
|
1580 // chance to monkey around with proto's prototype chain before this. |
|
1581 if (!sObjectClass) { |
|
1582 FindObjectClass(cx, proto); |
|
1583 NS_ASSERTION(sObjectClass && !strcmp(sObjectClass->name, "Object"), |
|
1584 "Incorrect object class!"); |
|
1585 } |
|
1586 |
|
1587 #ifdef DEBUG |
|
1588 JS::Rooted<JSObject*> proto2(cx); |
|
1589 JS_GetPrototype(cx, proto, &proto2); |
|
1590 NS_ASSERTION(proto2 && JS_GetClass(proto2) == sObjectClass, |
|
1591 "Hmm, somebody did something evil?"); |
|
1592 #endif |
|
1593 |
|
1594 #ifdef DEBUG |
|
1595 if (mData->mHasClassInterface && mData->mProtoChainInterface && |
|
1596 mData->mProtoChainInterface != &NS_GET_IID(nsISupports)) { |
|
1597 nsCOMPtr<nsIInterfaceInfoManager> |
|
1598 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); |
|
1599 |
|
1600 if (iim) { |
|
1601 nsCOMPtr<nsIInterfaceInfo> if_info; |
|
1602 iim->GetInfoForIID(mData->mProtoChainInterface, |
|
1603 getter_AddRefs(if_info)); |
|
1604 |
|
1605 if (if_info) { |
|
1606 nsXPIDLCString name; |
|
1607 if_info->GetName(getter_Copies(name)); |
|
1608 NS_ASSERTION(nsCRT::strcmp(CutPrefix(name), mData->mName) == 0, |
|
1609 "Class name and proto chain interface name mismatch!"); |
|
1610 } |
|
1611 } |
|
1612 } |
|
1613 #endif |
|
1614 |
|
1615 // Make prototype delegation work correctly. Consider if a site sets |
|
1616 // HTMLElement.prototype.foopy = function () { ... } Now, calling |
|
1617 // document.body.foopy() needs to ensure that looking up foopy on |
|
1618 // document.body's prototype will find the right function. |
|
1619 JS::Rooted<JSObject*> global(cx, ::JS_GetGlobalForObject(cx, proto)); |
|
1620 |
|
1621 // Only do this if the global object is a window. |
|
1622 // XXX Is there a better way to check this? |
|
1623 nsISupports *globalNative = XPConnect()->GetNativeOfWrapper(cx, global); |
|
1624 nsCOMPtr<nsPIDOMWindow> piwin = do_QueryInterface(globalNative); |
|
1625 if (!piwin) { |
|
1626 return NS_OK; |
|
1627 } |
|
1628 |
|
1629 nsGlobalWindow *win = nsGlobalWindow::FromSupports(globalNative); |
|
1630 if (win->IsClosedOrClosing()) { |
|
1631 return NS_OK; |
|
1632 } |
|
1633 |
|
1634 // If the window is in a different compartment than the global object, then |
|
1635 // it's likely that global is a sandbox object whose prototype is a window. |
|
1636 // Don't do anything in this case. |
|
1637 if (win->FastGetGlobalJSObject() && |
|
1638 js::GetObjectCompartment(global) != js::GetObjectCompartment(win->FastGetGlobalJSObject())) { |
|
1639 return NS_OK; |
|
1640 } |
|
1641 |
|
1642 if (win->IsOuterWindow()) { |
|
1643 // XXXjst: Do security checks here when we remove the security |
|
1644 // checks on the inner window. |
|
1645 |
|
1646 win = win->GetCurrentInnerWindowInternal(); |
|
1647 |
|
1648 if (!win || !(global = win->GetGlobalJSObject()) || |
|
1649 win->IsClosedOrClosing()) { |
|
1650 return NS_OK; |
|
1651 } |
|
1652 } |
|
1653 |
|
1654 // Don't overwrite a property set by content. |
|
1655 bool contentDefinedProperty; |
|
1656 if (!::JS_AlreadyHasOwnUCProperty(cx, global, reinterpret_cast<const jschar*>(mData->mNameUTF16), |
|
1657 NS_strlen(mData->mNameUTF16), |
|
1658 &contentDefinedProperty)) { |
|
1659 return NS_ERROR_FAILURE; |
|
1660 } |
|
1661 |
|
1662 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
1663 NS_ENSURE_TRUE(nameSpaceManager, NS_OK); |
|
1664 |
|
1665 JS::Rooted<JSPropertyDescriptor> desc(cx); |
|
1666 nsresult rv = ResolvePrototype(sXPConnect, win, cx, global, mData->mNameUTF16, |
|
1667 mData, nullptr, nameSpaceManager, proto, |
|
1668 &desc); |
|
1669 NS_ENSURE_SUCCESS(rv, rv); |
|
1670 if (!contentDefinedProperty && desc.object() && !desc.value().isUndefined() && |
|
1671 !JS_DefineUCProperty(cx, global, mData->mNameUTF16, |
|
1672 NS_strlen(mData->mNameUTF16), |
|
1673 desc.value(), desc.getter(), desc.setter(), |
|
1674 desc.attributes())) { |
|
1675 return NS_ERROR_UNEXPECTED; |
|
1676 } |
|
1677 |
|
1678 return NS_OK; |
|
1679 } |
|
1680 |
|
1681 // static |
|
1682 nsIClassInfo * |
|
1683 NS_GetDOMClassInfoInstance(nsDOMClassInfoID aID) |
|
1684 { |
|
1685 if (aID >= eDOMClassInfoIDCount) { |
|
1686 NS_ERROR("Bad ID!"); |
|
1687 |
|
1688 return nullptr; |
|
1689 } |
|
1690 |
|
1691 if (!nsDOMClassInfo::sIsInitialized) { |
|
1692 nsresult rv = nsDOMClassInfo::Init(); |
|
1693 |
|
1694 NS_ENSURE_SUCCESS(rv, nullptr); |
|
1695 } |
|
1696 |
|
1697 if (!sClassInfoData[aID].mCachedClassInfo) { |
|
1698 nsDOMClassInfoData& data = sClassInfoData[aID]; |
|
1699 |
|
1700 data.mCachedClassInfo = data.u.mConstructorFptr(&data); |
|
1701 NS_ENSURE_TRUE(data.mCachedClassInfo, nullptr); |
|
1702 |
|
1703 NS_ADDREF(data.mCachedClassInfo); |
|
1704 } |
|
1705 |
|
1706 NS_ASSERTION(!IS_EXTERNAL(sClassInfoData[aID].mCachedClassInfo), |
|
1707 "This is bad, internal class marked as external!"); |
|
1708 |
|
1709 return sClassInfoData[aID].mCachedClassInfo; |
|
1710 } |
|
1711 |
|
1712 // static |
|
1713 nsIClassInfo * |
|
1714 nsDOMClassInfo::GetClassInfoInstance(nsDOMClassInfoData* aData) |
|
1715 { |
|
1716 NS_ASSERTION(IS_EXTERNAL(aData->mCachedClassInfo) |
|
1717 || !aData->mCachedClassInfo, |
|
1718 "This is bad, external class marked as internal!"); |
|
1719 |
|
1720 if (!aData->mCachedClassInfo) { |
|
1721 if (aData->u.mExternalConstructorFptr) { |
|
1722 aData->mCachedClassInfo = |
|
1723 aData->u.mExternalConstructorFptr(aData->mName); |
|
1724 } else { |
|
1725 aData->mCachedClassInfo = nsDOMGenericSH::doCreate(aData); |
|
1726 } |
|
1727 NS_ENSURE_TRUE(aData->mCachedClassInfo, nullptr); |
|
1728 |
|
1729 NS_ADDREF(aData->mCachedClassInfo); |
|
1730 aData->mCachedClassInfo = MARK_EXTERNAL(aData->mCachedClassInfo); |
|
1731 } |
|
1732 |
|
1733 return GET_CLEAN_CI_PTR(aData->mCachedClassInfo); |
|
1734 } |
|
1735 |
|
1736 |
|
1737 // static |
|
1738 void |
|
1739 nsDOMClassInfo::ShutDown() |
|
1740 { |
|
1741 if (sClassInfoData[0].u.mConstructorFptr) { |
|
1742 uint32_t i; |
|
1743 |
|
1744 for (i = 0; i < eDOMClassInfoIDCount; i++) { |
|
1745 NS_IF_RELEASE(sClassInfoData[i].mCachedClassInfo); |
|
1746 } |
|
1747 } |
|
1748 |
|
1749 sLocation_id = JSID_VOID; |
|
1750 sConstructor_id = JSID_VOID; |
|
1751 sLength_id = JSID_VOID; |
|
1752 sItem_id = JSID_VOID; |
|
1753 sEnumerate_id = JSID_VOID; |
|
1754 sTop_id = JSID_VOID; |
|
1755 sDocument_id = JSID_VOID; |
|
1756 sWrappedJSObject_id = JSID_VOID; |
|
1757 |
|
1758 NS_IF_RELEASE(sXPConnect); |
|
1759 NS_IF_RELEASE(sSecMan); |
|
1760 sIsInitialized = false; |
|
1761 } |
|
1762 |
|
1763 // Window helper |
|
1764 |
|
1765 NS_IMETHODIMP |
|
1766 nsWindowSH::PreCreate(nsISupports *nativeObj, JSContext *cx, |
|
1767 JSObject *globalObj, JSObject **parentObj) |
|
1768 { |
|
1769 // Normally ::PreCreate() is used to give XPConnect the parent |
|
1770 // object for the object that's being wrapped, this parent object is |
|
1771 // set as the parent of the wrapper and it's also used to find the |
|
1772 // right scope for the object being wrapped. Now, in the case of the |
|
1773 // global object the wrapper shouldn't have a parent but we supply |
|
1774 // one here anyway (the global object itself) and this will be used |
|
1775 // by XPConnect only to find the right scope, once the scope is |
|
1776 // found XPConnect will find the existing wrapper (which always |
|
1777 // exists since it's created on window construction), since an |
|
1778 // existing wrapper is found the parent we supply here is ignored |
|
1779 // after the wrapper is found. |
|
1780 |
|
1781 nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryInterface(nativeObj)); |
|
1782 NS_ASSERTION(sgo, "nativeObj not a global object!"); |
|
1783 |
|
1784 nsGlobalWindow *win = nsGlobalWindow::FromSupports(nativeObj); |
|
1785 NS_ASSERTION(win->IsInnerWindow(), "Should be inner window."); |
|
1786 |
|
1787 // We sometimes get a disconnected window during file api test. :-( |
|
1788 if (!win->GetOuterWindowInternal()) |
|
1789 return NS_ERROR_FAILURE; |
|
1790 |
|
1791 // If we're bootstrapping, we don't have a JS object yet. |
|
1792 if (win->GetOuterWindowInternal()->IsCreatingInnerWindow()) |
|
1793 return NS_OK; |
|
1794 |
|
1795 return SetParentToWindow(win, parentObj); |
|
1796 } |
|
1797 |
|
1798 NS_IMETHODIMP |
|
1799 nsWindowSH::PostCreatePrototype(JSContext* aCx, JSObject* aProto) |
|
1800 { |
|
1801 JS::Rooted<JSObject*> proto(aCx, aProto); |
|
1802 |
|
1803 nsresult rv = nsDOMClassInfo::PostCreatePrototype(aCx, proto); |
|
1804 NS_ENSURE_SUCCESS(rv, rv); |
|
1805 |
|
1806 // We should probably move this into the CreateInterfaceObjects for Window |
|
1807 // once it is on WebIDL bindings. |
|
1808 WindowNamedPropertiesHandler::Install(aCx, proto); |
|
1809 return NS_OK; |
|
1810 } |
|
1811 |
|
1812 NS_IMETHODIMP |
|
1813 nsWindowSH::PostCreate(nsIXPConnectWrappedNative *wrapper, |
|
1814 JSContext *cx, JSObject *obj) |
|
1815 { |
|
1816 JS::Rooted<JSObject*> window(cx, obj); |
|
1817 |
|
1818 #ifdef DEBUG |
|
1819 nsCOMPtr<nsIScriptGlobalObject> sgo(do_QueryWrappedNative(wrapper)); |
|
1820 |
|
1821 NS_ASSERTION(sgo && sgo->GetGlobalJSObject() == obj, |
|
1822 "Multiple wrappers created for global object!"); |
|
1823 #endif |
|
1824 |
|
1825 const NativeProperties* windowProperties = |
|
1826 WindowBinding::sNativePropertyHooks->mNativeProperties.regular; |
|
1827 const NativeProperties* eventTargetProperties = |
|
1828 EventTargetBinding::sNativePropertyHooks->mNativeProperties.regular; |
|
1829 |
|
1830 return DefineWebIDLBindingPropertiesOnXPCObject(cx, window, windowProperties, true) && |
|
1831 DefineWebIDLBindingPropertiesOnXPCObject(cx, window, eventTargetProperties, true) ? |
|
1832 NS_OK : NS_ERROR_FAILURE; |
|
1833 } |
|
1834 |
|
1835 struct ResolveGlobalNameClosure |
|
1836 { |
|
1837 JSContext* cx; |
|
1838 JS::Handle<JSObject*> obj; |
|
1839 bool* retval; |
|
1840 }; |
|
1841 |
|
1842 static PLDHashOperator |
|
1843 ResolveGlobalName(const nsAString& aName, |
|
1844 const nsGlobalNameStruct& aNameStruct, |
|
1845 void* aClosure) |
|
1846 { |
|
1847 ResolveGlobalNameClosure* closure = |
|
1848 static_cast<ResolveGlobalNameClosure*>(aClosure); |
|
1849 JS::Rooted<JS::Value> dummy(closure->cx); |
|
1850 bool ok = JS_LookupUCProperty(closure->cx, closure->obj, |
|
1851 aName.BeginReading(), aName.Length(), |
|
1852 &dummy); |
|
1853 if (!ok) { |
|
1854 *closure->retval = false; |
|
1855 return PL_DHASH_STOP; |
|
1856 } |
|
1857 return PL_DHASH_NEXT; |
|
1858 } |
|
1859 |
|
1860 NS_IMETHODIMP |
|
1861 nsWindowSH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
1862 JSObject *aObj, bool *_retval) |
|
1863 { |
|
1864 JS::Rooted<JSObject*> obj(cx, aObj); |
|
1865 if (!xpc::WrapperFactory::IsXrayWrapper(obj)) { |
|
1866 *_retval = JS_EnumerateStandardClasses(cx, obj); |
|
1867 if (!*_retval) { |
|
1868 return NS_OK; |
|
1869 } |
|
1870 |
|
1871 // Now resolve everything from the namespace manager |
|
1872 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
1873 if (!nameSpaceManager) { |
|
1874 NS_ERROR("Can't get namespace manager."); |
|
1875 return NS_ERROR_UNEXPECTED; |
|
1876 } |
|
1877 ResolveGlobalNameClosure closure = { cx, obj, _retval }; |
|
1878 nameSpaceManager->EnumerateGlobalNames(ResolveGlobalName, &closure); |
|
1879 } |
|
1880 |
|
1881 return NS_OK; |
|
1882 } |
|
1883 |
|
1884 static nsDOMConstructorFunc |
|
1885 FindConstructorFunc(const nsDOMClassInfoData *aDOMClassInfoData) |
|
1886 { |
|
1887 for (uint32_t i = 0; i < ArrayLength(kConstructorFuncMap); ++i) { |
|
1888 if (&sClassInfoData[kConstructorFuncMap[i].mDOMClassInfoID] == |
|
1889 aDOMClassInfoData) { |
|
1890 return kConstructorFuncMap[i].mConstructorFunc; |
|
1891 } |
|
1892 } |
|
1893 return nullptr; |
|
1894 } |
|
1895 |
|
1896 static nsresult |
|
1897 BaseStubConstructor(nsIWeakReference* aWeakOwner, |
|
1898 const nsGlobalNameStruct *name_struct, JSContext *cx, |
|
1899 JS::Handle<JSObject*> obj, const JS::CallArgs &args) |
|
1900 { |
|
1901 MOZ_ASSERT(obj); |
|
1902 |
|
1903 nsresult rv; |
|
1904 nsCOMPtr<nsISupports> native; |
|
1905 if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
1906 const nsDOMClassInfoData* ci_data = |
|
1907 &sClassInfoData[name_struct->mDOMClassInfoID]; |
|
1908 nsDOMConstructorFunc func = FindConstructorFunc(ci_data); |
|
1909 if (func) { |
|
1910 rv = func(getter_AddRefs(native)); |
|
1911 } else { |
|
1912 rv = NS_ERROR_NOT_AVAILABLE; |
|
1913 } |
|
1914 } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) { |
|
1915 native = do_CreateInstance(name_struct->mCID, &rv); |
|
1916 } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) { |
|
1917 native = do_CreateInstance(name_struct->mAlias->mCID, &rv); |
|
1918 } else { |
|
1919 native = do_CreateInstance(*name_struct->mData->mConstructorCID, &rv); |
|
1920 } |
|
1921 if (NS_FAILED(rv)) { |
|
1922 NS_ERROR("Failed to create the object"); |
|
1923 return rv; |
|
1924 } |
|
1925 |
|
1926 nsCOMPtr<nsIJSNativeInitializer> initializer(do_QueryInterface(native)); |
|
1927 nsCOMPtr<nsIDOMGlobalObjectConstructor> constructor(do_QueryInterface(native)); |
|
1928 if (initializer || constructor) { |
|
1929 // Initialize object using the current inner window, but only if |
|
1930 // the caller can access it. |
|
1931 nsCOMPtr<nsPIDOMWindow> owner = do_QueryReferent(aWeakOwner); |
|
1932 nsPIDOMWindow* outerWindow = owner ? owner->GetOuterWindow() : nullptr; |
|
1933 nsPIDOMWindow* currentInner = |
|
1934 outerWindow ? outerWindow->GetCurrentInnerWindow() : nullptr; |
|
1935 if (!currentInner || |
|
1936 (owner != currentInner && |
|
1937 !nsContentUtils::CanCallerAccess(currentInner))) { |
|
1938 return NS_ERROR_DOM_SECURITY_ERR; |
|
1939 } |
|
1940 |
|
1941 if (initializer) { |
|
1942 rv = initializer->Initialize(currentInner, cx, obj, args); |
|
1943 if (NS_FAILED(rv)) { |
|
1944 return rv; |
|
1945 } |
|
1946 } else { |
|
1947 nsCOMPtr<nsIXPConnectWrappedJS> wrappedJS = do_QueryInterface(native); |
|
1948 |
|
1949 JS::Rooted<JSObject*> thisObject(cx, wrappedJS->GetJSObject()); |
|
1950 if (!thisObject) { |
|
1951 return NS_ERROR_UNEXPECTED; |
|
1952 } |
|
1953 |
|
1954 nsCxPusher pusher; |
|
1955 pusher.Push(cx); |
|
1956 |
|
1957 JSAutoCompartment ac(cx, thisObject); |
|
1958 |
|
1959 JS::Rooted<JS::Value> funval(cx); |
|
1960 if (!JS_GetProperty(cx, thisObject, "constructor", &funval) || |
|
1961 !funval.isObject()) { |
|
1962 return NS_ERROR_UNEXPECTED; |
|
1963 } |
|
1964 |
|
1965 // Check if the object is even callable. |
|
1966 NS_ENSURE_STATE(JS_ObjectIsCallable(cx, &funval.toObject())); |
|
1967 { |
|
1968 // wrap parameters in the target compartment |
|
1969 // we also pass in the calling window as the first argument |
|
1970 unsigned argc = args.length() + 1; |
|
1971 JS::AutoValueVector argv(cx); |
|
1972 if (!argv.resize(argc)) { |
|
1973 return NS_ERROR_OUT_OF_MEMORY; |
|
1974 } |
|
1975 |
|
1976 nsCOMPtr<nsIDOMWindow> currentWin(do_GetInterface(currentInner)); |
|
1977 rv = WrapNative(cx, currentWin, &NS_GET_IID(nsIDOMWindow), |
|
1978 true, argv.handleAt(0)); |
|
1979 |
|
1980 for (size_t i = 1; i < argc; ++i) { |
|
1981 argv[i] = args[i - 1]; |
|
1982 if (!JS_WrapValue(cx, argv.handleAt(i))) |
|
1983 return NS_ERROR_FAILURE; |
|
1984 } |
|
1985 |
|
1986 JS::Rooted<JS::Value> frval(cx); |
|
1987 bool ret = JS_CallFunctionValue(cx, thisObject, funval, argv, &frval); |
|
1988 |
|
1989 if (!ret) { |
|
1990 return NS_ERROR_FAILURE; |
|
1991 } |
|
1992 } |
|
1993 } |
|
1994 } |
|
1995 |
|
1996 js::AssertSameCompartment(cx, obj); |
|
1997 return WrapNative(cx, native, true, args.rval()); |
|
1998 } |
|
1999 |
|
2000 static nsresult |
|
2001 DefineInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj, const nsIID *aIID) |
|
2002 { |
|
2003 nsCOMPtr<nsIInterfaceInfoManager> |
|
2004 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); |
|
2005 NS_ENSURE_TRUE(iim, NS_ERROR_UNEXPECTED); |
|
2006 |
|
2007 nsCOMPtr<nsIInterfaceInfo> if_info; |
|
2008 |
|
2009 nsresult rv = iim->GetInfoForIID(aIID, getter_AddRefs(if_info)); |
|
2010 NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && if_info, rv); |
|
2011 |
|
2012 uint16_t constant_count; |
|
2013 |
|
2014 if_info->GetConstantCount(&constant_count); |
|
2015 |
|
2016 if (!constant_count) { |
|
2017 return NS_OK; |
|
2018 } |
|
2019 |
|
2020 nsCOMPtr<nsIInterfaceInfo> parent_if_info; |
|
2021 |
|
2022 rv = if_info->GetParent(getter_AddRefs(parent_if_info)); |
|
2023 NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && parent_if_info, rv); |
|
2024 |
|
2025 uint16_t parent_constant_count, i; |
|
2026 parent_if_info->GetConstantCount(&parent_constant_count); |
|
2027 |
|
2028 JS::Rooted<JS::Value> v(cx); |
|
2029 for (i = parent_constant_count; i < constant_count; i++) { |
|
2030 const nsXPTConstant *c = nullptr; |
|
2031 |
|
2032 rv = if_info->GetConstant(i, &c); |
|
2033 NS_ENSURE_TRUE(NS_SUCCEEDED(rv) && c, rv); |
|
2034 |
|
2035 uint16_t type = c->GetType().TagPart(); |
|
2036 |
|
2037 v.setUndefined(); |
|
2038 switch (type) { |
|
2039 case nsXPTType::T_I8: |
|
2040 case nsXPTType::T_U8: |
|
2041 { |
|
2042 v.setInt32(c->GetValue()->val.u8); |
|
2043 break; |
|
2044 } |
|
2045 case nsXPTType::T_I16: |
|
2046 case nsXPTType::T_U16: |
|
2047 { |
|
2048 v.setInt32(c->GetValue()->val.u16); |
|
2049 break; |
|
2050 } |
|
2051 case nsXPTType::T_I32: |
|
2052 { |
|
2053 v = JS_NumberValue(c->GetValue()->val.i32); |
|
2054 break; |
|
2055 } |
|
2056 case nsXPTType::T_U32: |
|
2057 { |
|
2058 v = JS_NumberValue(c->GetValue()->val.u32); |
|
2059 break; |
|
2060 } |
|
2061 default: |
|
2062 { |
|
2063 #ifdef DEBUG |
|
2064 NS_ERROR("Non-numeric constant found in interface."); |
|
2065 #endif |
|
2066 continue; |
|
2067 } |
|
2068 } |
|
2069 |
|
2070 if (!::JS_DefineProperty(cx, obj, c->GetName(), v, |
|
2071 JSPROP_ENUMERATE | JSPROP_READONLY | |
|
2072 JSPROP_PERMANENT, |
|
2073 JS_PropertyStub, JS_StrictPropertyStub)) { |
|
2074 return NS_ERROR_UNEXPECTED; |
|
2075 } |
|
2076 } |
|
2077 |
|
2078 return NS_OK; |
|
2079 } |
|
2080 |
|
2081 class nsDOMConstructor MOZ_FINAL : public nsIDOMDOMConstructor |
|
2082 { |
|
2083 protected: |
|
2084 nsDOMConstructor(const char16_t* aName, |
|
2085 bool aIsConstructable, |
|
2086 nsPIDOMWindow* aOwner) |
|
2087 : mClassName(aName), |
|
2088 mConstructable(aIsConstructable), |
|
2089 mWeakOwner(do_GetWeakReference(aOwner)) |
|
2090 { |
|
2091 } |
|
2092 |
|
2093 public: |
|
2094 |
|
2095 static nsresult Create(const char16_t* aName, |
|
2096 const nsDOMClassInfoData* aData, |
|
2097 const nsGlobalNameStruct* aNameStruct, |
|
2098 nsPIDOMWindow* aOwner, |
|
2099 nsDOMConstructor** aResult); |
|
2100 |
|
2101 NS_DECL_ISUPPORTS |
|
2102 NS_DECL_NSIDOMDOMCONSTRUCTOR |
|
2103 |
|
2104 nsresult PreCreate(JSContext *cx, JSObject *globalObj, JSObject **parentObj); |
|
2105 |
|
2106 nsresult Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
2107 JS::Handle<JSObject*> obj, const JS::CallArgs &args, |
|
2108 bool *_retval); |
|
2109 |
|
2110 nsresult HasInstance(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
2111 JS::Handle<JSObject*> obj, const jsval &val, bool *bp, |
|
2112 bool *_retval); |
|
2113 |
|
2114 nsresult ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj); |
|
2115 |
|
2116 private: |
|
2117 const nsGlobalNameStruct *GetNameStruct() |
|
2118 { |
|
2119 if (!mClassName) { |
|
2120 NS_ERROR("Can't get name"); |
|
2121 return nullptr; |
|
2122 } |
|
2123 |
|
2124 const nsGlobalNameStruct *nameStruct; |
|
2125 #ifdef DEBUG |
|
2126 nsresult rv = |
|
2127 #endif |
|
2128 GetNameStruct(nsDependentString(mClassName), &nameStruct); |
|
2129 |
|
2130 NS_ASSERTION(NS_FAILED(rv) || nameStruct, "Name isn't in hash."); |
|
2131 |
|
2132 return nameStruct; |
|
2133 } |
|
2134 |
|
2135 static nsresult GetNameStruct(const nsAString& aName, |
|
2136 const nsGlobalNameStruct **aNameStruct) |
|
2137 { |
|
2138 *aNameStruct = nullptr; |
|
2139 |
|
2140 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
2141 if (!nameSpaceManager) { |
|
2142 NS_ERROR("Can't get namespace manager."); |
|
2143 return NS_ERROR_UNEXPECTED; |
|
2144 } |
|
2145 |
|
2146 *aNameStruct = nameSpaceManager->LookupName(aName); |
|
2147 |
|
2148 // Return NS_OK here, aName just isn't a DOM class but nothing failed. |
|
2149 return NS_OK; |
|
2150 } |
|
2151 |
|
2152 static bool IsConstructable(const nsDOMClassInfoData *aData) |
|
2153 { |
|
2154 if (IS_EXTERNAL(aData->mCachedClassInfo)) { |
|
2155 const nsExternalDOMClassInfoData* data = |
|
2156 static_cast<const nsExternalDOMClassInfoData*>(aData); |
|
2157 return data->mConstructorCID != nullptr; |
|
2158 } |
|
2159 |
|
2160 return FindConstructorFunc(aData); |
|
2161 } |
|
2162 static bool IsConstructable(const nsGlobalNameStruct *aNameStruct) |
|
2163 { |
|
2164 return |
|
2165 (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor && |
|
2166 IsConstructable(&sClassInfoData[aNameStruct->mDOMClassInfoID])) || |
|
2167 (aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo && |
|
2168 IsConstructable(aNameStruct->mData)) || |
|
2169 aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructor || |
|
2170 aNameStruct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias; |
|
2171 } |
|
2172 |
|
2173 const char16_t* mClassName; |
|
2174 const bool mConstructable; |
|
2175 nsWeakPtr mWeakOwner; |
|
2176 }; |
|
2177 |
|
2178 //static |
|
2179 nsresult |
|
2180 nsDOMConstructor::Create(const char16_t* aName, |
|
2181 const nsDOMClassInfoData* aData, |
|
2182 const nsGlobalNameStruct* aNameStruct, |
|
2183 nsPIDOMWindow* aOwner, |
|
2184 nsDOMConstructor** aResult) |
|
2185 { |
|
2186 *aResult = nullptr; |
|
2187 // Prevent creating a constructor if aOwner is inner window which doesn't have |
|
2188 // an outer window. If the outer window doesn't have an inner window or the |
|
2189 // caller can't access the outer window's current inner window then try to use |
|
2190 // the owner (so long as it is, in fact, an inner window). If that doesn't |
|
2191 // work then prevent creation also. |
|
2192 nsPIDOMWindow* outerWindow = aOwner->GetOuterWindow(); |
|
2193 nsPIDOMWindow* currentInner = |
|
2194 outerWindow ? outerWindow->GetCurrentInnerWindow() : aOwner; |
|
2195 if (!currentInner || |
|
2196 (aOwner != currentInner && |
|
2197 !nsContentUtils::CanCallerAccess(currentInner) && |
|
2198 !(currentInner = aOwner)->IsInnerWindow())) { |
|
2199 return NS_ERROR_DOM_SECURITY_ERR; |
|
2200 } |
|
2201 |
|
2202 bool constructable = aNameStruct ? |
|
2203 IsConstructable(aNameStruct) : |
|
2204 IsConstructable(aData); |
|
2205 |
|
2206 *aResult = new nsDOMConstructor(aName, constructable, currentInner); |
|
2207 NS_ENSURE_TRUE(*aResult, NS_ERROR_OUT_OF_MEMORY); |
|
2208 NS_ADDREF(*aResult); |
|
2209 return NS_OK; |
|
2210 } |
|
2211 |
|
2212 NS_IMPL_ADDREF(nsDOMConstructor) |
|
2213 NS_IMPL_RELEASE(nsDOMConstructor) |
|
2214 NS_INTERFACE_MAP_BEGIN(nsDOMConstructor) |
|
2215 NS_INTERFACE_MAP_ENTRY(nsIDOMDOMConstructor) |
|
2216 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
2217 if (aIID.Equals(NS_GET_IID(nsIClassInfo))) { |
|
2218 #ifdef DEBUG |
|
2219 { |
|
2220 const nsGlobalNameStruct *name_struct = GetNameStruct(); |
|
2221 NS_ASSERTION(!name_struct || |
|
2222 mConstructable == IsConstructable(name_struct), |
|
2223 "Can't change constructability dynamically!"); |
|
2224 } |
|
2225 #endif |
|
2226 foundInterface = |
|
2227 NS_GetDOMClassInfoInstance(mConstructable ? |
|
2228 eDOMClassInfo_DOMConstructor_id : |
|
2229 eDOMClassInfo_DOMPrototype_id); |
|
2230 if (!foundInterface) { |
|
2231 *aInstancePtr = nullptr; |
|
2232 return NS_ERROR_OUT_OF_MEMORY; |
|
2233 } |
|
2234 } else |
|
2235 NS_INTERFACE_MAP_END |
|
2236 |
|
2237 nsresult |
|
2238 nsDOMConstructor::PreCreate(JSContext *cx, JSObject *globalObj, JSObject **parentObj) |
|
2239 { |
|
2240 nsCOMPtr<nsPIDOMWindow> owner(do_QueryReferent(mWeakOwner)); |
|
2241 if (!owner) { |
|
2242 // Can't do anything. |
|
2243 return NS_OK; |
|
2244 } |
|
2245 |
|
2246 nsGlobalWindow *win = static_cast<nsGlobalWindow *>(owner.get()); |
|
2247 return SetParentToWindow(win, parentObj); |
|
2248 } |
|
2249 |
|
2250 nsresult |
|
2251 nsDOMConstructor::Construct(nsIXPConnectWrappedNative *wrapper, JSContext * cx, |
|
2252 JS::Handle<JSObject*> obj, const JS::CallArgs &args, |
|
2253 bool *_retval) |
|
2254 { |
|
2255 MOZ_ASSERT(obj); |
|
2256 |
|
2257 const nsGlobalNameStruct *name_struct = GetNameStruct(); |
|
2258 NS_ENSURE_TRUE(name_struct, NS_ERROR_FAILURE); |
|
2259 |
|
2260 if (!IsConstructable(name_struct)) { |
|
2261 // ignore return value, we return false anyway |
|
2262 return NS_ERROR_DOM_NOT_SUPPORTED_ERR; |
|
2263 } |
|
2264 |
|
2265 return BaseStubConstructor(mWeakOwner, name_struct, cx, obj, args); |
|
2266 } |
|
2267 |
|
2268 nsresult |
|
2269 nsDOMConstructor::HasInstance(nsIXPConnectWrappedNative *wrapper, |
|
2270 JSContext * cx, JS::Handle<JSObject*> obj, |
|
2271 const jsval &v, bool *bp, bool *_retval) |
|
2272 |
|
2273 { |
|
2274 // No need to look these up in the hash. |
|
2275 *bp = false; |
|
2276 if (JSVAL_IS_PRIMITIVE(v)) { |
|
2277 return NS_OK; |
|
2278 } |
|
2279 |
|
2280 JS::Rooted<JSObject*> dom_obj(cx, v.toObjectOrNull()); |
|
2281 NS_ASSERTION(dom_obj, "nsDOMConstructor::HasInstance couldn't get object"); |
|
2282 |
|
2283 // This might not be the right object, if there are wrappers. Unwrap if we can. |
|
2284 JSObject *wrapped_obj = js::CheckedUnwrap(dom_obj, /* stopAtOuter = */ false); |
|
2285 if (wrapped_obj) |
|
2286 dom_obj = wrapped_obj; |
|
2287 |
|
2288 const JSClass *dom_class = JS_GetClass(dom_obj); |
|
2289 if (!dom_class) { |
|
2290 NS_ERROR("nsDOMConstructor::HasInstance can't get class."); |
|
2291 return NS_ERROR_UNEXPECTED; |
|
2292 } |
|
2293 |
|
2294 const nsGlobalNameStruct *name_struct; |
|
2295 nsresult rv = GetNameStruct(NS_ConvertASCIItoUTF16(dom_class->name), &name_struct); |
|
2296 if (NS_FAILED(rv)) { |
|
2297 return rv; |
|
2298 } |
|
2299 |
|
2300 if (!name_struct) { |
|
2301 // This isn't a normal DOM object, see if this constructor lives on its |
|
2302 // prototype chain. |
|
2303 JS::Rooted<JS::Value> val(cx); |
|
2304 if (!JS_GetProperty(cx, obj, "prototype", &val)) { |
|
2305 return NS_ERROR_UNEXPECTED; |
|
2306 } |
|
2307 |
|
2308 if (JSVAL_IS_PRIMITIVE(val)) { |
|
2309 return NS_OK; |
|
2310 } |
|
2311 |
|
2312 JS::Rooted<JSObject*> dot_prototype(cx, val.toObjectOrNull()); |
|
2313 |
|
2314 JS::Rooted<JSObject*> proto(cx, dom_obj); |
|
2315 for (;;) { |
|
2316 if (!JS_GetPrototype(cx, proto, &proto)) { |
|
2317 return NS_ERROR_UNEXPECTED; |
|
2318 } |
|
2319 if (!proto) { |
|
2320 break; |
|
2321 } |
|
2322 if (proto == dot_prototype) { |
|
2323 *bp = true; |
|
2324 break; |
|
2325 } |
|
2326 } |
|
2327 |
|
2328 return NS_OK; |
|
2329 } |
|
2330 |
|
2331 if (name_struct->mType != nsGlobalNameStruct::eTypeClassConstructor && |
|
2332 name_struct->mType != nsGlobalNameStruct::eTypeExternalClassInfo && |
|
2333 name_struct->mType != nsGlobalNameStruct::eTypeExternalConstructorAlias) { |
|
2334 // Doesn't have DOM interfaces. |
|
2335 return NS_OK; |
|
2336 } |
|
2337 |
|
2338 const nsGlobalNameStruct *class_name_struct = GetNameStruct(); |
|
2339 NS_ENSURE_TRUE(class_name_struct, NS_ERROR_FAILURE); |
|
2340 |
|
2341 if (name_struct == class_name_struct) { |
|
2342 *bp = true; |
|
2343 |
|
2344 return NS_OK; |
|
2345 } |
|
2346 |
|
2347 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
2348 NS_ASSERTION(nameSpaceManager, "Can't get namespace manager?"); |
|
2349 |
|
2350 const nsIID *class_iid; |
|
2351 if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface || |
|
2352 class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) { |
|
2353 class_iid = &class_name_struct->mIID; |
|
2354 } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2355 class_iid = |
|
2356 sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface; |
|
2357 } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
2358 class_iid = class_name_struct->mData->mProtoChainInterface; |
|
2359 } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) { |
|
2360 const nsGlobalNameStruct* alias_struct = |
|
2361 nameSpaceManager->GetConstructorProto(class_name_struct); |
|
2362 if (!alias_struct) { |
|
2363 NS_ERROR("Couldn't get constructor prototype."); |
|
2364 return NS_ERROR_UNEXPECTED; |
|
2365 } |
|
2366 |
|
2367 if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2368 class_iid = |
|
2369 sClassInfoData[alias_struct->mDOMClassInfoID].mProtoChainInterface; |
|
2370 } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
2371 class_iid = alias_struct->mData->mProtoChainInterface; |
|
2372 } else { |
|
2373 NS_ERROR("Expected eTypeClassConstructor or eTypeExternalClassInfo."); |
|
2374 return NS_ERROR_UNEXPECTED; |
|
2375 } |
|
2376 } else { |
|
2377 *bp = false; |
|
2378 |
|
2379 return NS_OK; |
|
2380 } |
|
2381 |
|
2382 if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) { |
|
2383 name_struct = nameSpaceManager->GetConstructorProto(name_struct); |
|
2384 if (!name_struct) { |
|
2385 NS_ERROR("Couldn't get constructor prototype."); |
|
2386 return NS_ERROR_UNEXPECTED; |
|
2387 } |
|
2388 } |
|
2389 |
|
2390 NS_ASSERTION(name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor || |
|
2391 name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo, |
|
2392 "The constructor was set up with a struct of the wrong type."); |
|
2393 |
|
2394 const nsDOMClassInfoData *ci_data = nullptr; |
|
2395 if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor && |
|
2396 name_struct->mDOMClassInfoID >= 0) { |
|
2397 ci_data = &sClassInfoData[name_struct->mDOMClassInfoID]; |
|
2398 } else if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
2399 ci_data = name_struct->mData; |
|
2400 } |
|
2401 |
|
2402 nsCOMPtr<nsIInterfaceInfoManager> |
|
2403 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); |
|
2404 if (!iim) { |
|
2405 NS_ERROR("nsDOMConstructor::HasInstance can't get interface info mgr."); |
|
2406 return NS_ERROR_UNEXPECTED; |
|
2407 } |
|
2408 |
|
2409 nsCOMPtr<nsIInterfaceInfo> if_info; |
|
2410 uint32_t count = 0; |
|
2411 const nsIID* class_interface; |
|
2412 while ((class_interface = ci_data->mInterfaces[count++])) { |
|
2413 if (class_iid->Equals(*class_interface)) { |
|
2414 *bp = true; |
|
2415 |
|
2416 return NS_OK; |
|
2417 } |
|
2418 |
|
2419 iim->GetInfoForIID(class_interface, getter_AddRefs(if_info)); |
|
2420 if (!if_info) { |
|
2421 NS_ERROR("nsDOMConstructor::HasInstance can't get interface info."); |
|
2422 return NS_ERROR_UNEXPECTED; |
|
2423 } |
|
2424 |
|
2425 if_info->HasAncestor(class_iid, bp); |
|
2426 |
|
2427 if (*bp) { |
|
2428 return NS_OK; |
|
2429 } |
|
2430 } |
|
2431 |
|
2432 return NS_OK; |
|
2433 } |
|
2434 |
|
2435 nsresult |
|
2436 nsDOMConstructor::ResolveInterfaceConstants(JSContext *cx, JS::Handle<JSObject*> obj) |
|
2437 { |
|
2438 const nsGlobalNameStruct *class_name_struct = GetNameStruct(); |
|
2439 if (!class_name_struct) |
|
2440 return NS_ERROR_UNEXPECTED; |
|
2441 |
|
2442 const nsIID *class_iid; |
|
2443 if (class_name_struct->mType == nsGlobalNameStruct::eTypeInterface || |
|
2444 class_name_struct->mType == nsGlobalNameStruct::eTypeClassProto) { |
|
2445 class_iid = &class_name_struct->mIID; |
|
2446 } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2447 class_iid = |
|
2448 sClassInfoData[class_name_struct->mDOMClassInfoID].mProtoChainInterface; |
|
2449 } else if (class_name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
2450 class_iid = class_name_struct->mData->mProtoChainInterface; |
|
2451 } else { |
|
2452 return NS_OK; |
|
2453 } |
|
2454 |
|
2455 nsresult rv = DefineInterfaceConstants(cx, obj, class_iid); |
|
2456 NS_ENSURE_SUCCESS(rv, rv); |
|
2457 |
|
2458 return NS_OK; |
|
2459 } |
|
2460 |
|
2461 NS_IMETHODIMP |
|
2462 nsDOMConstructor::ToString(nsAString &aResult) |
|
2463 { |
|
2464 aResult.AssignLiteral("[object "); |
|
2465 aResult.Append(mClassName); |
|
2466 aResult.Append(char16_t(']')); |
|
2467 |
|
2468 return NS_OK; |
|
2469 } |
|
2470 |
|
2471 |
|
2472 static nsresult |
|
2473 GetXPCProto(nsIXPConnect *aXPConnect, JSContext *cx, nsGlobalWindow *aWin, |
|
2474 const nsGlobalNameStruct *aNameStruct, |
|
2475 nsIXPConnectJSObjectHolder **aProto) |
|
2476 { |
|
2477 NS_ASSERTION(aNameStruct->mType == |
|
2478 nsGlobalNameStruct::eTypeClassConstructor || |
|
2479 aNameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo, |
|
2480 "Wrong type!"); |
|
2481 |
|
2482 nsCOMPtr<nsIClassInfo> ci; |
|
2483 if (aNameStruct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2484 int32_t id = aNameStruct->mDOMClassInfoID; |
|
2485 NS_ABORT_IF_FALSE(id >= 0, "Negative DOM classinfo?!?"); |
|
2486 |
|
2487 nsDOMClassInfoID ci_id = (nsDOMClassInfoID)id; |
|
2488 |
|
2489 ci = NS_GetDOMClassInfoInstance(ci_id); |
|
2490 |
|
2491 // In most cases we want to find the wrapped native prototype in |
|
2492 // aWin's scope and use that prototype for |
|
2493 // ClassName.prototype. But in the case where we're setting up |
|
2494 // "Window.prototype" or "ChromeWindow.prototype" we want to do |
|
2495 // the look up in aWin's outer window's scope since the inner |
|
2496 // window's wrapped native prototype comes from the outer |
|
2497 // window's scope. |
|
2498 if (ci_id == eDOMClassInfo_Window_id || |
|
2499 ci_id == eDOMClassInfo_ModalContentWindow_id || |
|
2500 ci_id == eDOMClassInfo_ChromeWindow_id) { |
|
2501 nsGlobalWindow *scopeWindow = aWin->GetOuterWindowInternal(); |
|
2502 |
|
2503 if (scopeWindow) { |
|
2504 aWin = scopeWindow; |
|
2505 } |
|
2506 } |
|
2507 } |
|
2508 else { |
|
2509 ci = nsDOMClassInfo::GetClassInfoInstance(aNameStruct->mData); |
|
2510 } |
|
2511 NS_ENSURE_TRUE(ci, NS_ERROR_UNEXPECTED); |
|
2512 |
|
2513 nsresult rv = |
|
2514 aXPConnect->GetWrappedNativePrototype(cx, aWin->GetGlobalJSObject(), ci, |
|
2515 aProto); |
|
2516 NS_ENSURE_SUCCESS(rv, rv); |
|
2517 |
|
2518 JS::Rooted<JSObject*> proto_obj(cx, (*aProto)->GetJSObject()); |
|
2519 if (!JS_WrapObject(cx, &proto_obj)) { |
|
2520 return NS_ERROR_FAILURE; |
|
2521 } |
|
2522 |
|
2523 NS_IF_RELEASE(*aProto); |
|
2524 return aXPConnect->HoldObject(cx, proto_obj, aProto); |
|
2525 } |
|
2526 |
|
2527 // Either ci_data must be non-null or name_struct must be non-null and of type |
|
2528 // eTypeClassProto. |
|
2529 static nsresult |
|
2530 ResolvePrototype(nsIXPConnect *aXPConnect, nsGlobalWindow *aWin, JSContext *cx, |
|
2531 JS::Handle<JSObject*> obj, const char16_t *name, |
|
2532 const nsDOMClassInfoData *ci_data, |
|
2533 const nsGlobalNameStruct *name_struct, |
|
2534 nsScriptNameSpaceManager *nameSpaceManager, |
|
2535 JSObject* aDot_prototype, |
|
2536 JS::MutableHandle<JSPropertyDescriptor> ctorDesc) |
|
2537 { |
|
2538 JS::Rooted<JSObject*> dot_prototype(cx, aDot_prototype); |
|
2539 NS_ASSERTION(ci_data || |
|
2540 (name_struct && |
|
2541 name_struct->mType == nsGlobalNameStruct::eTypeClassProto), |
|
2542 "Wrong type or missing ci_data!"); |
|
2543 |
|
2544 nsRefPtr<nsDOMConstructor> constructor; |
|
2545 nsresult rv = nsDOMConstructor::Create(name, ci_data, name_struct, aWin, |
|
2546 getter_AddRefs(constructor)); |
|
2547 NS_ENSURE_SUCCESS(rv, rv); |
|
2548 |
|
2549 JS::Rooted<JS::Value> v(cx); |
|
2550 |
|
2551 js::AssertSameCompartment(cx, obj); |
|
2552 rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor), |
|
2553 false, &v); |
|
2554 NS_ENSURE_SUCCESS(rv, rv); |
|
2555 |
|
2556 FillPropertyDescriptor(ctorDesc, obj, 0, v); |
|
2557 // And make sure we wrap the value into the right compartment. Note that we |
|
2558 // do this with ctorDesc.value(), not with v, because we need v to be in the |
|
2559 // right compartment (that of the reflector of |constructor|) below. |
|
2560 if (!JS_WrapValue(cx, ctorDesc.value())) { |
|
2561 return NS_ERROR_UNEXPECTED; |
|
2562 } |
|
2563 |
|
2564 JS::Rooted<JSObject*> class_obj(cx, &v.toObject()); |
|
2565 |
|
2566 const nsIID *primary_iid = &NS_GET_IID(nsISupports); |
|
2567 |
|
2568 if (!ci_data) { |
|
2569 primary_iid = &name_struct->mIID; |
|
2570 } |
|
2571 else if (ci_data->mProtoChainInterface) { |
|
2572 primary_iid = ci_data->mProtoChainInterface; |
|
2573 } |
|
2574 |
|
2575 nsCOMPtr<nsIInterfaceInfo> if_info; |
|
2576 nsCOMPtr<nsIInterfaceInfo> parent; |
|
2577 const char *class_parent_name = nullptr; |
|
2578 |
|
2579 if (!primary_iid->Equals(NS_GET_IID(nsISupports))) { |
|
2580 JSAutoCompartment ac(cx, class_obj); |
|
2581 |
|
2582 rv = DefineInterfaceConstants(cx, class_obj, primary_iid); |
|
2583 NS_ENSURE_SUCCESS(rv, rv); |
|
2584 |
|
2585 nsCOMPtr<nsIInterfaceInfoManager> |
|
2586 iim(do_GetService(NS_INTERFACEINFOMANAGER_SERVICE_CONTRACTID)); |
|
2587 NS_ENSURE_TRUE(iim, NS_ERROR_NOT_AVAILABLE); |
|
2588 |
|
2589 iim->GetInfoForIID(primary_iid, getter_AddRefs(if_info)); |
|
2590 NS_ENSURE_TRUE(if_info, NS_ERROR_UNEXPECTED); |
|
2591 |
|
2592 const nsIID *iid = nullptr; |
|
2593 |
|
2594 if (ci_data && !ci_data->mHasClassInterface) { |
|
2595 if_info->GetIIDShared(&iid); |
|
2596 } else { |
|
2597 if_info->GetParent(getter_AddRefs(parent)); |
|
2598 NS_ENSURE_TRUE(parent, NS_ERROR_UNEXPECTED); |
|
2599 |
|
2600 parent->GetIIDShared(&iid); |
|
2601 } |
|
2602 |
|
2603 if (iid) { |
|
2604 if (!iid->Equals(NS_GET_IID(nsISupports))) { |
|
2605 if (ci_data && !ci_data->mHasClassInterface) { |
|
2606 // If the class doesn't have a class interface the primary |
|
2607 // interface is the interface that should be |
|
2608 // constructor.prototype.__proto__. |
|
2609 |
|
2610 if_info->GetNameShared(&class_parent_name); |
|
2611 } else { |
|
2612 // If the class does have a class interface (or there's no |
|
2613 // real class for this name) then the parent of the |
|
2614 // primary interface is what we want on |
|
2615 // constructor.prototype.__proto__. |
|
2616 |
|
2617 NS_ASSERTION(parent, "Whoa, this is bad, null parent here!"); |
|
2618 |
|
2619 parent->GetNameShared(&class_parent_name); |
|
2620 } |
|
2621 } |
|
2622 } |
|
2623 } |
|
2624 |
|
2625 { |
|
2626 JS::Rooted<JSObject*> winobj(cx, aWin->FastGetGlobalJSObject()); |
|
2627 |
|
2628 JS::Rooted<JSObject*> proto(cx); |
|
2629 |
|
2630 if (class_parent_name) { |
|
2631 JSAutoCompartment ac(cx, winobj); |
|
2632 |
|
2633 JS::Rooted<JS::Value> val(cx); |
|
2634 if (!JS_LookupProperty(cx, winobj, CutPrefix(class_parent_name), &val)) { |
|
2635 return NS_ERROR_UNEXPECTED; |
|
2636 } |
|
2637 |
|
2638 if (val.isObject()) { |
|
2639 JS::Rooted<JSObject*> obj(cx, &val.toObject()); |
|
2640 if (!JS_LookupProperty(cx, obj, "prototype", &val)) { |
|
2641 return NS_ERROR_UNEXPECTED; |
|
2642 } |
|
2643 |
|
2644 if (val.isObject()) { |
|
2645 proto = &val.toObject(); |
|
2646 } |
|
2647 } |
|
2648 } |
|
2649 |
|
2650 if (dot_prototype) { |
|
2651 JSAutoCompartment ac(cx, dot_prototype); |
|
2652 JS::Rooted<JSObject*> xpc_proto_proto(cx); |
|
2653 if (!::JS_GetPrototype(cx, dot_prototype, &xpc_proto_proto)) { |
|
2654 return NS_ERROR_UNEXPECTED; |
|
2655 } |
|
2656 |
|
2657 if (proto && |
|
2658 (!xpc_proto_proto || |
|
2659 JS_GetClass(xpc_proto_proto) == sObjectClass)) { |
|
2660 if (!JS_WrapObject(cx, &proto) || |
|
2661 !JS_SetPrototype(cx, dot_prototype, proto)) { |
|
2662 return NS_ERROR_UNEXPECTED; |
|
2663 } |
|
2664 } |
|
2665 } else { |
|
2666 JSAutoCompartment ac(cx, winobj); |
|
2667 if (!proto) { |
|
2668 proto = JS_GetObjectPrototype(cx, winobj); |
|
2669 } |
|
2670 dot_prototype = ::JS_NewObjectWithUniqueType(cx, |
|
2671 &sDOMConstructorProtoClass, |
|
2672 proto, |
|
2673 winobj); |
|
2674 NS_ENSURE_TRUE(dot_prototype, NS_ERROR_OUT_OF_MEMORY); |
|
2675 } |
|
2676 } |
|
2677 |
|
2678 v = OBJECT_TO_JSVAL(dot_prototype); |
|
2679 |
|
2680 JSAutoCompartment ac(cx, class_obj); |
|
2681 |
|
2682 // Per ECMA, the prototype property is {DontEnum, DontDelete, ReadOnly} |
|
2683 if (!JS_WrapValue(cx, &v) || |
|
2684 !JS_DefineProperty(cx, class_obj, "prototype", v, |
|
2685 JSPROP_PERMANENT | JSPROP_READONLY, |
|
2686 JS_PropertyStub, JS_StrictPropertyStub)) { |
|
2687 return NS_ERROR_UNEXPECTED; |
|
2688 } |
|
2689 |
|
2690 return NS_OK; |
|
2691 } |
|
2692 |
|
2693 static bool |
|
2694 OldBindingConstructorEnabled(const nsGlobalNameStruct *aStruct, |
|
2695 nsGlobalWindow *aWin, JSContext *cx) |
|
2696 { |
|
2697 MOZ_ASSERT(aStruct->mType == nsGlobalNameStruct::eTypeProperty || |
|
2698 aStruct->mType == nsGlobalNameStruct::eTypeClassConstructor || |
|
2699 aStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfo); |
|
2700 |
|
2701 // Don't expose chrome only constructors to content windows. |
|
2702 if (aStruct->mChromeOnly) { |
|
2703 bool expose; |
|
2704 if (aStruct->mAllowXBL) { |
|
2705 expose = IsChromeOrXBL(cx, nullptr); |
|
2706 } else { |
|
2707 expose = nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal()); |
|
2708 } |
|
2709 |
|
2710 if (!expose) { |
|
2711 return false; |
|
2712 } |
|
2713 } |
|
2714 |
|
2715 // Don't expose CSSSupportsRule unless @supports processing is enabled. |
|
2716 if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSSupportsRule_id) { |
|
2717 if (!CSSSupportsRule::PrefEnabled()) { |
|
2718 return false; |
|
2719 } |
|
2720 } |
|
2721 |
|
2722 // Don't expose CSSFontFeatureValuesRule unless the pref is enabled |
|
2723 if (aStruct->mDOMClassInfoID == eDOMClassInfo_CSSFontFeatureValuesRule_id) { |
|
2724 return nsCSSFontFeatureValuesRule::PrefEnabled(); |
|
2725 } |
|
2726 |
|
2727 return true; |
|
2728 } |
|
2729 |
|
2730 bool |
|
2731 nsWindowSH::NameStructEnabled(JSContext* aCx, nsGlobalWindow *aWin, |
|
2732 const nsAString& aName, |
|
2733 const nsGlobalNameStruct& aNameStruct) |
|
2734 { |
|
2735 const nsGlobalNameStruct* nameStruct = &aNameStruct; |
|
2736 if (nameStruct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) { |
|
2737 nsresult rv = GetExternalClassInfo(GetNameSpaceManager(), aName, nameStruct, |
|
2738 &nameStruct); |
|
2739 if (NS_FAILED(rv) || !nameStruct) { |
|
2740 return false; |
|
2741 } |
|
2742 } |
|
2743 |
|
2744 return (nameStruct->mType != nsGlobalNameStruct::eTypeProperty && |
|
2745 nameStruct->mType != nsGlobalNameStruct::eTypeClassConstructor && |
|
2746 nameStruct->mType != nsGlobalNameStruct::eTypeExternalClassInfo) || |
|
2747 OldBindingConstructorEnabled(nameStruct, aWin, aCx); |
|
2748 } |
|
2749 |
|
2750 #ifdef RELEASE_BUILD |
|
2751 #define USE_CONTROLLERS_SHIM |
|
2752 #endif |
|
2753 |
|
2754 #ifdef USE_CONTROLLERS_SHIM |
|
2755 static const JSClass ControllersShimClass = { |
|
2756 "XULControllers", 0, |
|
2757 JS_PropertyStub, JS_DeletePropertyStub, JS_PropertyStub, JS_StrictPropertyStub, |
|
2758 JS_EnumerateStub, JS_ResolveStub, JS_ConvertStub, nullptr |
|
2759 }; |
|
2760 #endif |
|
2761 |
|
2762 // static |
|
2763 nsresult |
|
2764 nsWindowSH::GlobalResolve(nsGlobalWindow *aWin, JSContext *cx, |
|
2765 JS::Handle<JSObject*> obj, JS::Handle<jsid> id, |
|
2766 JS::MutableHandle<JSPropertyDescriptor> desc) |
|
2767 { |
|
2768 #ifdef USE_CONTROLLERS_SHIM |
|
2769 if (id == XPCJSRuntime::Get()->GetStringID(XPCJSRuntime::IDX_CONTROLLERS) && |
|
2770 !xpc::IsXrayWrapper(obj) && |
|
2771 !nsContentUtils::IsSystemPrincipal(aWin->GetPrincipal())) |
|
2772 { |
|
2773 if (aWin->GetDoc()) { |
|
2774 aWin->GetDoc()->WarnOnceAbout(nsIDocument::eWindow_Controllers); |
|
2775 } |
|
2776 JS::Rooted<JSObject*> shim(cx, JS_NewObject(cx, &ControllersShimClass, JS::NullPtr(), obj)); |
|
2777 if (NS_WARN_IF(!shim)) { |
|
2778 return NS_ERROR_OUT_OF_MEMORY; |
|
2779 } |
|
2780 FillPropertyDescriptor(desc, obj, JS::ObjectValue(*shim), /* readOnly = */ false); |
|
2781 return NS_OK; |
|
2782 } |
|
2783 #endif |
|
2784 |
|
2785 nsScriptNameSpaceManager *nameSpaceManager = GetNameSpaceManager(); |
|
2786 NS_ENSURE_TRUE(nameSpaceManager, NS_ERROR_NOT_INITIALIZED); |
|
2787 |
|
2788 nsDependentJSString name(id); |
|
2789 |
|
2790 const char16_t *class_name = nullptr; |
|
2791 const nsGlobalNameStruct *name_struct = |
|
2792 nameSpaceManager->LookupName(name, &class_name); |
|
2793 |
|
2794 if (!name_struct) { |
|
2795 return NS_OK; |
|
2796 } |
|
2797 |
|
2798 // The class_name had better match our name |
|
2799 MOZ_ASSERT(name.Equals(class_name)); |
|
2800 |
|
2801 NS_ENSURE_TRUE(class_name, NS_ERROR_UNEXPECTED); |
|
2802 |
|
2803 nsresult rv = NS_OK; |
|
2804 |
|
2805 if (name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfoCreator) { |
|
2806 rv = GetExternalClassInfo(nameSpaceManager, name, name_struct, |
|
2807 &name_struct); |
|
2808 if (NS_FAILED(rv) || !name_struct) { |
|
2809 return rv; |
|
2810 } |
|
2811 } |
|
2812 |
|
2813 if (name_struct->mType == nsGlobalNameStruct::eTypeNewDOMBinding || |
|
2814 name_struct->mType == nsGlobalNameStruct::eTypeInterface || |
|
2815 name_struct->mType == nsGlobalNameStruct::eTypeClassProto || |
|
2816 name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2817 // Lookup new DOM bindings. |
|
2818 DefineInterface getOrCreateInterfaceObject = |
|
2819 name_struct->mDefineDOMInterface; |
|
2820 if (getOrCreateInterfaceObject) { |
|
2821 if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor && |
|
2822 !OldBindingConstructorEnabled(name_struct, aWin, cx)) { |
|
2823 return NS_OK; |
|
2824 } |
|
2825 |
|
2826 ConstructorEnabled* checkEnabledForScope = name_struct->mConstructorEnabled; |
|
2827 // We do the enabled check on the current compartment of cx, but for the |
|
2828 // actual object we pass in the underlying object in the Xray case. That |
|
2829 // way the callee can decide whether to allow access based on the caller |
|
2830 // or the window being touched. |
|
2831 JS::Rooted<JSObject*> global(cx, |
|
2832 js::CheckedUnwrap(obj, /* stopAtOuter = */ false)); |
|
2833 if (!global) { |
|
2834 return NS_ERROR_DOM_SECURITY_ERR; |
|
2835 } |
|
2836 if (checkEnabledForScope && !checkEnabledForScope(cx, global)) { |
|
2837 return NS_OK; |
|
2838 } |
|
2839 |
|
2840 // The DOM constructor resolve machinery interacts with Xrays in tricky |
|
2841 // ways, and there are some asymmetries that are important to understand. |
|
2842 // |
|
2843 // In the regular (non-Xray) case, we only want to resolve constructors |
|
2844 // once (so that if they're deleted, they don't reappear). We do this by |
|
2845 // stashing the constructor in a slot on the global, such that we can see |
|
2846 // during resolve whether we've created it already. This is rather |
|
2847 // memory-intensive, so we don't try to maintain these semantics when |
|
2848 // manipulating a global over Xray (so the properties just re-resolve if |
|
2849 // they've been deleted). |
|
2850 // |
|
2851 // Unfortunately, there's a bit of an impedance-mismatch between the Xray |
|
2852 // and non-Xray machinery. The Xray machinery wants an API that returns a |
|
2853 // JSPropertyDescriptor, so that the resolve hook doesn't have to get |
|
2854 // snared up with trying to define a property on the Xray holder. At the |
|
2855 // same time, the DefineInterface callbacks are set up to define things |
|
2856 // directly on the global. And re-jiggering them to return property |
|
2857 // descriptors is tricky, because some DefineInterface callbacks define |
|
2858 // multiple things (like the Image() alias for HTMLImageElement). |
|
2859 // |
|
2860 // So the setup is as-follows: |
|
2861 // |
|
2862 // * The resolve function takes a JSPropertyDescriptor, but in the |
|
2863 // non-Xray case, callees may define things directly on the global, and |
|
2864 // set the value on the property descriptor to |undefined| to indicate |
|
2865 // that there's nothing more for the caller to do. We assert against |
|
2866 // this behavior in the Xray case. |
|
2867 // |
|
2868 // * We make sure that we do a non-Xray resolve first, so that all the |
|
2869 // slots are set up. In the Xray case, this means unwrapping and doing |
|
2870 // a non-Xray resolve before doing the Xray resolve. |
|
2871 // |
|
2872 // This all could use some grand refactoring, but for now we just limp |
|
2873 // along. |
|
2874 if (xpc::WrapperFactory::IsXrayWrapper(obj)) { |
|
2875 JS::Rooted<JSObject*> interfaceObject(cx); |
|
2876 { |
|
2877 JSAutoCompartment ac(cx, global); |
|
2878 interfaceObject = getOrCreateInterfaceObject(cx, global, id, false); |
|
2879 } |
|
2880 if (NS_WARN_IF(!interfaceObject)) { |
|
2881 return NS_ERROR_FAILURE; |
|
2882 } |
|
2883 if (!JS_WrapObject(cx, &interfaceObject)) { |
|
2884 return NS_ERROR_FAILURE; |
|
2885 } |
|
2886 |
|
2887 FillPropertyDescriptor(desc, obj, 0, JS::ObjectValue(*interfaceObject)); |
|
2888 } else { |
|
2889 JS::Rooted<JSObject*> interfaceObject(cx, |
|
2890 getOrCreateInterfaceObject(cx, obj, id, true)); |
|
2891 if (NS_WARN_IF(!interfaceObject)) { |
|
2892 return NS_ERROR_FAILURE; |
|
2893 } |
|
2894 // We've already defined the property. We indicate this to the caller |
|
2895 // by filling a property descriptor with JS::UndefinedValue() as the |
|
2896 // value. We still have to fill in a property descriptor, though, so |
|
2897 // that the caller knows the property is in fact on this object. It |
|
2898 // doesn't matter what we pass for the "readonly" argument here. |
|
2899 FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false); |
|
2900 } |
|
2901 |
|
2902 return NS_OK; |
|
2903 } |
|
2904 } |
|
2905 |
|
2906 if (name_struct->mType == nsGlobalNameStruct::eTypeInterface) { |
|
2907 // We're resolving a name of a DOM interface for which there is no |
|
2908 // direct DOM class, create a constructor object... |
|
2909 nsRefPtr<nsDOMConstructor> constructor; |
|
2910 rv = nsDOMConstructor::Create(class_name, |
|
2911 nullptr, |
|
2912 name_struct, |
|
2913 static_cast<nsPIDOMWindow*>(aWin), |
|
2914 getter_AddRefs(constructor)); |
|
2915 NS_ENSURE_SUCCESS(rv, rv); |
|
2916 |
|
2917 JS::Rooted<JS::Value> v(cx); |
|
2918 js::AssertSameCompartment(cx, obj); |
|
2919 rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor), |
|
2920 false, &v); |
|
2921 NS_ENSURE_SUCCESS(rv, rv); |
|
2922 |
|
2923 JS::Rooted<JSObject*> class_obj(cx, &v.toObject()); |
|
2924 |
|
2925 // ... and define the constants from the DOM interface on that |
|
2926 // constructor object. |
|
2927 |
|
2928 { |
|
2929 JSAutoCompartment ac(cx, class_obj); |
|
2930 rv = DefineInterfaceConstants(cx, class_obj, &name_struct->mIID); |
|
2931 NS_ENSURE_SUCCESS(rv, rv); |
|
2932 } |
|
2933 |
|
2934 if (!JS_WrapValue(cx, &v)) { |
|
2935 return NS_ERROR_UNEXPECTED; |
|
2936 } |
|
2937 |
|
2938 FillPropertyDescriptor(desc, obj, 0, v); |
|
2939 return NS_OK; |
|
2940 } |
|
2941 |
|
2942 if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor || |
|
2943 name_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
2944 if (!OldBindingConstructorEnabled(name_struct, aWin, cx)) { |
|
2945 return NS_OK; |
|
2946 } |
|
2947 |
|
2948 // Create the XPConnect prototype for our classinfo, PostCreateProto will |
|
2949 // set up the prototype chain. This will go ahead and define things on the |
|
2950 // actual window's global. |
|
2951 nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder; |
|
2952 rv = GetXPCProto(sXPConnect, cx, aWin, name_struct, |
|
2953 getter_AddRefs(proto_holder)); |
|
2954 NS_ENSURE_SUCCESS(rv, rv); |
|
2955 bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); |
|
2956 MOZ_ASSERT_IF(obj != aWin->GetGlobalJSObject(), isXray); |
|
2957 if (!isXray) { |
|
2958 // GetXPCProto already defined the property for us |
|
2959 FillPropertyDescriptor(desc, obj, JS::UndefinedValue(), false); |
|
2960 return NS_OK; |
|
2961 } |
|
2962 |
|
2963 // This is the Xray case. Look up the constructor object for this |
|
2964 // prototype. |
|
2965 JS::Rooted<JSObject*> dot_prototype(cx, proto_holder->GetJSObject()); |
|
2966 NS_ENSURE_STATE(dot_prototype); |
|
2967 |
|
2968 const nsDOMClassInfoData *ci_data; |
|
2969 if (name_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
2970 ci_data = &sClassInfoData[name_struct->mDOMClassInfoID]; |
|
2971 } else { |
|
2972 ci_data = name_struct->mData; |
|
2973 } |
|
2974 |
|
2975 return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data, |
|
2976 name_struct, nameSpaceManager, dot_prototype, |
|
2977 desc); |
|
2978 } |
|
2979 |
|
2980 if (name_struct->mType == nsGlobalNameStruct::eTypeClassProto) { |
|
2981 // We don't have a XPConnect prototype object, let ResolvePrototype create |
|
2982 // one. |
|
2983 return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, nullptr, |
|
2984 name_struct, nameSpaceManager, nullptr, desc); |
|
2985 } |
|
2986 |
|
2987 if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructorAlias) { |
|
2988 const nsGlobalNameStruct *alias_struct = |
|
2989 nameSpaceManager->GetConstructorProto(name_struct); |
|
2990 NS_ENSURE_TRUE(alias_struct, NS_ERROR_UNEXPECTED); |
|
2991 |
|
2992 // We need to use the XPConnect prototype for the DOM class that this |
|
2993 // constructor is an alias for (for example for Image we need the prototype |
|
2994 // for HTMLImageElement). |
|
2995 nsCOMPtr<nsIXPConnectJSObjectHolder> proto_holder; |
|
2996 rv = GetXPCProto(sXPConnect, cx, aWin, alias_struct, |
|
2997 getter_AddRefs(proto_holder)); |
|
2998 NS_ENSURE_SUCCESS(rv, rv); |
|
2999 |
|
3000 JSObject* dot_prototype = proto_holder->GetJSObject(); |
|
3001 NS_ENSURE_STATE(dot_prototype); |
|
3002 |
|
3003 const nsDOMClassInfoData *ci_data; |
|
3004 if (alias_struct->mType == nsGlobalNameStruct::eTypeClassConstructor) { |
|
3005 ci_data = &sClassInfoData[alias_struct->mDOMClassInfoID]; |
|
3006 } else if (alias_struct->mType == nsGlobalNameStruct::eTypeExternalClassInfo) { |
|
3007 ci_data = alias_struct->mData; |
|
3008 } else { |
|
3009 return NS_ERROR_UNEXPECTED; |
|
3010 } |
|
3011 |
|
3012 return ResolvePrototype(sXPConnect, aWin, cx, obj, class_name, ci_data, |
|
3013 name_struct, nameSpaceManager, nullptr, desc); |
|
3014 } |
|
3015 |
|
3016 if (name_struct->mType == nsGlobalNameStruct::eTypeExternalConstructor) { |
|
3017 nsRefPtr<nsDOMConstructor> constructor; |
|
3018 rv = nsDOMConstructor::Create(class_name, nullptr, name_struct, |
|
3019 static_cast<nsPIDOMWindow*>(aWin), |
|
3020 getter_AddRefs(constructor)); |
|
3021 NS_ENSURE_SUCCESS(rv, rv); |
|
3022 |
|
3023 JS::Rooted<JS::Value> val(cx); |
|
3024 js::AssertSameCompartment(cx, obj); |
|
3025 rv = WrapNative(cx, constructor, &NS_GET_IID(nsIDOMDOMConstructor), |
|
3026 true, &val); |
|
3027 NS_ENSURE_SUCCESS(rv, rv); |
|
3028 |
|
3029 NS_ASSERTION(val.isObject(), "Why didn't we get a JSObject?"); |
|
3030 |
|
3031 FillPropertyDescriptor(desc, obj, 0, val); |
|
3032 |
|
3033 return NS_OK; |
|
3034 } |
|
3035 |
|
3036 if (name_struct->mType == nsGlobalNameStruct::eTypeProperty) { |
|
3037 if (!OldBindingConstructorEnabled(name_struct, aWin, cx)) |
|
3038 return NS_OK; |
|
3039 |
|
3040 // Before defining a global property, check for a named subframe of the |
|
3041 // same name. If it exists, we don't want to shadow it. |
|
3042 nsCOMPtr<nsIDOMWindow> childWin = aWin->GetChildWindow(name); |
|
3043 if (childWin) |
|
3044 return NS_OK; |
|
3045 |
|
3046 nsCOMPtr<nsISupports> native(do_CreateInstance(name_struct->mCID, &rv)); |
|
3047 NS_ENSURE_SUCCESS(rv, rv); |
|
3048 |
|
3049 JS::Rooted<JS::Value> prop_val(cx, JS::UndefinedValue()); // Property value. |
|
3050 |
|
3051 nsCOMPtr<nsIDOMGlobalPropertyInitializer> gpi(do_QueryInterface(native)); |
|
3052 if (gpi) { |
|
3053 rv = gpi->Init(aWin, &prop_val); |
|
3054 NS_ENSURE_SUCCESS(rv, rv); |
|
3055 } |
|
3056 |
|
3057 if (JSVAL_IS_PRIMITIVE(prop_val) && !JSVAL_IS_NULL(prop_val)) { |
|
3058 if (aWin->IsOuterWindow()) { |
|
3059 nsGlobalWindow *inner = aWin->GetCurrentInnerWindowInternal(); |
|
3060 NS_ENSURE_TRUE(inner, NS_ERROR_UNEXPECTED); |
|
3061 } |
|
3062 |
|
3063 rv = WrapNative(cx, native, true, &prop_val); |
|
3064 } |
|
3065 |
|
3066 NS_ENSURE_SUCCESS(rv, rv); |
|
3067 |
|
3068 if (!JS_WrapValue(cx, &prop_val)) { |
|
3069 return NS_ERROR_UNEXPECTED; |
|
3070 } |
|
3071 |
|
3072 FillPropertyDescriptor(desc, obj, prop_val, false); |
|
3073 |
|
3074 return NS_OK; |
|
3075 } |
|
3076 |
|
3077 return rv; |
|
3078 } |
|
3079 |
|
3080 template<class Interface> |
|
3081 static nsresult |
|
3082 LocationSetterGuts(JSContext *cx, JSObject *obj, JS::MutableHandle<JS::Value> vp) |
|
3083 { |
|
3084 // This function duplicates some of the logic in XPC_WN_HelperSetProperty |
|
3085 obj = js::CheckedUnwrap(obj, /* stopAtOuter = */ false); |
|
3086 if (!IS_WN_REFLECTOR(obj)) |
|
3087 return NS_ERROR_XPC_BAD_CONVERT_JS; |
|
3088 XPCWrappedNative *wrapper = XPCWrappedNative::Get(obj); |
|
3089 |
|
3090 // The error checks duplicate code in THROW_AND_RETURN_IF_BAD_WRAPPER |
|
3091 NS_ENSURE_TRUE(!wrapper || wrapper->IsValid(), NS_ERROR_XPC_HAS_BEEN_SHUTDOWN); |
|
3092 |
|
3093 nsCOMPtr<Interface> xpcomObj = do_QueryWrappedNative(wrapper, obj); |
|
3094 NS_ENSURE_TRUE(xpcomObj, NS_ERROR_UNEXPECTED); |
|
3095 |
|
3096 nsCOMPtr<nsIDOMLocation> location; |
|
3097 nsresult rv = xpcomObj->GetLocation(getter_AddRefs(location)); |
|
3098 NS_ENSURE_SUCCESS(rv, rv); |
|
3099 |
|
3100 // Grab the value we're being set to before we stomp on |vp| |
|
3101 JS::Rooted<JSString*> val(cx, JS::ToString(cx, vp)); |
|
3102 NS_ENSURE_TRUE(val, NS_ERROR_UNEXPECTED); |
|
3103 |
|
3104 // Make sure |val| stays alive below |
|
3105 JS::Anchor<JSString *> anchor(val); |
|
3106 |
|
3107 // We have to wrap location into vp before null-checking location, to |
|
3108 // avoid assigning the wrong thing into the slot. |
|
3109 rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, vp); |
|
3110 NS_ENSURE_SUCCESS(rv, rv); |
|
3111 |
|
3112 if (!location) { |
|
3113 // Make this a no-op |
|
3114 return NS_OK; |
|
3115 } |
|
3116 |
|
3117 nsDependentJSString depStr; |
|
3118 NS_ENSURE_TRUE(depStr.init(cx, val), NS_ERROR_UNEXPECTED); |
|
3119 |
|
3120 return location->SetHref(depStr); |
|
3121 } |
|
3122 |
|
3123 template<class Interface> |
|
3124 static bool |
|
3125 LocationSetter(JSContext *cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, bool strict, |
|
3126 JS::MutableHandle<JS::Value> vp) |
|
3127 { |
|
3128 nsresult rv = LocationSetterGuts<Interface>(cx, obj, vp); |
|
3129 if (NS_FAILED(rv)) { |
|
3130 xpc::Throw(cx, rv); |
|
3131 return false; |
|
3132 } |
|
3133 |
|
3134 return true; |
|
3135 } |
|
3136 |
|
3137 static bool |
|
3138 LocationSetterUnwrapper(JSContext *cx, JS::Handle<JSObject*> obj_, JS::Handle<jsid> id, |
|
3139 bool strict, JS::MutableHandle<JS::Value> vp) |
|
3140 { |
|
3141 JS::Rooted<JSObject*> obj(cx, obj_); |
|
3142 |
|
3143 JSObject *wrapped = XPCWrapper::UnsafeUnwrapSecurityWrapper(obj); |
|
3144 if (wrapped) { |
|
3145 obj = wrapped; |
|
3146 } |
|
3147 |
|
3148 return LocationSetter<nsIDOMWindow>(cx, obj, id, strict, vp); |
|
3149 } |
|
3150 |
|
3151 NS_IMETHODIMP |
|
3152 nsWindowSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3153 JSObject *obj_, jsid id_, JSObject **objp, |
|
3154 bool *_retval) |
|
3155 { |
|
3156 JS::Rooted<JSObject*> obj(cx, obj_); |
|
3157 JS::Rooted<jsid> id(cx, id_); |
|
3158 |
|
3159 if (!JSID_IS_STRING(id)) { |
|
3160 return NS_OK; |
|
3161 } |
|
3162 |
|
3163 MOZ_ASSERT(*_retval == true); // guaranteed by XPC_WN_Helper_NewResolve |
|
3164 |
|
3165 nsGlobalWindow *win = nsGlobalWindow::FromWrapper(wrapper); |
|
3166 MOZ_ASSERT(win->IsInnerWindow()); |
|
3167 |
|
3168 // Don't resolve standard classes on XrayWrappers, only resolve them if we're |
|
3169 // resolving on the real global object. |
|
3170 bool isXray = xpc::WrapperFactory::IsXrayWrapper(obj); |
|
3171 if (!isXray) { |
|
3172 bool did_resolve = false; |
|
3173 if (!JS_ResolveStandardClass(cx, obj, id, &did_resolve)) { |
|
3174 // Return NS_OK to avoid stomping over the exception that was passed |
|
3175 // down from the ResolveStandardClass call. |
|
3176 *_retval = false; |
|
3177 return NS_OK; |
|
3178 } |
|
3179 |
|
3180 if (did_resolve) { |
|
3181 *objp = obj; |
|
3182 return NS_OK; |
|
3183 } |
|
3184 } |
|
3185 |
|
3186 // WebIDL quickstubs handle location for us, but Xrays don't see those. So if |
|
3187 // we're an Xray, we have to resolve stuff here to make "window.location = |
|
3188 // someString" work. |
|
3189 if (sLocation_id == id && isXray) { |
|
3190 nsCOMPtr<nsIDOMLocation> location; |
|
3191 nsresult rv = win->GetLocation(getter_AddRefs(location)); |
|
3192 NS_ENSURE_SUCCESS(rv, rv); |
|
3193 |
|
3194 JS::Rooted<JS::Value> v(cx); |
|
3195 rv = WrapNative(cx, location, &NS_GET_IID(nsIDOMLocation), true, &v); |
|
3196 NS_ENSURE_SUCCESS(rv, rv); |
|
3197 |
|
3198 bool ok = JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, |
|
3199 LocationSetterUnwrapper, |
|
3200 JSPROP_PERMANENT | JSPROP_ENUMERATE); |
|
3201 |
|
3202 if (!ok) { |
|
3203 return NS_ERROR_FAILURE; |
|
3204 } |
|
3205 |
|
3206 *objp = obj; |
|
3207 |
|
3208 return NS_OK; |
|
3209 } |
|
3210 |
|
3211 // WebIDL quickstubs handle "top" for us, but Xrays don't see those. So if |
|
3212 // we're an Xray and we want "top" to be JSPROP_PERMANENT, we need to resolve |
|
3213 // it here. |
|
3214 if (sTop_id == id && isXray) { |
|
3215 nsCOMPtr<nsIDOMWindow> top; |
|
3216 nsresult rv = win->GetScriptableTop(getter_AddRefs(top)); |
|
3217 NS_ENSURE_SUCCESS(rv, rv); |
|
3218 |
|
3219 JS::Rooted<JS::Value> v(cx); |
|
3220 js::AssertSameCompartment(cx, obj); |
|
3221 rv = WrapNative(cx, top, &NS_GET_IID(nsIDOMWindow), true, &v); |
|
3222 NS_ENSURE_SUCCESS(rv, rv); |
|
3223 |
|
3224 // Hold on to the top window object as a global property so we |
|
3225 // don't need to worry about losing expando properties etc. |
|
3226 if (!JS_DefinePropertyById(cx, obj, id, v, JS_PropertyStub, JS_StrictPropertyStub, |
|
3227 JSPROP_READONLY | JSPROP_PERMANENT | |
|
3228 JSPROP_ENUMERATE)) { |
|
3229 return NS_ERROR_FAILURE; |
|
3230 } |
|
3231 *objp = obj; |
|
3232 |
|
3233 return NS_OK; |
|
3234 } |
|
3235 |
|
3236 if (isXray) { |
|
3237 // We promise to resolve on the underlying object first. That will create |
|
3238 // the actual interface object if needed and store it in a data structure |
|
3239 // hanging off the global. Then our second call will wrap up in an Xray as |
|
3240 // needed. We do things this way because we use the existence of the |
|
3241 // object in that data structure as a flag that indicates that its name |
|
3242 // (and any relevant named constructor names) has been resolved before; |
|
3243 // this allows us to avoid re-resolving in the Xray case if the property is |
|
3244 // deleted by page script. |
|
3245 JS::Rooted<JSObject*> global(cx, |
|
3246 js::UncheckedUnwrap(obj, /* stopAtOuter = */ false)); |
|
3247 JSAutoCompartment ac(cx, global); |
|
3248 JS::Rooted<JSPropertyDescriptor> desc(cx); |
|
3249 if (!win->DoNewResolve(cx, global, id, &desc)) { |
|
3250 return NS_ERROR_FAILURE; |
|
3251 } |
|
3252 // If we have an object here, that means we resolved the property. |
|
3253 // But if the value is undefined, that means that GlobalResolve |
|
3254 // also already defined it, so we don't have to. |
|
3255 if (desc.object() && !desc.value().isUndefined() && |
|
3256 !JS_DefinePropertyById(cx, global, id, desc.value(), |
|
3257 desc.getter(), desc.setter(), |
|
3258 desc.attributes())) { |
|
3259 return NS_ERROR_FAILURE; |
|
3260 } |
|
3261 } |
|
3262 |
|
3263 JS::Rooted<JSPropertyDescriptor> desc(cx); |
|
3264 if (!win->DoNewResolve(cx, obj, id, &desc)) { |
|
3265 return NS_ERROR_FAILURE; |
|
3266 } |
|
3267 if (desc.object()) { |
|
3268 // If we have an object here, that means we resolved the property. |
|
3269 // But if the value is undefined, that means that GlobalResolve |
|
3270 // also already defined it, so we don't have to. Note that in the |
|
3271 // Xray case we should never see undefined. |
|
3272 MOZ_ASSERT_IF(isXray, !desc.value().isUndefined()); |
|
3273 if (!desc.value().isUndefined() && |
|
3274 !JS_DefinePropertyById(cx, obj, id, desc.value(), |
|
3275 desc.getter(), desc.setter(), |
|
3276 desc.attributes())) { |
|
3277 return NS_ERROR_FAILURE; |
|
3278 } |
|
3279 |
|
3280 *objp = obj; |
|
3281 return NS_OK; |
|
3282 } |
|
3283 |
|
3284 if (sDocument_id == id) { |
|
3285 nsCOMPtr<nsIDocument> document = win->GetDoc(); |
|
3286 JS::Rooted<JS::Value> v(cx); |
|
3287 nsresult rv = WrapNative(cx, document, document, |
|
3288 &NS_GET_IID(nsIDOMDocument), &v, false); |
|
3289 NS_ENSURE_SUCCESS(rv, rv); |
|
3290 |
|
3291 // nsIDocument::WrapObject will handle defining the property. |
|
3292 *objp = obj; |
|
3293 |
|
3294 // NB: We need to do this for any Xray wrapper. |
|
3295 if (xpc::WrapperFactory::IsXrayWrapper(obj)) { |
|
3296 *_retval = JS_WrapValue(cx, &v) && |
|
3297 JS_DefineProperty(cx, obj, "document", v, |
|
3298 JSPROP_READONLY | JSPROP_ENUMERATE, |
|
3299 JS_PropertyStub, JS_StrictPropertyStub); |
|
3300 if (!*_retval) { |
|
3301 return NS_ERROR_UNEXPECTED; |
|
3302 } |
|
3303 } |
|
3304 |
|
3305 return NS_OK; |
|
3306 } |
|
3307 |
|
3308 return nsDOMGenericSH::NewResolve(wrapper, cx, obj, id, objp, _retval); |
|
3309 } |
|
3310 |
|
3311 NS_IMETHODIMP |
|
3312 nsWindowSH::OuterObject(nsIXPConnectWrappedNative *wrapper, JSContext * cx, |
|
3313 JSObject * obj, JSObject * *_retval) |
|
3314 { |
|
3315 nsGlobalWindow *origWin = nsGlobalWindow::FromWrapper(wrapper); |
|
3316 nsGlobalWindow *win = origWin->GetOuterWindowInternal(); |
|
3317 |
|
3318 if (!win) { |
|
3319 // If we no longer have an outer window. No code should ever be |
|
3320 // running on a window w/o an outer, which means this hook should |
|
3321 // never be called when we have no outer. But just in case, return |
|
3322 // null to prevent leaking an inner window to code in a different |
|
3323 // window. |
|
3324 *_retval = nullptr; |
|
3325 return NS_ERROR_UNEXPECTED; |
|
3326 } |
|
3327 |
|
3328 JS::Rooted<JSObject*> winObj(cx, win->FastGetGlobalJSObject()); |
|
3329 MOZ_ASSERT(winObj); |
|
3330 |
|
3331 // Note that while |wrapper| is same-compartment with cx, the outer window |
|
3332 // might not be. If we're running script in an inactive scope and evalute |
|
3333 // |this|, the outer window is actually a cross-compartment wrapper. So we |
|
3334 // need to wrap here. |
|
3335 if (!JS_WrapObject(cx, &winObj)) { |
|
3336 *_retval = nullptr; |
|
3337 return NS_ERROR_UNEXPECTED; |
|
3338 } |
|
3339 |
|
3340 *_retval = winObj; |
|
3341 return NS_OK; |
|
3342 } |
|
3343 |
|
3344 NS_IMETHODIMP |
|
3345 nsLocationSH::PreCreate(nsISupports *nativeObj, JSContext *cx, |
|
3346 JSObject *globalObj, JSObject **parentObj) |
|
3347 { |
|
3348 // window.location can be held onto by both evil pages that want to track the |
|
3349 // user's progress on the web and bookmarklets that want to use the location |
|
3350 // object. Parent it to the outer window so that access checks do the Right |
|
3351 // Thing. |
|
3352 *parentObj = globalObj; |
|
3353 |
|
3354 nsCOMPtr<nsIDOMLocation> safeLoc(do_QueryInterface(nativeObj)); |
|
3355 if (!safeLoc) { |
|
3356 // Oops, this wasn't really a location object. This can happen if someone |
|
3357 // tries to use our scriptable helper as a real object and tries to wrap |
|
3358 // it, see bug 319296 |
|
3359 return NS_OK; |
|
3360 } |
|
3361 |
|
3362 nsLocation *loc = (nsLocation *)safeLoc.get(); |
|
3363 nsIDocShell *ds = loc->GetDocShell(); |
|
3364 if (!ds) { |
|
3365 NS_WARNING("Refusing to create a location in the wrong scope"); |
|
3366 return NS_ERROR_UNEXPECTED; |
|
3367 } |
|
3368 |
|
3369 nsCOMPtr<nsIScriptGlobalObject> sgo = do_GetInterface(ds); |
|
3370 if (!sgo) { |
|
3371 NS_WARNING("Refusing to create a location in the wrong scope because the " |
|
3372 "docshell is being destroyed"); |
|
3373 return NS_ERROR_UNEXPECTED; |
|
3374 } |
|
3375 |
|
3376 *parentObj = sgo->GetGlobalJSObject(); |
|
3377 return *parentObj ? NS_OK : NS_ERROR_FAILURE; |
|
3378 } |
|
3379 |
|
3380 NS_IMETHODIMP |
|
3381 nsLocationSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3382 JSObject *obj, jsid aId, jsval *vp, bool *_retval) |
|
3383 { |
|
3384 JS::Rooted<JSObject*> rootedObj(cx, obj); |
|
3385 |
|
3386 // Shadowing protection. This will go away when nsLocation moves to the new |
|
3387 // bindings. |
|
3388 JS::Rooted<jsid> id(cx, aId); |
|
3389 if (wrapper->HasNativeMember(id)) { |
|
3390 JS_ReportError(cx, "Permission denied to shadow native property"); |
|
3391 return NS_ERROR_FAILURE; |
|
3392 } |
|
3393 |
|
3394 nsLocation* location = static_cast<nsLocation*>(GetNative(wrapper, rootedObj)); |
|
3395 location->PreserveWrapper(location); |
|
3396 |
|
3397 return NS_OK; |
|
3398 } |
|
3399 |
|
3400 // EventTarget helper |
|
3401 |
|
3402 NS_IMETHODIMP |
|
3403 nsEventTargetSH::PreCreate(nsISupports *nativeObj, JSContext *cx, |
|
3404 JSObject *aGlobalObj, JSObject **parentObj) |
|
3405 { |
|
3406 JS::Rooted<JSObject*> globalObj(cx, aGlobalObj); |
|
3407 DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(nativeObj); |
|
3408 |
|
3409 nsCOMPtr<nsIScriptGlobalObject> native_parent; |
|
3410 target->GetParentObject(getter_AddRefs(native_parent)); |
|
3411 |
|
3412 *parentObj = native_parent ? native_parent->GetGlobalJSObject() : globalObj; |
|
3413 |
|
3414 return *parentObj ? NS_OK : NS_ERROR_FAILURE; |
|
3415 } |
|
3416 |
|
3417 NS_IMETHODIMP |
|
3418 nsEventTargetSH::AddProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3419 JSObject *obj, jsid id, jsval *vp, bool *_retval) |
|
3420 { |
|
3421 nsEventTargetSH::PreserveWrapper(GetNative(wrapper, obj)); |
|
3422 |
|
3423 return NS_OK; |
|
3424 } |
|
3425 |
|
3426 void |
|
3427 nsEventTargetSH::PreserveWrapper(nsISupports *aNative) |
|
3428 { |
|
3429 DOMEventTargetHelper* target = DOMEventTargetHelper::FromSupports(aNative); |
|
3430 target->PreserveWrapper(aNative); |
|
3431 } |
|
3432 |
|
3433 // Generic array scriptable helper. |
|
3434 |
|
3435 NS_IMETHODIMP |
|
3436 nsGenericArraySH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3437 JSObject *aObj, jsid aId, JSObject **objp, |
|
3438 bool *_retval) |
|
3439 { |
|
3440 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3441 JS::Rooted<jsid> id(cx, aId); |
|
3442 if (id == sLength_id) { |
|
3443 // Bail early; this isn't something we're interested in |
|
3444 return NS_OK; |
|
3445 } |
|
3446 |
|
3447 bool is_number = false; |
|
3448 int32_t n = GetArrayIndexFromId(cx, id, &is_number); |
|
3449 |
|
3450 if (is_number && n >= 0) { |
|
3451 // XXX The following is a cheap optimization to avoid hitting xpconnect to |
|
3452 // get the length. We may want to consider asking our concrete |
|
3453 // implementation for the length, and falling back onto the GetProperty if |
|
3454 // it doesn't provide one. |
|
3455 |
|
3456 uint32_t length; |
|
3457 nsresult rv = GetLength(wrapper, cx, obj, &length); |
|
3458 NS_ENSURE_SUCCESS(rv, rv); |
|
3459 |
|
3460 uint32_t index = uint32_t(n); |
|
3461 if (index < length) { |
|
3462 *_retval = ::JS_DefineElement(cx, obj, index, JSVAL_VOID, nullptr, nullptr, |
|
3463 JSPROP_ENUMERATE | JSPROP_SHARED); |
|
3464 *objp = obj; |
|
3465 } |
|
3466 } |
|
3467 |
|
3468 return NS_OK; |
|
3469 } |
|
3470 |
|
3471 nsresult |
|
3472 nsGenericArraySH::GetLength(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3473 JS::Handle<JSObject*> obj, uint32_t *length) |
|
3474 { |
|
3475 *length = 0; |
|
3476 |
|
3477 JS::Rooted<JS::Value> lenval(cx); |
|
3478 if (!JS_GetProperty(cx, obj, "length", &lenval)) { |
|
3479 return NS_ERROR_UNEXPECTED; |
|
3480 } |
|
3481 |
|
3482 if (!JSVAL_IS_INT(lenval)) { |
|
3483 // This can apparently happen with some sparse array impls falling back |
|
3484 // onto this code. |
|
3485 return NS_OK; |
|
3486 } |
|
3487 |
|
3488 int32_t slen = JSVAL_TO_INT(lenval); |
|
3489 if (slen < 0) { |
|
3490 return NS_OK; |
|
3491 } |
|
3492 |
|
3493 *length = (uint32_t)slen; |
|
3494 |
|
3495 return NS_OK; |
|
3496 } |
|
3497 |
|
3498 NS_IMETHODIMP |
|
3499 nsGenericArraySH::Enumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3500 JSObject *aObj, bool *_retval) |
|
3501 { |
|
3502 // Recursion protection in case someone tries to be smart and call |
|
3503 // the enumerate hook from a user defined .length getter, or |
|
3504 // somesuch. |
|
3505 |
|
3506 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3507 static bool sCurrentlyEnumerating; |
|
3508 |
|
3509 if (sCurrentlyEnumerating) { |
|
3510 // Don't recurse to death. |
|
3511 return NS_OK; |
|
3512 } |
|
3513 |
|
3514 sCurrentlyEnumerating = true; |
|
3515 |
|
3516 JS::Rooted<JS::Value> len_val(cx); |
|
3517 bool ok = ::JS_GetProperty(cx, obj, "length", &len_val); |
|
3518 |
|
3519 if (ok && JSVAL_IS_INT(len_val)) { |
|
3520 int32_t length = JSVAL_TO_INT(len_val); |
|
3521 |
|
3522 for (int32_t i = 0; ok && i < length; ++i) { |
|
3523 ok = ::JS_DefineElement(cx, obj, i, JSVAL_VOID, nullptr, nullptr, |
|
3524 JSPROP_ENUMERATE | JSPROP_SHARED); |
|
3525 } |
|
3526 } |
|
3527 |
|
3528 sCurrentlyEnumerating = false; |
|
3529 |
|
3530 return ok ? NS_OK : NS_ERROR_UNEXPECTED; |
|
3531 } |
|
3532 |
|
3533 // Array scriptable helper |
|
3534 |
|
3535 NS_IMETHODIMP |
|
3536 nsArraySH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3537 JSObject *aObj, jsid aId, jsval *vp, bool *_retval) |
|
3538 { |
|
3539 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3540 JS::Rooted<jsid> id(cx, aId); |
|
3541 bool is_number = false; |
|
3542 int32_t n = GetArrayIndexFromId(cx, id, &is_number); |
|
3543 |
|
3544 nsresult rv = NS_OK; |
|
3545 |
|
3546 if (is_number) { |
|
3547 if (n < 0) { |
|
3548 return NS_ERROR_DOM_INDEX_SIZE_ERR; |
|
3549 } |
|
3550 |
|
3551 // Make sure rv == NS_OK here, so GetItemAt implementations that never fail |
|
3552 // don't have to set rv. |
|
3553 rv = NS_OK; |
|
3554 nsWrapperCache *cache = nullptr; |
|
3555 nsISupports* array_item = |
|
3556 GetItemAt(GetNative(wrapper, obj), n, &cache, &rv); |
|
3557 NS_ENSURE_SUCCESS(rv, rv); |
|
3558 |
|
3559 if (array_item) { |
|
3560 JS::Rooted<JS::Value> rval(cx); |
|
3561 rv = WrapNative(cx, array_item, cache, true, &rval); |
|
3562 NS_ENSURE_SUCCESS(rv, rv); |
|
3563 *vp = rval; |
|
3564 |
|
3565 rv = NS_SUCCESS_I_DID_SOMETHING; |
|
3566 } |
|
3567 } |
|
3568 |
|
3569 return rv; |
|
3570 } |
|
3571 |
|
3572 |
|
3573 // CSSRuleList scriptable helper |
|
3574 |
|
3575 nsISupports* |
|
3576 nsCSSRuleListSH::GetItemAt(nsISupports *aNative, uint32_t aIndex, |
|
3577 nsWrapperCache **aCache, nsresult *aResult) |
|
3578 { |
|
3579 nsICSSRuleList* list = static_cast<nsICSSRuleList*>(aNative); |
|
3580 #ifdef DEBUG |
|
3581 { |
|
3582 nsCOMPtr<nsICSSRuleList> list_qi = do_QueryInterface(aNative); |
|
3583 |
|
3584 // If this assertion fires the QI implementation for the object in |
|
3585 // question doesn't use the nsICSSRuleList pointer as the nsISupports |
|
3586 // pointer. That must be fixed, or we'll crash... |
|
3587 NS_ABORT_IF_FALSE(list_qi == list, "Uh, fix QI!"); |
|
3588 } |
|
3589 #endif |
|
3590 |
|
3591 return list->Item(aIndex); |
|
3592 } |
|
3593 |
|
3594 |
|
3595 // Storage2SH |
|
3596 |
|
3597 // One reason we need a newResolve hook is that in order for |
|
3598 // enumeration of storage object keys to work the keys we're |
|
3599 // enumerating need to exist on the storage object for the JS engine |
|
3600 // to find them. |
|
3601 |
|
3602 NS_IMETHODIMP |
|
3603 nsStorage2SH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3604 JSObject *obj, jsid aId, JSObject **objp, |
|
3605 bool *_retval) |
|
3606 { |
|
3607 JS::Rooted<jsid> id(cx, aId); |
|
3608 if (ObjectIsNativeWrapper(cx, obj)) { |
|
3609 return NS_OK; |
|
3610 } |
|
3611 |
|
3612 JS::Rooted<JSObject*> realObj(cx, wrapper->GetJSObject()); |
|
3613 |
|
3614 JSAutoCompartment ac(cx, realObj); |
|
3615 |
|
3616 // First check to see if the property is defined on our prototype, |
|
3617 // after converting id to a string if it's an integer. |
|
3618 |
|
3619 JS::Rooted<JSString*> jsstr(cx, IdToString(cx, id)); |
|
3620 if (!jsstr) { |
|
3621 return NS_OK; |
|
3622 } |
|
3623 |
|
3624 JS::Rooted<JSObject*> proto(cx); |
|
3625 if (!::JS_GetPrototype(cx, realObj, &proto)) { |
|
3626 return NS_ERROR_FAILURE; |
|
3627 } |
|
3628 bool hasProp; |
|
3629 |
|
3630 if (proto && |
|
3631 (::JS_HasPropertyById(cx, proto, id, &hasProp) && |
|
3632 hasProp)) { |
|
3633 // We found the property we're resolving on the prototype, |
|
3634 // nothing left to do here then. |
|
3635 |
|
3636 return NS_OK; |
|
3637 } |
|
3638 |
|
3639 // We're resolving property that doesn't exist on the prototype, |
|
3640 // check if the key exists in the storage object. |
|
3641 |
|
3642 nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper)); |
|
3643 |
|
3644 nsDependentJSString depStr; |
|
3645 NS_ENSURE_TRUE(depStr.init(cx, jsstr), NS_ERROR_UNEXPECTED); |
|
3646 |
|
3647 // GetItem() will return null if the caller can't access the session |
|
3648 // storage item. |
|
3649 nsAutoString data; |
|
3650 nsresult rv = storage->GetItem(depStr, data); |
|
3651 NS_ENSURE_SUCCESS(rv, rv); |
|
3652 |
|
3653 if (!DOMStringIsNull(data)) { |
|
3654 if (!::JS_DefinePropertyById(cx, realObj, id, JSVAL_VOID, nullptr, |
|
3655 nullptr, JSPROP_ENUMERATE)) { |
|
3656 return NS_ERROR_FAILURE; |
|
3657 } |
|
3658 |
|
3659 *objp = realObj; |
|
3660 } |
|
3661 |
|
3662 return NS_OK; |
|
3663 } |
|
3664 |
|
3665 NS_IMETHODIMP |
|
3666 nsStorage2SH::GetProperty(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3667 JSObject *aObj, jsid aId, jsval *vp, bool *_retval) |
|
3668 { |
|
3669 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3670 JS::Rooted<jsid> id(cx, aId); |
|
3671 nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper)); |
|
3672 NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED); |
|
3673 |
|
3674 JSString* key = IdToString(cx, id); |
|
3675 NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED); |
|
3676 |
|
3677 nsDependentJSString keyStr; |
|
3678 NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED); |
|
3679 |
|
3680 // For native wrappers, do not get random names on storage objects. |
|
3681 if (ObjectIsNativeWrapper(cx, obj)) { |
|
3682 return NS_ERROR_NOT_AVAILABLE; |
|
3683 } |
|
3684 |
|
3685 nsAutoString val; |
|
3686 nsresult rv = storage->GetItem(keyStr, val); |
|
3687 NS_ENSURE_SUCCESS(rv, rv); |
|
3688 |
|
3689 if (DOMStringIsNull(val)) { |
|
3690 // No such key. |
|
3691 *vp = JSVAL_VOID; |
|
3692 } else { |
|
3693 JSString* str = |
|
3694 JS_NewUCStringCopyN(cx, static_cast<const jschar *>(val.get()), |
|
3695 val.Length()); |
|
3696 NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY); |
|
3697 |
|
3698 *vp = STRING_TO_JSVAL(str); |
|
3699 } |
|
3700 |
|
3701 return NS_SUCCESS_I_DID_SOMETHING; |
|
3702 } |
|
3703 |
|
3704 NS_IMETHODIMP |
|
3705 nsStorage2SH::SetProperty(nsIXPConnectWrappedNative *wrapper, |
|
3706 JSContext *cx, JSObject *obj, jsid aId, |
|
3707 jsval *vp, bool *_retval) |
|
3708 { |
|
3709 JS::Rooted<jsid> id(cx, aId); |
|
3710 nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper)); |
|
3711 NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED); |
|
3712 |
|
3713 JSString *key = IdToString(cx, id); |
|
3714 NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED); |
|
3715 |
|
3716 nsDependentJSString keyStr; |
|
3717 NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED); |
|
3718 |
|
3719 JS::Rooted<JS::Value> val(cx, *vp); |
|
3720 JSString *value = JS::ToString(cx, val); |
|
3721 NS_ENSURE_TRUE(value, NS_ERROR_UNEXPECTED); |
|
3722 |
|
3723 nsDependentJSString valueStr; |
|
3724 NS_ENSURE_TRUE(valueStr.init(cx, value), NS_ERROR_UNEXPECTED); |
|
3725 |
|
3726 nsresult rv = storage->SetItem(keyStr, valueStr); |
|
3727 if (NS_SUCCEEDED(rv)) { |
|
3728 rv = NS_SUCCESS_I_DID_SOMETHING; |
|
3729 } |
|
3730 |
|
3731 return rv; |
|
3732 } |
|
3733 |
|
3734 NS_IMETHODIMP |
|
3735 nsStorage2SH::DelProperty(nsIXPConnectWrappedNative *wrapper, |
|
3736 JSContext *cx, JSObject *obj, jsid aId, |
|
3737 bool *_retval) |
|
3738 { |
|
3739 JS::Rooted<jsid> id(cx, aId); |
|
3740 nsCOMPtr<nsIDOMStorage> storage(do_QueryWrappedNative(wrapper)); |
|
3741 NS_ENSURE_TRUE(storage, NS_ERROR_UNEXPECTED); |
|
3742 |
|
3743 JSString *key = IdToString(cx, id); |
|
3744 NS_ENSURE_TRUE(key, NS_ERROR_UNEXPECTED); |
|
3745 |
|
3746 nsDependentJSString keyStr; |
|
3747 NS_ENSURE_TRUE(keyStr.init(cx, key), NS_ERROR_UNEXPECTED); |
|
3748 |
|
3749 nsresult rv = storage->RemoveItem(keyStr); |
|
3750 if (NS_FAILED(rv)) { |
|
3751 return rv; |
|
3752 } |
|
3753 |
|
3754 *_retval = true; |
|
3755 return NS_SUCCESS_I_DID_SOMETHING; |
|
3756 } |
|
3757 |
|
3758 |
|
3759 NS_IMETHODIMP |
|
3760 nsStorage2SH::NewEnumerate(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3761 JSObject *obj, uint32_t enum_op, jsval *statep, |
|
3762 jsid *idp, bool *_retval) |
|
3763 { |
|
3764 if (enum_op == JSENUMERATE_INIT || enum_op == JSENUMERATE_INIT_ALL) { |
|
3765 nsCOMPtr<nsPIDOMStorage> storage(do_QueryWrappedNative(wrapper)); |
|
3766 |
|
3767 // XXXndeakin need to free the keys afterwards |
|
3768 nsTArray<nsString> *keys = storage->GetKeys(); |
|
3769 NS_ENSURE_TRUE(keys, NS_ERROR_OUT_OF_MEMORY); |
|
3770 |
|
3771 *statep = PRIVATE_TO_JSVAL(keys); |
|
3772 |
|
3773 if (idp) { |
|
3774 *idp = INT_TO_JSID(keys->Length()); |
|
3775 } |
|
3776 return NS_OK; |
|
3777 } |
|
3778 |
|
3779 nsTArray<nsString> *keys = |
|
3780 (nsTArray<nsString> *)JSVAL_TO_PRIVATE(*statep); |
|
3781 |
|
3782 if (enum_op == JSENUMERATE_NEXT && keys->Length() != 0) { |
|
3783 nsString& key = keys->ElementAt(0); |
|
3784 JS::Rooted<JSString*> str(cx, JS_NewUCStringCopyN(cx, key.get(), key.Length())); |
|
3785 NS_ENSURE_TRUE(str, NS_ERROR_OUT_OF_MEMORY); |
|
3786 |
|
3787 JS::Rooted<jsid> id(cx); |
|
3788 JS_StringToId(cx, str, &id); |
|
3789 *idp = id; |
|
3790 |
|
3791 keys->RemoveElementAt(0); |
|
3792 |
|
3793 return NS_OK; |
|
3794 } |
|
3795 |
|
3796 // destroy the keys array if we have no keys or if we're done |
|
3797 NS_ABORT_IF_FALSE(enum_op == JSENUMERATE_DESTROY || |
|
3798 (enum_op == JSENUMERATE_NEXT && keys->Length() == 0), |
|
3799 "Bad call from the JS engine"); |
|
3800 delete keys; |
|
3801 |
|
3802 *statep = JSVAL_NULL; |
|
3803 |
|
3804 return NS_OK; |
|
3805 } |
|
3806 |
|
3807 // nsIDOMEventListener::HandleEvent() 'this' converter helper |
|
3808 |
|
3809 NS_INTERFACE_MAP_BEGIN(nsEventListenerThisTranslator) |
|
3810 NS_INTERFACE_MAP_ENTRY(nsIXPCFunctionThisTranslator) |
|
3811 NS_INTERFACE_MAP_ENTRY(nsISupports) |
|
3812 NS_INTERFACE_MAP_END |
|
3813 |
|
3814 |
|
3815 NS_IMPL_ADDREF(nsEventListenerThisTranslator) |
|
3816 NS_IMPL_RELEASE(nsEventListenerThisTranslator) |
|
3817 |
|
3818 |
|
3819 NS_IMETHODIMP |
|
3820 nsEventListenerThisTranslator::TranslateThis(nsISupports *aInitialThis, |
|
3821 nsISupports **_retval) |
|
3822 { |
|
3823 nsCOMPtr<nsIDOMEvent> event(do_QueryInterface(aInitialThis)); |
|
3824 NS_ENSURE_TRUE(event, NS_ERROR_UNEXPECTED); |
|
3825 |
|
3826 nsCOMPtr<EventTarget> target = event->InternalDOMEvent()->GetCurrentTarget(); |
|
3827 target.forget(_retval); |
|
3828 return NS_OK; |
|
3829 } |
|
3830 |
|
3831 NS_IMETHODIMP |
|
3832 nsDOMConstructorSH::PreCreate(nsISupports *nativeObj, JSContext *cx, |
|
3833 JSObject *aGlobalObj, JSObject **parentObj) |
|
3834 { |
|
3835 JS::Rooted<JSObject*> globalObj(cx, aGlobalObj); |
|
3836 nsDOMConstructor *wrapped = static_cast<nsDOMConstructor *>(nativeObj); |
|
3837 |
|
3838 #ifdef DEBUG |
|
3839 { |
|
3840 nsCOMPtr<nsIDOMDOMConstructor> is_constructor = |
|
3841 do_QueryInterface(nativeObj); |
|
3842 NS_ASSERTION(is_constructor, "How did we not get a constructor?"); |
|
3843 } |
|
3844 #endif |
|
3845 |
|
3846 return wrapped->PreCreate(cx, globalObj, parentObj); |
|
3847 } |
|
3848 |
|
3849 NS_IMETHODIMP |
|
3850 nsDOMConstructorSH::NewResolve(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3851 JSObject *aObj, jsid aId, JSObject **objp, |
|
3852 bool *_retval) |
|
3853 { |
|
3854 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3855 JS::Rooted<jsid> id(cx, aId); |
|
3856 // For regular DOM constructors, we have our interface constants defined on |
|
3857 // us by nsWindowSH::GlobalResolve. However, XrayWrappers can't see these |
|
3858 // interface constants (as they look like expando properties) so we have to |
|
3859 // specially resolve those constants here, but only for Xray wrappers. |
|
3860 if (!ObjectIsNativeWrapper(cx, obj)) { |
|
3861 return NS_OK; |
|
3862 } |
|
3863 |
|
3864 JS::Rooted<JSObject*> nativePropsObj(cx, xpc::XrayUtils::GetNativePropertiesObject(cx, obj)); |
|
3865 nsDOMConstructor *wrapped = |
|
3866 static_cast<nsDOMConstructor *>(wrapper->Native()); |
|
3867 nsresult rv = wrapped->ResolveInterfaceConstants(cx, nativePropsObj); |
|
3868 NS_ENSURE_SUCCESS(rv, rv); |
|
3869 |
|
3870 // Now re-lookup the ID to see if we should report back that we resolved the |
|
3871 // looked-for constant. Note that we don't have to worry about infinitely |
|
3872 // recurring back here because the Xray wrapper's holder object doesn't call |
|
3873 // NewResolve hooks. |
|
3874 bool found; |
|
3875 if (!JS_HasPropertyById(cx, nativePropsObj, id, &found)) { |
|
3876 *_retval = false; |
|
3877 return NS_OK; |
|
3878 } |
|
3879 |
|
3880 if (found) { |
|
3881 *objp = obj; |
|
3882 } |
|
3883 return NS_OK; |
|
3884 } |
|
3885 |
|
3886 NS_IMETHODIMP |
|
3887 nsDOMConstructorSH::Call(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3888 JSObject *aObj, const JS::CallArgs &args, bool *_retval) |
|
3889 { |
|
3890 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3891 MOZ_ASSERT(obj); |
|
3892 |
|
3893 nsDOMConstructor *wrapped = |
|
3894 static_cast<nsDOMConstructor *>(wrapper->Native()); |
|
3895 |
|
3896 #ifdef DEBUG |
|
3897 { |
|
3898 nsCOMPtr<nsIDOMDOMConstructor> is_constructor = |
|
3899 do_QueryWrappedNative(wrapper); |
|
3900 NS_ASSERTION(is_constructor, "How did we not get a constructor?"); |
|
3901 } |
|
3902 #endif |
|
3903 |
|
3904 return wrapped->Construct(wrapper, cx, obj, args, _retval); |
|
3905 } |
|
3906 |
|
3907 NS_IMETHODIMP |
|
3908 nsDOMConstructorSH::Construct(nsIXPConnectWrappedNative *wrapper, JSContext *cx, |
|
3909 JSObject *aObj, const JS::CallArgs &args, bool *_retval) |
|
3910 { |
|
3911 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3912 MOZ_ASSERT(obj); |
|
3913 |
|
3914 nsDOMConstructor *wrapped = |
|
3915 static_cast<nsDOMConstructor *>(wrapper->Native()); |
|
3916 |
|
3917 #ifdef DEBUG |
|
3918 { |
|
3919 nsCOMPtr<nsIDOMDOMConstructor> is_constructor = |
|
3920 do_QueryWrappedNative(wrapper); |
|
3921 NS_ASSERTION(is_constructor, "How did we not get a constructor?"); |
|
3922 } |
|
3923 #endif |
|
3924 |
|
3925 return wrapped->Construct(wrapper, cx, obj, args, _retval); |
|
3926 } |
|
3927 |
|
3928 NS_IMETHODIMP |
|
3929 nsDOMConstructorSH::HasInstance(nsIXPConnectWrappedNative *wrapper, |
|
3930 JSContext *cx, JSObject *aObj, JS::Handle<JS::Value> val, |
|
3931 bool *bp, bool *_retval) |
|
3932 { |
|
3933 JS::Rooted<JSObject*> obj(cx, aObj); |
|
3934 nsDOMConstructor *wrapped = |
|
3935 static_cast<nsDOMConstructor *>(wrapper->Native()); |
|
3936 |
|
3937 #ifdef DEBUG |
|
3938 { |
|
3939 nsCOMPtr<nsIDOMDOMConstructor> is_constructor = |
|
3940 do_QueryWrappedNative(wrapper); |
|
3941 NS_ASSERTION(is_constructor, "How did we not get a constructor?"); |
|
3942 } |
|
3943 #endif |
|
3944 |
|
3945 return wrapped->HasInstance(wrapper, cx, obj, val, bp, _retval); |
|
3946 } |
|
3947 |
|
3948 NS_IMETHODIMP |
|
3949 nsNonDOMObjectSH::GetFlags(uint32_t *aFlags) |
|
3950 { |
|
3951 // This is NOT a DOM Object. Use this helper class for cases when you need |
|
3952 // to do something like implement nsISecurityCheckedComponent in a meaningful |
|
3953 // way. |
|
3954 *aFlags = nsIClassInfo::MAIN_THREAD_ONLY | nsIClassInfo::SINGLETON_CLASSINFO; |
|
3955 return NS_OK; |
|
3956 } |