dom/base/nsDOMClassInfo.cpp

Sat, 03 Jan 2015 20:18:00 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Sat, 03 Jan 2015 20:18:00 +0100
branch
TOR_BUG_3246
changeset 7
129ffea94266
permissions
-rw-r--r--

Conditionally enable double key logic according to:
private browsing mode or privacy.thirdparty.isolate preference and
implement in GetCookieStringCommon and FindCookie where it counts...
With some reservations of how to convince FindCookie users to test
condition and pass a nullptr when disabling double key logic.

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

mercurial