Line data Source code
1 : /* THIS FILE IS AUTOGENERATED FROM External.webidl BY Codegen.py - DO NOT EDIT */
2 :
3 : #include "AtomList.h"
4 : #include "ExternalBinding.h"
5 : #include "WrapperFactory.h"
6 : #include "mozilla/OwningNonNull.h"
7 : #include "mozilla/UseCounter.h"
8 : #include "mozilla/dom/BindingUtils.h"
9 : #include "mozilla/dom/DOMJSClass.h"
10 : #include "mozilla/dom/NonRefcountedDOMObject.h"
11 : #include "mozilla/dom/PrimitiveConversions.h"
12 : #include "mozilla/dom/XrayExpandoClass.h"
13 : #include "nsContentUtils.h"
14 : #include "nsIGlobalObject.h"
15 :
16 : namespace mozilla {
17 : namespace dom {
18 :
19 : namespace ExternalBinding {
20 :
21 : static bool
22 0 : AddSearchProvider(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::External* self, const JSJitMethodCallArgs& args)
23 : {
24 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
25 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "External.AddSearchProvider");
26 : }
27 0 : if (!mozilla::dom::EnforceNotInPrerendering(cx, obj)) {
28 : // Return false from the JSNative in order to trigger
29 : // an uncatchable exception.
30 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
31 0 : return false;
32 : }
33 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
34 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
35 0 : if (objIsXray) {
36 0 : unwrappedObj.emplace(cx, obj);
37 : }
38 0 : binding_detail::FakeString arg0;
39 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
40 0 : return false;
41 : }
42 0 : if (objIsXray) {
43 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
44 0 : if (!unwrappedObj.ref()) {
45 0 : return false;
46 : }
47 : }
48 0 : binding_detail::FastErrorResult rv;
49 0 : self->AddSearchProvider(NonNullHelper(Constify(arg0)), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj));
50 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
51 0 : return false;
52 : }
53 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
54 0 : args.rval().setUndefined();
55 0 : return true;
56 : }
57 :
58 : static const JSJitInfo AddSearchProvider_methodinfo = {
59 : { (JSJitGetterOp)AddSearchProvider },
60 : { prototypes::id::External },
61 : { PrototypeTraits<prototypes::id::External>::Depth },
62 : JSJitInfo::Method,
63 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
64 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
65 : false, /* isInfallible. False in setters. */
66 : false, /* isMovable. Not relevant for setters. */
67 : false, /* isEliminatable. Not relevant for setters. */
68 : false, /* isAlwaysInSlot. Only relevant for getters. */
69 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
70 : false, /* isTypedMethod. Only relevant for methods. */
71 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
72 : };
73 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
74 : static_assert(0 < 1, "There is no slot for us");
75 :
76 : static bool
77 0 : IsSearchProviderInstalled(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::External* self, const JSJitMethodCallArgs& args)
78 : {
79 0 : if (MOZ_UNLIKELY(args.length() < 1)) {
80 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "External.IsSearchProviderInstalled");
81 : }
82 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
83 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
84 0 : if (objIsXray) {
85 0 : unwrappedObj.emplace(cx, obj);
86 : }
87 0 : binding_detail::FakeString arg0;
88 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
89 0 : return false;
90 : }
91 0 : if (objIsXray) {
92 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
93 0 : if (!unwrappedObj.ref()) {
94 0 : return false;
95 : }
96 : }
97 0 : binding_detail::FastErrorResult rv;
98 0 : uint32_t result(self->IsSearchProviderInstalled(NonNullHelper(Constify(arg0)), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj)));
99 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
100 0 : return false;
101 : }
102 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
103 0 : args.rval().setNumber(result);
104 0 : return true;
105 : }
106 :
107 : static const JSJitInfo IsSearchProviderInstalled_methodinfo = {
108 : { (JSJitGetterOp)IsSearchProviderInstalled },
109 : { prototypes::id::External },
110 : { PrototypeTraits<prototypes::id::External>::Depth },
111 : JSJitInfo::Method,
112 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
113 : JSVAL_TYPE_DOUBLE, /* returnType. Not relevant for setters. */
114 : false, /* isInfallible. False in setters. */
115 : false, /* isMovable. Not relevant for setters. */
116 : false, /* isEliminatable. Not relevant for setters. */
117 : false, /* isAlwaysInSlot. Only relevant for getters. */
118 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
119 : false, /* isTypedMethod. Only relevant for methods. */
120 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
121 : };
122 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
123 : static_assert(0 < 1, "There is no slot for us");
124 :
125 : static bool
126 0 : addSearchEngine(JSContext* cx, JS::Handle<JSObject*> obj, mozilla::dom::External* self, const JSJitMethodCallArgs& args)
127 : {
128 0 : if (MOZ_UNLIKELY(args.length() < 4)) {
129 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "External.addSearchEngine");
130 : }
131 0 : if (!mozilla::dom::EnforceNotInPrerendering(cx, obj)) {
132 : // Return false from the JSNative in order to trigger
133 : // an uncatchable exception.
134 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
135 0 : return false;
136 : }
137 0 : Maybe<JS::Rooted<JSObject*> > unwrappedObj;
138 0 : bool objIsXray = xpc::WrapperFactory::IsXrayWrapper(obj);
139 0 : if (objIsXray) {
140 0 : unwrappedObj.emplace(cx, obj);
141 : }
142 0 : binding_detail::FakeString arg0;
143 0 : if (!ConvertJSValueToString(cx, args[0], eStringify, eStringify, arg0)) {
144 0 : return false;
145 : }
146 0 : binding_detail::FakeString arg1;
147 0 : if (!ConvertJSValueToString(cx, args[1], eStringify, eStringify, arg1)) {
148 0 : return false;
149 : }
150 0 : binding_detail::FakeString arg2;
151 0 : if (!ConvertJSValueToString(cx, args[2], eStringify, eStringify, arg2)) {
152 0 : return false;
153 : }
154 0 : binding_detail::FakeString arg3;
155 0 : if (!ConvertJSValueToString(cx, args[3], eStringify, eStringify, arg3)) {
156 0 : return false;
157 : }
158 0 : if (objIsXray) {
159 0 : unwrappedObj.ref() = js::CheckedUnwrap(unwrappedObj.ref());
160 0 : if (!unwrappedObj.ref()) {
161 0 : return false;
162 : }
163 : }
164 0 : binding_detail::FastErrorResult rv;
165 0 : self->AddSearchEngine(NonNullHelper(Constify(arg0)), NonNullHelper(Constify(arg1)), NonNullHelper(Constify(arg2)), NonNullHelper(Constify(arg3)), rv, js::GetObjectCompartment(unwrappedObj ? *unwrappedObj : obj));
166 0 : if (MOZ_UNLIKELY(rv.MaybeSetPendingException(cx))) {
167 0 : return false;
168 : }
169 0 : MOZ_ASSERT(!JS_IsExceptionPending(cx));
170 0 : SetDocumentAndPageUseCounter(cx, obj, eUseCounter_External_addSearchEngine);
171 0 : args.rval().setUndefined();
172 0 : return true;
173 : }
174 :
175 : static const JSJitInfo addSearchEngine_methodinfo = {
176 : { (JSJitGetterOp)addSearchEngine },
177 : { prototypes::id::External },
178 : { PrototypeTraits<prototypes::id::External>::Depth },
179 : JSJitInfo::Method,
180 : JSJitInfo::AliasEverything, /* aliasSet. Not relevant for setters. */
181 : JSVAL_TYPE_UNDEFINED, /* returnType. Not relevant for setters. */
182 : false, /* isInfallible. False in setters. */
183 : false, /* isMovable. Not relevant for setters. */
184 : false, /* isEliminatable. Not relevant for setters. */
185 : false, /* isAlwaysInSlot. Only relevant for getters. */
186 : false, /* isLazilyCachedInSlot. Only relevant for getters. */
187 : false, /* isTypedMethod. Only relevant for methods. */
188 : 0 /* Reserved slot index, if we're stored in a slot, else 0. */
189 : };
190 : static_assert(0 <= JSJitInfo::maxSlotIndex, "We won't fit");
191 : static_assert(0 < 1, "There is no slot for us");
192 :
193 : static bool
194 0 : _addProperty(JSContext* cx, JS::Handle<JSObject*> obj, JS::Handle<jsid> id, JS::Handle<JS::Value> val)
195 : {
196 0 : mozilla::dom::External* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::External>(obj);
197 : // We don't want to preserve if we don't have a wrapper, and we
198 : // obviously can't preserve if we're not initialized.
199 0 : if (self && self->GetWrapperPreserveColor()) {
200 0 : PreserveWrapper(self);
201 : }
202 0 : return true;
203 : }
204 :
205 : static void
206 0 : _finalize(js::FreeOp* fop, JSObject* obj)
207 : {
208 0 : mozilla::dom::External* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::External>(obj);
209 0 : if (self) {
210 0 : ClearWrapper(self, self, obj);
211 0 : AddForDeferredFinalization<mozilla::dom::External>(self);
212 : }
213 0 : }
214 :
215 : static void
216 0 : _objectMoved(JSObject* obj, const JSObject* old)
217 : {
218 0 : mozilla::dom::External* self = UnwrapPossiblyNotInitializedDOMObject<mozilla::dom::External>(obj);
219 0 : if (self) {
220 0 : UpdateWrapper(self, self, obj, old);
221 : }
222 0 : }
223 :
224 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
225 : #if defined(__clang__)
226 : #pragma clang diagnostic push
227 : #pragma clang diagnostic ignored "-Wmissing-braces"
228 : #endif
229 : static const JSFunctionSpec sChromeStaticMethods_specs[] = {
230 : JS_FNSPEC("_create", External::_Create, nullptr, 2, 0, nullptr),
231 : JS_FS_END
232 : };
233 : #if defined(__clang__)
234 : #pragma clang diagnostic pop
235 : #endif
236 :
237 :
238 : // Can't be const because the pref-enabled boolean needs to be writable
239 : static Prefable<const JSFunctionSpec> sChromeStaticMethods[] = {
240 : { nullptr, &sChromeStaticMethods_specs[0] },
241 : { nullptr, nullptr }
242 : };
243 :
244 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
245 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
246 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
247 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
248 :
249 : // We deliberately use brace-elision to make Visual Studio produce better initalization code.
250 : #if defined(__clang__)
251 : #pragma clang diagnostic push
252 : #pragma clang diagnostic ignored "-Wmissing-braces"
253 : #endif
254 : static const JSFunctionSpec sMethods_specs[] = {
255 : JS_FNSPEC("AddSearchProvider", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&AddSearchProvider_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
256 : JS_FNSPEC("IsSearchProviderInstalled", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&IsSearchProviderInstalled_methodinfo), 1, JSPROP_ENUMERATE, nullptr),
257 : JS_FNSPEC("addSearchEngine", GenericBindingMethod, reinterpret_cast<const JSJitInfo*>(&addSearchEngine_methodinfo), 4, JSPROP_ENUMERATE, nullptr),
258 : JS_FS_END
259 : };
260 : #if defined(__clang__)
261 : #pragma clang diagnostic pop
262 : #endif
263 :
264 :
265 : // Can't be const because the pref-enabled boolean needs to be writable
266 : static Prefable<const JSFunctionSpec> sMethods[] = {
267 : { nullptr, &sMethods_specs[0] },
268 : { nullptr, nullptr }
269 : };
270 :
271 : static_assert(1 <= 1ull << NUM_BITS_PROPERTY_INFO_PREF_INDEX,
272 : "We have a prefable index that is >= (1 << NUM_BITS_PROPERTY_INFO_PREF_INDEX)");
273 : static_assert(3 <= 1ull << NUM_BITS_PROPERTY_INFO_SPEC_INDEX,
274 : "We have a spec index that is >= (1 << NUM_BITS_PROPERTY_INFO_SPEC_INDEX)");
275 :
276 :
277 : static uint16_t sNativeProperties_sortedPropertyIndices[3];
278 : static PropertyInfo sNativeProperties_propertyInfos[3];
279 :
280 : static const NativePropertiesN<1> sNativeProperties = {
281 : false, 0,
282 : false, 0,
283 : true, 0 /* sMethods */,
284 : false, 0,
285 : false, 0,
286 : false, 0,
287 : false, 0,
288 : -1,
289 : 3,
290 : sNativeProperties_sortedPropertyIndices,
291 : {
292 : { sMethods, &sNativeProperties_propertyInfos[0] }
293 : }
294 : };
295 : static_assert(3 < 1ull << CHAR_BIT * sizeof(sNativeProperties.propertyInfoCount),
296 : "We have a property info count that is oversized");
297 :
298 : static uint16_t sChromeOnlyNativeProperties_sortedPropertyIndices[1];
299 : static PropertyInfo sChromeOnlyNativeProperties_propertyInfos[1];
300 :
301 : static const NativePropertiesN<1> sChromeOnlyNativeProperties = {
302 : true, 0 /* sChromeStaticMethods */,
303 : false, 0,
304 : false, 0,
305 : false, 0,
306 : false, 0,
307 : false, 0,
308 : false, 0,
309 : -1,
310 : 1,
311 : sChromeOnlyNativeProperties_sortedPropertyIndices,
312 : {
313 : { sChromeStaticMethods, &sChromeOnlyNativeProperties_propertyInfos[0] }
314 : }
315 : };
316 : static_assert(1 < 1ull << CHAR_BIT * sizeof(sChromeOnlyNativeProperties.propertyInfoCount),
317 : "We have a property info count that is oversized");
318 :
319 : static const DOMIfaceAndProtoJSClass sInterfaceObjectClass = {
320 : {
321 : "Function",
322 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_SLOTS_BASE),
323 : &sBoringInterfaceObjectClassClassOps,
324 : JS_NULL_CLASS_SPEC,
325 : JS_NULL_CLASS_EXT,
326 : &sInterfaceObjectClassObjectOps
327 : },
328 : eInterface,
329 : true,
330 : prototypes::id::External,
331 : PrototypeTraits<prototypes::id::External>::Depth,
332 : sNativePropertyHooks,
333 : "function External() {\n [native code]\n}",
334 : JS::GetRealmFunctionPrototype
335 : };
336 :
337 : static const DOMIfaceAndProtoJSClass sPrototypeClass = {
338 : {
339 : "ExternalPrototype",
340 : JSCLASS_IS_DOMIFACEANDPROTOJSCLASS | JSCLASS_HAS_RESERVED_SLOTS(DOM_INTERFACE_PROTO_SLOTS_BASE),
341 : JS_NULL_CLASS_OPS,
342 : JS_NULL_CLASS_SPEC,
343 : JS_NULL_CLASS_EXT,
344 : JS_NULL_OBJECT_OPS
345 : },
346 : eInterfacePrototype,
347 : false,
348 : prototypes::id::External,
349 : PrototypeTraits<prototypes::id::External>::Depth,
350 : sNativePropertyHooks,
351 : "[object ExternalPrototype]",
352 : JS::GetRealmObjectPrototype
353 : };
354 :
355 : JSObject*
356 0 : DefineDOMInterface(JSContext* aCx, JS::Handle<JSObject*> aGlobal, JS::Handle<jsid> id, bool aDefineOnGlobal)
357 : {
358 0 : return GetConstructorObjectHandle(aCx, aDefineOnGlobal);
359 : }
360 :
361 : static const js::ClassOps sClassOps = {
362 : _addProperty, /* addProperty */
363 : nullptr, /* delProperty */
364 : nullptr, /* getProperty */
365 : nullptr, /* setProperty */
366 : nullptr, /* enumerate */
367 : nullptr, /* newEnumerate */
368 : nullptr, /* resolve */
369 : nullptr, /* mayResolve */
370 : _finalize, /* finalize */
371 : nullptr, /* call */
372 : nullptr, /* hasInstance */
373 : nullptr, /* construct */
374 : nullptr, /* trace */
375 : };
376 :
377 : static const js::ClassExtension sClassExtension = {
378 : nullptr, /* weakmapKeyDelegateOp */
379 : _objectMoved /* objectMovedOp */
380 : };
381 :
382 : static const DOMJSClass sClass = {
383 : { "External",
384 : JSCLASS_IS_DOMJSCLASS | JSCLASS_FOREGROUND_FINALIZE | JSCLASS_HAS_RESERVED_SLOTS(1),
385 : &sClassOps,
386 : JS_NULL_CLASS_SPEC,
387 : &sClassExtension,
388 : JS_NULL_OBJECT_OPS
389 : },
390 : { prototypes::id::External, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count, prototypes::id::_ID_Count },
391 : IsBaseOf<nsISupports, mozilla::dom::External >::value,
392 : sNativePropertyHooks,
393 : FindAssociatedGlobalForNative<mozilla::dom::External>::Get,
394 : GetProtoObjectHandle,
395 : GetCCParticipant<mozilla::dom::External>::Get()
396 : };
397 : static_assert(1 == DOM_INSTANCE_RESERVED_SLOTS,
398 : "Must have the right minimal number of reserved slots.");
399 : static_assert(1 >= 1,
400 : "Must have enough reserved slots.");
401 :
402 : const JSClass*
403 0 : GetJSClass()
404 : {
405 0 : return sClass.ToJSClass();
406 : }
407 :
408 : bool
409 0 : Wrap(JSContext* aCx, mozilla::dom::External* aObject, nsWrapperCache* aCache, JS::Handle<JSObject*> aGivenProto, JS::MutableHandle<JSObject*> aReflector)
410 : {
411 : MOZ_ASSERT(static_cast<mozilla::dom::External*>(aObject) ==
412 : reinterpret_cast<mozilla::dom::External*>(aObject),
413 : "Multiple inheritance for mozilla::dom::External is broken.");
414 0 : MOZ_ASSERT(ToSupportsIsCorrect(aObject));
415 0 : MOZ_ASSERT_IF(aGivenProto, js::IsObjectInContextCompartment(aGivenProto, aCx));
416 0 : MOZ_ASSERT(!aCache->GetWrapper(),
417 : "You should probably not be using Wrap() directly; use "
418 : "GetOrCreateDOMReflector instead");
419 :
420 0 : MOZ_ASSERT(ToSupportsIsOnPrimaryInheritanceChain(aObject, aCache),
421 : "nsISupports must be on our primary inheritance chain");
422 :
423 0 : JS::Rooted<JSObject*> global(aCx, FindAssociatedGlobal(aCx, aObject->GetParentObject()));
424 0 : if (!global) {
425 0 : return false;
426 : }
427 0 : MOZ_ASSERT(JS_IsGlobalObject(global));
428 0 : MOZ_ASSERT(JS::ObjectIsNotGray(global));
429 :
430 : // That might have ended up wrapping us already, due to the wonders
431 : // of XBL. Check for that, and bail out as needed.
432 0 : aReflector.set(aCache->GetWrapper());
433 0 : if (aReflector) {
434 : #ifdef DEBUG
435 0 : binding_detail::AssertReflectorHasGivenProto(aCx, aReflector, aGivenProto);
436 : #endif // DEBUG
437 0 : return true;
438 : }
439 :
440 0 : JSAutoCompartment ac(aCx, global);
441 0 : JS::Handle<JSObject*> canonicalProto = GetProtoObjectHandle(aCx);
442 0 : if (!canonicalProto) {
443 0 : return false;
444 : }
445 0 : JS::Rooted<JSObject*> proto(aCx);
446 0 : if (aGivenProto) {
447 0 : proto = aGivenProto;
448 : // Unfortunately, while aGivenProto was in the compartment of aCx
449 : // coming in, we changed compartments to that of "parent" so may need
450 : // to wrap the proto here.
451 0 : if (js::GetContextCompartment(aCx) != js::GetObjectCompartment(proto)) {
452 0 : if (!JS_WrapObject(aCx, &proto)) {
453 0 : return false;
454 : }
455 : }
456 : } else {
457 0 : proto = canonicalProto;
458 : }
459 :
460 0 : BindingJSObjectCreator<mozilla::dom::External> creator(aCx);
461 0 : creator.CreateObject(aCx, sClass.ToJSClass(), proto, aObject, aReflector);
462 0 : if (!aReflector) {
463 0 : return false;
464 : }
465 :
466 0 : aCache->SetWrapper(aReflector);
467 0 : creator.InitializationSucceeded();
468 :
469 0 : MOZ_ASSERT(aCache->GetWrapperPreserveColor() &&
470 : aCache->GetWrapperPreserveColor() == aReflector);
471 : // If proto != canonicalProto, we have to preserve our wrapper;
472 : // otherwise we won't be able to properly recreate it later, since
473 : // we won't know what proto to use. Note that we don't check
474 : // aGivenProto here, since it's entirely possible (and even
475 : // somewhat common) to have a non-null aGivenProto which is the
476 : // same as canonicalProto.
477 0 : if (proto != canonicalProto) {
478 0 : PreserveWrapper(aObject);
479 : }
480 :
481 0 : return true;
482 : }
483 :
484 : const NativePropertyHooks sNativePropertyHooks[] = { {
485 : nullptr,
486 : nullptr,
487 : nullptr,
488 : { sNativeProperties.Upcast(), sChromeOnlyNativeProperties.Upcast() },
489 : prototypes::id::External,
490 : constructors::id::External,
491 : nullptr,
492 : &DefaultXrayExpandoObjectClass
493 : } };
494 :
495 : void
496 0 : CreateInterfaceObjects(JSContext* aCx, JS::Handle<JSObject*> aGlobal, ProtoAndIfaceCache& aProtoAndIfaceCache, bool aDefineOnGlobal)
497 : {
498 0 : JS::Rooted<JSObject*> parentProto(aCx, JS::GetRealmObjectPrototype(aCx));
499 0 : if (!parentProto) {
500 0 : return;
501 : }
502 :
503 0 : JS::Rooted<JSObject*> constructorProto(aCx, JS::GetRealmFunctionPrototype(aCx));
504 0 : if (!constructorProto) {
505 0 : return;
506 : }
507 :
508 : static bool sIdsInited = false;
509 0 : if (!sIdsInited && NS_IsMainThread()) {
510 0 : if (!InitIds(aCx, sNativeProperties.Upcast())) {
511 0 : return;
512 : }
513 0 : if (!InitIds(aCx, sChromeOnlyNativeProperties.Upcast())) {
514 0 : return;
515 : }
516 0 : sIdsInited = true;
517 : }
518 :
519 0 : JS::Heap<JSObject*>* protoCache = &aProtoAndIfaceCache.EntrySlotOrCreate(prototypes::id::External);
520 0 : JS::Heap<JSObject*>* interfaceCache = &aProtoAndIfaceCache.EntrySlotOrCreate(constructors::id::External);
521 0 : dom::CreateInterfaceObjects(aCx, aGlobal, parentProto,
522 : &sPrototypeClass.mBase, protoCache,
523 : constructorProto, &sInterfaceObjectClass.mBase, 0, nullptr,
524 : interfaceCache,
525 : sNativeProperties.Upcast(),
526 0 : nsContentUtils::ThreadsafeIsSystemCaller(aCx) ? sChromeOnlyNativeProperties.Upcast() : nullptr,
527 : "External", aDefineOnGlobal,
528 : nullptr,
529 0 : false);
530 : }
531 :
532 : JS::Handle<JSObject*>
533 0 : GetProtoObjectHandle(JSContext* aCx)
534 : {
535 : /* Get the interface prototype object for this class. This will create the
536 : object as needed. */
537 0 : bool aDefineOnGlobal = true;
538 :
539 : /* Make sure our global is sane. Hopefully we can remove this sometime */
540 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
541 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
542 0 : return nullptr;
543 : }
544 :
545 : /* Check to see whether the interface objects are already installed */
546 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
547 0 : if (!protoAndIfaceCache.HasEntryInSlot(prototypes::id::External)) {
548 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
549 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
550 : }
551 :
552 : /*
553 : * The object might _still_ be null, but that's OK.
554 : *
555 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
556 : * traced by TraceProtoAndIfaceCache() and its contents are never
557 : * changed after they have been set.
558 : *
559 : * Calling address() avoids the read read barrier that does gray
560 : * unmarking, but it's not possible for the object to be gray here.
561 : */
562 :
563 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(prototypes::id::External);
564 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
565 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
566 : }
567 :
568 : JS::Handle<JSObject*>
569 0 : GetConstructorObjectHandle(JSContext* aCx, bool aDefineOnGlobal)
570 : {
571 : /* Get the interface object for this class. This will create the object as
572 : needed. */
573 :
574 : /* Make sure our global is sane. Hopefully we can remove this sometime */
575 0 : JSObject* global = JS::CurrentGlobalOrNull(aCx);
576 0 : if (!(js::GetObjectClass(global)->flags & JSCLASS_DOM_GLOBAL)) {
577 0 : return nullptr;
578 : }
579 :
580 : /* Check to see whether the interface objects are already installed */
581 0 : ProtoAndIfaceCache& protoAndIfaceCache = *GetProtoAndIfaceCache(global);
582 0 : if (!protoAndIfaceCache.HasEntryInSlot(constructors::id::External)) {
583 0 : JS::Rooted<JSObject*> rootedGlobal(aCx, global);
584 0 : CreateInterfaceObjects(aCx, rootedGlobal, protoAndIfaceCache, aDefineOnGlobal);
585 : }
586 :
587 : /*
588 : * The object might _still_ be null, but that's OK.
589 : *
590 : * Calling fromMarkedLocation() is safe because protoAndIfaceCache is
591 : * traced by TraceProtoAndIfaceCache() and its contents are never
592 : * changed after they have been set.
593 : *
594 : * Calling address() avoids the read read barrier that does gray
595 : * unmarking, but it's not possible for the object to be gray here.
596 : */
597 :
598 0 : const JS::Heap<JSObject*>& entrySlot = protoAndIfaceCache.EntrySlotMustExist(constructors::id::External);
599 0 : MOZ_ASSERT(JS::ObjectIsNotGray(entrySlot));
600 0 : return JS::Handle<JSObject*>::fromMarkedLocation(entrySlot.address());
601 : }
602 :
603 : JSObject*
604 0 : GetConstructorObject(JSContext* aCx)
605 : {
606 0 : return GetConstructorObjectHandle(aCx);
607 : }
608 :
609 : } // namespace ExternalBinding
610 :
611 :
612 :
613 : void
614 0 : ExternalJSImpl::AddSearchProvider(const nsAString& aDescriptionURL, ErrorResult& aRv, JSCompartment* aCompartment)
615 : {
616 0 : CallSetup s(this, aRv, "External.AddSearchProvider", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
617 0 : JSContext* cx = s.GetContext();
618 0 : if (!cx) {
619 0 : MOZ_ASSERT(aRv.Failed());
620 0 : return;
621 : }
622 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
623 0 : JS::AutoValueVector argv(cx);
624 0 : if (!argv.resize(1)) {
625 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
626 0 : return;
627 : }
628 0 : unsigned argc = 1;
629 :
630 : do {
631 0 : nsString mutableStr(aDescriptionURL);
632 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
633 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
634 0 : return;
635 : }
636 0 : break;
637 : } while (0);
638 :
639 0 : JS::Rooted<JS::Value> callable(cx);
640 0 : ExternalAtoms* atomsCache = GetAtomCache<ExternalAtoms>(cx);
641 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
642 0 : !GetCallableProperty(cx, atomsCache->AddSearchProvider_id, &callable)) {
643 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
644 0 : return;
645 : }
646 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
647 0 : if (!JS::Call(cx, thisValue, callable,
648 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
649 0 : aRv.NoteJSContextException(cx);
650 0 : return;
651 : }
652 : }
653 :
654 : uint32_t
655 0 : ExternalJSImpl::IsSearchProviderInstalled(const nsAString& aSearchURL, ErrorResult& aRv, JSCompartment* aCompartment)
656 : {
657 0 : CallSetup s(this, aRv, "External.IsSearchProviderInstalled", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
658 0 : JSContext* cx = s.GetContext();
659 0 : if (!cx) {
660 0 : MOZ_ASSERT(aRv.Failed());
661 0 : return uint32_t(0);
662 : }
663 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
664 0 : JS::AutoValueVector argv(cx);
665 0 : if (!argv.resize(1)) {
666 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
667 0 : return uint32_t(0);
668 : }
669 0 : unsigned argc = 1;
670 :
671 : do {
672 0 : nsString mutableStr(aSearchURL);
673 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
674 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
675 0 : return uint32_t(0);
676 : }
677 0 : break;
678 : } while (0);
679 :
680 0 : JS::Rooted<JS::Value> callable(cx);
681 0 : ExternalAtoms* atomsCache = GetAtomCache<ExternalAtoms>(cx);
682 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
683 0 : !GetCallableProperty(cx, atomsCache->IsSearchProviderInstalled_id, &callable)) {
684 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
685 0 : return uint32_t(0);
686 : }
687 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
688 0 : if (!JS::Call(cx, thisValue, callable,
689 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
690 0 : aRv.NoteJSContextException(cx);
691 0 : return uint32_t(0);
692 : }
693 : uint32_t rvalDecl;
694 0 : if (!ValueToPrimitive<uint32_t, eDefault>(cx, rval, &rvalDecl)) {
695 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
696 0 : return uint32_t(0);
697 : }
698 0 : return rvalDecl;
699 : }
700 :
701 : void
702 0 : ExternalJSImpl::AddSearchEngine(const nsAString& engineURL, const nsAString& iconURL, const nsAString& suggestedTitle, const nsAString& suggestedCategory, ErrorResult& aRv, JSCompartment* aCompartment)
703 : {
704 0 : CallSetup s(this, aRv, "External.addSearchEngine", eRethrowContentExceptions, aCompartment, /* aIsJSImplementedWebIDL = */ true);
705 0 : JSContext* cx = s.GetContext();
706 0 : if (!cx) {
707 0 : MOZ_ASSERT(aRv.Failed());
708 0 : return;
709 : }
710 0 : JS::Rooted<JS::Value> rval(cx, JS::UndefinedValue());
711 0 : JS::AutoValueVector argv(cx);
712 0 : if (!argv.resize(4)) {
713 0 : aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
714 0 : return;
715 : }
716 0 : unsigned argc = 4;
717 :
718 : do {
719 0 : nsString mutableStr(suggestedCategory);
720 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[3])) {
721 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
722 0 : return;
723 : }
724 0 : break;
725 : } while (0);
726 :
727 : do {
728 0 : nsString mutableStr(suggestedTitle);
729 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[2])) {
730 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
731 0 : return;
732 : }
733 0 : break;
734 : } while (0);
735 :
736 : do {
737 0 : nsString mutableStr(iconURL);
738 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[1])) {
739 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
740 0 : return;
741 : }
742 0 : break;
743 : } while (0);
744 :
745 : do {
746 0 : nsString mutableStr(engineURL);
747 0 : if (!xpc::NonVoidStringToJsval(cx, mutableStr, argv[0])) {
748 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
749 0 : return;
750 : }
751 0 : break;
752 : } while (0);
753 :
754 0 : JS::Rooted<JS::Value> callable(cx);
755 0 : ExternalAtoms* atomsCache = GetAtomCache<ExternalAtoms>(cx);
756 0 : if ((!*reinterpret_cast<jsid**>(atomsCache) && !InitIds(cx, atomsCache)) ||
757 0 : !GetCallableProperty(cx, atomsCache->addSearchEngine_id, &callable)) {
758 0 : aRv.Throw(NS_ERROR_UNEXPECTED);
759 0 : return;
760 : }
761 0 : JS::Rooted<JS::Value> thisValue(cx, JS::ObjectValue(*mCallback));
762 0 : if (!JS::Call(cx, thisValue, callable,
763 0 : JS::HandleValueArray::subarray(argv, 0, argc), &rval)) {
764 0 : aRv.NoteJSContextException(cx);
765 0 : return;
766 : }
767 : }
768 :
769 : bool
770 0 : ExternalJSImpl::InitIds(JSContext* cx, ExternalAtoms* atomsCache)
771 : {
772 0 : MOZ_ASSERT(!*reinterpret_cast<jsid**>(atomsCache));
773 :
774 : // Initialize these in reverse order so that any failure leaves the first one
775 : // uninitialized.
776 0 : if (!atomsCache->addSearchEngine_id.init(cx, "addSearchEngine") ||
777 0 : !atomsCache->IsSearchProviderInstalled_id.init(cx, "IsSearchProviderInstalled") ||
778 0 : !atomsCache->AddSearchProvider_id.init(cx, "AddSearchProvider")) {
779 0 : return false;
780 : }
781 0 : return true;
782 : }
783 :
784 :
785 :
786 : NS_IMPL_CYCLE_COLLECTION_CLASS(External)
787 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(External)
788 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mImpl)
789 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
790 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
791 0 : tmp->ClearWeakReferences();
792 0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
793 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(External)
794 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mImpl)
795 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
796 0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
797 0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(External)
798 0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(External)
799 0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(External)
800 0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(External)
801 0 : NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
802 0 : NS_INTERFACE_MAP_ENTRY(nsISupports)
803 0 : NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
804 0 : NS_INTERFACE_MAP_END
805 :
806 0 : External::External(JS::Handle<JSObject*> aJSImplObject, nsIGlobalObject* aParent)
807 0 : : mImpl(new ExternalJSImpl(nullptr, aJSImplObject, /* aIncumbentGlobal = */ nullptr)),
808 0 : mParent(aParent)
809 : {
810 0 : }
811 :
812 :
813 0 : External::~External()
814 : {
815 0 : }
816 :
817 : nsISupports*
818 0 : External::GetParentObject() const
819 : {
820 0 : return mParent;
821 : }
822 :
823 : JSObject*
824 0 : External::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
825 : {
826 0 : JS::Rooted<JSObject*> obj(aCx, ExternalBinding::Wrap(aCx, this, aGivenProto));
827 0 : if (!obj) {
828 0 : return nullptr;
829 : }
830 :
831 : // Now define it on our chrome object
832 0 : JSAutoCompartment ac(aCx, mImpl->CallbackOrNull());
833 0 : if (!JS_WrapObject(aCx, &obj)) {
834 0 : return nullptr;
835 : }
836 0 : if (!JS_DefineProperty(aCx, mImpl->CallbackOrNull(), "__DOM_IMPL__", obj, 0)) {
837 0 : return nullptr;
838 : }
839 0 : return obj;
840 : }
841 :
842 : void
843 0 : External::AddSearchProvider(const nsAString& aDescriptionURL, ErrorResult& aRv, JSCompartment* aCompartment)
844 : {
845 0 : return mImpl->AddSearchProvider(aDescriptionURL, aRv, aCompartment);
846 : }
847 :
848 : uint32_t
849 0 : External::IsSearchProviderInstalled(const nsAString& aSearchURL, ErrorResult& aRv, JSCompartment* aCompartment)
850 : {
851 0 : return mImpl->IsSearchProviderInstalled(aSearchURL, aRv, aCompartment);
852 : }
853 :
854 : void
855 0 : External::AddSearchEngine(const nsAString& engineURL, const nsAString& iconURL, const nsAString& suggestedTitle, const nsAString& suggestedCategory, ErrorResult& aRv, JSCompartment* aCompartment)
856 : {
857 0 : return mImpl->AddSearchEngine(engineURL, iconURL, suggestedTitle, suggestedCategory, aRv, aCompartment);
858 : }
859 :
860 : bool
861 0 : External::_Create(JSContext* cx, unsigned argc, JS::Value* vp)
862 : {
863 0 : JS::CallArgs args = JS::CallArgsFromVp(argc, vp);
864 0 : if (args.length() < 2) {
865 0 : return ThrowErrorMessage(cx, MSG_MISSING_ARGUMENTS, "External._create");
866 : }
867 0 : if (!args[0].isObject()) {
868 0 : return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 1 of External._create");
869 : }
870 0 : if (!args[1].isObject()) {
871 0 : return ThrowErrorMessage(cx, MSG_NOT_OBJECT, "Argument 2 of External._create");
872 : }
873 :
874 : // GlobalObject will go through wrappers as needed for us, and
875 : // is simpler than the right UnwrapArg incantation.
876 0 : GlobalObject global(cx, &args[0].toObject());
877 0 : if (global.Failed()) {
878 0 : return false;
879 : }
880 0 : nsCOMPtr<nsIGlobalObject> globalHolder = do_QueryInterface(global.GetAsSupports());
881 0 : MOZ_ASSERT(globalHolder);
882 0 : JS::Rooted<JSObject*> arg(cx, &args[1].toObject());
883 0 : RefPtr<External> impl = new External(arg, globalHolder);
884 0 : MOZ_ASSERT(js::IsObjectInContextCompartment(arg, cx));
885 0 : return GetOrCreateDOMReflector(cx, impl, args.rval());
886 : }
887 :
888 :
889 : } // namespace dom
890 : } // namespace mozilla
|