Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
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 | } |