dom/base/nsDOMClassInfo.cpp

branch
TOR_BUG_9701
changeset 15
b8a032363ba2
equal deleted inserted replaced
-1:000000000000 0:8b83d78f3be7
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 }

mercurial