1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*-
2  * vim: set ts=8 sw=4 et tw=78:
3  *
4  * This Source Code Form is subject to the terms of the Mozilla Public
5  * License, v. 2.0. If a copy of the MPL was not distributed with this
6  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
7 
8 #include "ShimInterfaceInfo.h"
9 
10 #include "nsIDOMCharacterData.h"
11 #include "nsIDOMClientRect.h"
12 #include "nsIDOMClientRectList.h"
13 #include "nsIDOMClipboardEvent.h"
14 #include "nsIDOMComment.h"
15 #include "nsIDOMCustomEvent.h"
16 #ifdef MOZ_WEBRTC
17 #include "nsIDOMDataChannel.h"
18 #endif
19 #include "nsIDOMDataTransfer.h"
20 #include "nsIDOMDOMCursor.h"
21 #include "nsIDOMDOMException.h"
22 #include "nsIDOMDOMRequest.h"
23 #include "nsIDOMDocument.h"
24 #include "nsIDOMDocumentFragment.h"
25 #include "nsIDOMDocumentType.h"
26 #include "nsIDOMDragEvent.h"
27 #include "nsIDOMElement.h"
28 #include "nsIDOMEvent.h"
29 #include "nsIDOMEventTarget.h"
30 #include "nsIDOMFileList.h"
31 #include "nsIDOMFocusEvent.h"
32 #include "nsIDOMGeoPositionError.h"
33 #include "nsIDOMHTMLFormElement.h"
34 #include "nsIDOMHTMLInputElement.h"
35 #include "nsIDOMMouseEvent.h"
36 #include "nsIDOMMouseScrollEvent.h"
37 #include "nsIDOMNode.h"
38 #include "nsIDOMNodeList.h"
39 #include "nsIDOMNotifyPaintEvent.h"
40 #include "nsIDOMNSEvent.h"
41 #include "nsIDOMOfflineResourceList.h"
42 #include "nsIDOMParser.h"
43 #include "nsIDOMProcessingInstruction.h"
44 #include "nsIDOMRange.h"
45 #include "nsIDOMScreen.h"
46 #include "nsIDOMScrollAreaEvent.h"
47 #include "nsIDOMSerializer.h"
48 #include "nsIDOMText.h"
49 #include "nsIDOMUIEvent.h"
50 #include "nsIDOMWheelEvent.h"
51 #include "nsIDOMXMLDocument.h"
52 #include "nsIDOMXULCommandEvent.h"
53 #include "nsIDOMXULElement.h"
54 #include "nsIFrameLoader.h"
55 #include "nsIListBoxObject.h"
56 #include "nsISelection.h"
57 #include "nsITreeBoxObject.h"
58 #include "nsIWebBrowserPersistable.h"
59 
60 #include "mozilla/dom/CharacterDataBinding.h"
61 #include "mozilla/dom/DOMRectBinding.h"
62 #include "mozilla/dom/DOMRectListBinding.h"
63 #include "mozilla/dom/ClipboardEventBinding.h"
64 #include "mozilla/dom/CommentBinding.h"
65 #include "mozilla/dom/CSSPrimitiveValueBinding.h"
66 #include "mozilla/dom/CSSStyleDeclarationBinding.h"
67 #include "mozilla/dom/CSSStyleSheetBinding.h"
68 #include "mozilla/dom/CSSValueBinding.h"
69 #include "mozilla/dom/CSSValueListBinding.h"
70 #include "mozilla/dom/CustomEventBinding.h"
71 #include "mozilla/dom/DataTransferBinding.h"
72 #include "mozilla/dom/DOMCursorBinding.h"
73 #include "mozilla/dom/DOMExceptionBinding.h"
74 #include "mozilla/dom/DOMParserBinding.h"
75 #include "mozilla/dom/DOMRequestBinding.h"
76 #include "mozilla/dom/DocumentBinding.h"
77 #include "mozilla/dom/DocumentFragmentBinding.h"
78 #include "mozilla/dom/DocumentTypeBinding.h"
79 #include "mozilla/dom/DragEventBinding.h"
80 #include "mozilla/dom/ElementBinding.h"
81 #include "mozilla/dom/EventBinding.h"
82 #include "mozilla/dom/EventTargetBinding.h"
83 #include "mozilla/dom/FileListBinding.h"
84 #include "mozilla/dom/FocusEventBinding.h"
85 #include "mozilla/dom/FrameLoaderBinding.h"
86 #include "mozilla/dom/HTMLAnchorElementBinding.h"
87 #include "mozilla/dom/HTMLAreaElementBinding.h"
88 #include "mozilla/dom/HTMLButtonElementBinding.h"
89 #include "mozilla/dom/HTMLFormElementBinding.h"
90 #include "mozilla/dom/HTMLFrameSetElementBinding.h"
91 #include "mozilla/dom/HTMLHtmlElementBinding.h"
92 #include "mozilla/dom/HTMLInputElementBinding.h"
93 #include "mozilla/dom/ListBoxObjectBinding.h"
94 #include "mozilla/dom/MediaListBinding.h"
95 #include "mozilla/dom/MessageEventBinding.h"
96 #include "mozilla/dom/MouseEventBinding.h"
97 #include "mozilla/dom/MouseScrollEventBinding.h"
98 #include "mozilla/dom/NodeListBinding.h"
99 #include "mozilla/dom/NodeBinding.h"
100 #include "mozilla/dom/NotifyPaintEventBinding.h"
101 #include "mozilla/dom/EventBinding.h"
102 #include "mozilla/dom/OfflineResourceListBinding.h"
103 #include "mozilla/dom/PositionErrorBinding.h"
104 #include "mozilla/dom/ProcessingInstructionBinding.h"
105 #include "mozilla/dom/RangeBinding.h"
106 #include "mozilla/dom/RectBinding.h"
107 #ifdef MOZ_WEBRTC
108 #include "mozilla/dom/RTCDataChannelBinding.h"
109 #endif
110 #include "mozilla/dom/ScreenBinding.h"
111 #include "mozilla/dom/SelectionBinding.h"
112 #include "mozilla/dom/ScrollAreaEventBinding.h"
113 #include "mozilla/dom/StorageEventBinding.h"
114 #include "mozilla/dom/StyleSheetBinding.h"
115 #include "mozilla/dom/StyleSheetListBinding.h"
116 #include "mozilla/dom/SVGElementBinding.h"
117 #include "mozilla/dom/TextBinding.h"
118 #include "mozilla/dom/TimeEventBinding.h"
119 #include "mozilla/dom/TreeBoxObjectBinding.h"
120 #include "mozilla/dom/UIEventBinding.h"
121 #include "mozilla/dom/WheelEventBinding.h"
122 #include "mozilla/dom/XMLDocumentBinding.h"
123 #include "mozilla/dom/XMLSerializerBinding.h"
124 #include "mozilla/dom/XULCommandEventBinding.h"
125 #include "mozilla/dom/XULDocumentBinding.h"
126 #include "mozilla/dom/XULElementBinding.h"
127 
128 using namespace mozilla;
129 
130 struct ComponentsInterfaceShimEntry {
ComponentsInterfaceShimEntryComponentsInterfaceShimEntry131   constexpr ComponentsInterfaceShimEntry(
132       const char* aName, const nsIID& aIID,
133       const dom::NativePropertyHooks* aNativePropHooks)
134       : geckoName(aName), iid(aIID), nativePropHooks(aNativePropHooks) {}
135 
136   const char* geckoName;
137   const nsIID& iid;
138   const dom::NativePropertyHooks* nativePropHooks;
139 };
140 
141 #define DEFINE_SHIM_WITH_CUSTOM_INTERFACE(geckoName, domName) \
142   {                                                           \
143     #geckoName, NS_GET_IID(geckoName),                        \
144         mozilla::dom::domName##Binding::sNativePropertyHooks  \
145   }
146 #define DEFINE_SHIM(name) DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOM##name, name)
147 
148 /**
149  * These shim entries allow us to make old XPIDL interfaces implementing DOM
150  * APIs as non-scriptable in order to save some runtime memory on Firefox OS,
151  * without breaking the entries under Components.interfaces which might both
152  * be used by our code and add-ons.  Specifically, the shim entries provide
153  * the following:
154  *
155  * * Components.interfaces.nsIFoo entries.  These entries basically work
156  *   almost exactly as the usual ones that you would get through the
157  *   XPIDL machinery.  Specifically, they have the right name, they reflect
158  *   the right IID, and they will work properly when passed to QueryInterface.
159  *
160  * * Components.interfaces.nsIFoo.CONSTANT values.  These entries will have
161  *   the right name and the right value for most integer types.  Note that
162  *   support for non-numerical constants is untested and will probably not
163  *   work out of the box.
164  *
165  * FAQ:
166  * * When should I add an entry to the list here?
167  *   Only if you're making an XPIDL interfaces which has a corresponding
168  *   WebIDL interface non-scriptable.
169  * * When should I remove an entry from this list?
170  *   If you are completely removing an XPIDL interface from the code base.  If
171  *   you forget to do so, the compiler will remind you.
172  * * How should I add an entry to the list here?
173  *   First, make sure that the XPIDL interface in question is non-scriptable
174  *   and also has a corresponding WebIDL interface.  Then, add two include
175  *   entries above, one for the XPIDL interface and one for the WebIDL
176  *   interface, and add a shim entry below.  If the name of the XPIDL
177  *   interface only has an "nsIDOM" prefix prepended to the WebIDL name, you
178  *   can use the DEFINE_SHIM macro and pass in the name of the WebIDL
179  *   interface.  Otherwise, use DEFINE_SHIM_WITH_CUSTOM_INTERFACE.
180  */
181 
182 const ComponentsInterfaceShimEntry kComponentsInterfaceShimMap[] = {
183     DEFINE_SHIM(CharacterData),
184     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRect, DOMRectReadOnly),
185     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMClientRectList, DOMRectList),
186     DEFINE_SHIM(ClipboardEvent),
187     DEFINE_SHIM(Comment),
188     DEFINE_SHIM(CustomEvent),
189     DEFINE_SHIM(DataTransfer),
190     DEFINE_SHIM(DOMCursor),
191     DEFINE_SHIM(DOMException),
192     DEFINE_SHIM(DOMRequest),
193     DEFINE_SHIM(Document),
194     DEFINE_SHIM(DocumentFragment),
195     DEFINE_SHIM(DocumentType),
196     DEFINE_SHIM(DragEvent),
197     DEFINE_SHIM(Element),
198     DEFINE_SHIM(Event),
199     DEFINE_SHIM(EventTarget),
200     DEFINE_SHIM(FileList),
201     DEFINE_SHIM(FocusEvent),
202     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIFrameLoader, FrameLoader),
203     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMGeoPositionError, PositionError),
204     DEFINE_SHIM(HTMLFormElement),
205     DEFINE_SHIM(HTMLInputElement),
206     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIListBoxObject, ListBoxObject),
207     DEFINE_SHIM(MouseEvent),
208     DEFINE_SHIM(MouseScrollEvent),
209     DEFINE_SHIM(NodeList),
210     DEFINE_SHIM(Node),
211     DEFINE_SHIM(NotifyPaintEvent),
212     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMNSEvent, Event),
213     DEFINE_SHIM(OfflineResourceList),
214     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMParser, DOMParser),
215     DEFINE_SHIM(ProcessingInstruction),
216     DEFINE_SHIM(Range),
217 #ifdef MOZ_WEBRTC
218     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMDataChannel, RTCDataChannel),
219 #endif
220     DEFINE_SHIM(Screen),
221     DEFINE_SHIM(ScrollAreaEvent),
222     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIDOMSerializer, XMLSerializer),
223     DEFINE_SHIM(Text),
224     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsITreeBoxObject, TreeBoxObject),
225     DEFINE_SHIM(UIEvent),
226     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsIWebBrowserPersistable, FrameLoader),
227     DEFINE_SHIM(WheelEvent),
228     DEFINE_SHIM(XMLDocument),
229     DEFINE_SHIM(XULCommandEvent),
230     DEFINE_SHIM(XULElement),
231     DEFINE_SHIM_WITH_CUSTOM_INTERFACE(nsISelection, Selection),
232 };
233 
234 #undef DEFINE_SHIM
235 #undef DEFINE_SHIM_WITH_CUSTOM_INTERFACE
236 
NS_IMPL_ISUPPORTS(ShimInterfaceInfo,nsISupports,nsIInterfaceInfo)237 NS_IMPL_ISUPPORTS(ShimInterfaceInfo, nsISupports, nsIInterfaceInfo)
238 
239 already_AddRefed<ShimInterfaceInfo> ShimInterfaceInfo::MaybeConstruct(
240     const char* aName, JSContext* cx) {
241   RefPtr<ShimInterfaceInfo> info;
242   for (uint32_t i = 0; i < ArrayLength(kComponentsInterfaceShimMap); ++i) {
243     if (!strcmp(aName, kComponentsInterfaceShimMap[i].geckoName)) {
244       const ComponentsInterfaceShimEntry& shimEntry =
245           kComponentsInterfaceShimMap[i];
246       info = new ShimInterfaceInfo(shimEntry.iid, shimEntry.geckoName,
247                                    shimEntry.nativePropHooks);
248       break;
249     }
250   }
251   return info.forget();
252 }
253 
ShimInterfaceInfo(const nsIID & aIID,const char * aName,const mozilla::dom::NativePropertyHooks * aNativePropHooks)254 ShimInterfaceInfo::ShimInterfaceInfo(
255     const nsIID& aIID, const char* aName,
256     const mozilla::dom::NativePropertyHooks* aNativePropHooks)
257     : mIID(aIID), mName(aName), mNativePropHooks(aNativePropHooks) {}
258 
259 NS_IMETHODIMP
GetName(char ** aName)260 ShimInterfaceInfo::GetName(char** aName) {
261   *aName = ToNewCString(mName);
262   return NS_OK;
263 }
264 
265 NS_IMETHODIMP
GetInterfaceIID(nsIID ** aIID)266 ShimInterfaceInfo::GetInterfaceIID(nsIID** aIID) {
267   *aIID = mIID.Clone();
268   return NS_OK;
269 }
270 
271 NS_IMETHODIMP
IsScriptable(bool * aRetVal)272 ShimInterfaceInfo::IsScriptable(bool* aRetVal) {
273   // This class should pretend that the interface is scriptable because
274   // that's what nsJSIID assumes.
275   *aRetVal = true;
276   return NS_OK;
277 }
278 
279 NS_IMETHODIMP
IsBuiltinClass(bool * aRetVal)280 ShimInterfaceInfo::IsBuiltinClass(bool* aRetVal) {
281   *aRetVal = true;
282   return NS_OK;
283 }
284 
285 NS_IMETHODIMP
IsMainProcessScriptableOnly(bool * aRetVal)286 ShimInterfaceInfo::IsMainProcessScriptableOnly(bool* aRetVal) {
287   *aRetVal = false;
288   return NS_OK;
289 }
290 
291 NS_IMETHODIMP
GetParent(nsIInterfaceInfo ** aParent)292 ShimInterfaceInfo::GetParent(nsIInterfaceInfo** aParent) {
293   *aParent = nullptr;
294   return NS_OK;
295 }
296 
297 NS_IMETHODIMP
GetMethodCount(uint16_t * aCount)298 ShimInterfaceInfo::GetMethodCount(uint16_t* aCount) {
299   // Pretend we don't have any methods.
300   *aCount = 0;
301   return NS_OK;
302 }
303 
304 NS_IMETHODIMP
GetConstantCount(uint16_t * aCount)305 ShimInterfaceInfo::GetConstantCount(uint16_t* aCount) {
306   // We assume that we never have interfaces with more than UINT16_MAX
307   // constants defined on them.
308   uint16_t count = 0;
309 
310   // NOTE: The structure of this loop must be kept in sync with the loop
311   // in GetConstant.
312   const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
313   do {
314     const mozilla::dom::NativeProperties* props[] = {
315         propHooks->mNativeProperties.regular,
316         propHooks->mNativeProperties.chromeOnly};
317     for (size_t i = 0; i < ArrayLength(props); ++i) {
318       auto prop = props[i];
319       if (prop && prop->HasConstants()) {
320         for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
321           // We have found one constant here.  We explicitly do not
322           // bother calling isEnabled() here because it's OK to define
323           // potentially extra constants on these shim interfaces.
324           ++count;
325         }
326       }
327     }
328   } while ((propHooks = propHooks->mProtoHooks));
329   *aCount = count;
330   return NS_OK;
331 }
332 
333 NS_IMETHODIMP
GetMethodInfo(uint16_t aIndex,const nsXPTMethodInfo ** aInfo)334 ShimInterfaceInfo::GetMethodInfo(uint16_t aIndex,
335                                  const nsXPTMethodInfo** aInfo) {
336   MOZ_ASSERT(false, "This should never be called");
337   return NS_ERROR_NOT_IMPLEMENTED;
338 }
339 
340 NS_IMETHODIMP
GetMethodInfoForName(const char * aName,uint16_t * aIndex,const nsXPTMethodInfo ** aInfo)341 ShimInterfaceInfo::GetMethodInfoForName(const char* aName, uint16_t* aIndex,
342                                         const nsXPTMethodInfo** aInfo) {
343   MOZ_ASSERT(false, "This should never be called");
344   return NS_ERROR_NOT_IMPLEMENTED;
345 }
346 
347 NS_IMETHODIMP
GetConstant(uint16_t aIndex,JS::MutableHandleValue aConstant,char ** aName)348 ShimInterfaceInfo::GetConstant(uint16_t aIndex,
349                                JS::MutableHandleValue aConstant, char** aName) {
350   // We assume that we never have interfaces with more than UINT16_MAX
351   // constants defined on them.
352   uint16_t index = 0;
353 
354   // NOTE: The structure of this loop must be kept in sync with the loop
355   // in GetConstantCount.
356   const mozilla::dom::NativePropertyHooks* propHooks = mNativePropHooks;
357   do {
358     const mozilla::dom::NativeProperties* props[] = {
359         propHooks->mNativeProperties.regular,
360         propHooks->mNativeProperties.chromeOnly};
361     for (size_t i = 0; i < ArrayLength(props); ++i) {
362       auto prop = props[i];
363       if (prop && prop->HasConstants()) {
364         for (auto cs = prop->Constants()->specs; cs->name; ++cs) {
365           // We have found one constant here.  We explicitly do not
366           // bother calling isEnabled() here because it's OK to define
367           // potentially extra constants on these shim interfaces.
368           if (index == aIndex) {
369             aConstant.set(cs->value);
370             *aName = ToNewCString(nsDependentCString(cs->name));
371             return NS_OK;
372           }
373           ++index;
374         }
375       }
376     }
377   } while ((propHooks = propHooks->mProtoHooks));
378 
379   // aIndex was bigger than the number of constants we have.
380   return NS_ERROR_INVALID_ARG;
381 }
382 
383 NS_IMETHODIMP
GetInfoForParam(uint16_t aIndex,const nsXPTParamInfo * aParam,nsIInterfaceInfo ** aRetVal)384 ShimInterfaceInfo::GetInfoForParam(uint16_t aIndex,
385                                    const nsXPTParamInfo* aParam,
386                                    nsIInterfaceInfo** aRetVal) {
387   MOZ_ASSERT(false, "This should never be called");
388   return NS_ERROR_NOT_IMPLEMENTED;
389 }
390 
391 NS_IMETHODIMP
GetIIDForParam(uint16_t aIndex,const nsXPTParamInfo * aParam,nsIID ** aRetVal)392 ShimInterfaceInfo::GetIIDForParam(uint16_t aIndex, const nsXPTParamInfo* aParam,
393                                   nsIID** aRetVal) {
394   MOZ_ASSERT(false, "This should never be called");
395   return NS_ERROR_NOT_IMPLEMENTED;
396 }
397 
398 NS_IMETHODIMP
GetTypeForParam(uint16_t aInex,const nsXPTParamInfo * aParam,uint16_t aDimension,nsXPTType * aRetVal)399 ShimInterfaceInfo::GetTypeForParam(uint16_t aInex, const nsXPTParamInfo* aParam,
400                                    uint16_t aDimension, nsXPTType* aRetVal) {
401   MOZ_ASSERT(false, "This should never be called");
402   return NS_ERROR_NOT_IMPLEMENTED;
403 }
404 
405 NS_IMETHODIMP
GetSizeIsArgNumberForParam(uint16_t aInex,const nsXPTParamInfo * aParam,uint16_t aDimension,uint8_t * aRetVal)406 ShimInterfaceInfo::GetSizeIsArgNumberForParam(uint16_t aInex,
407                                               const nsXPTParamInfo* aParam,
408                                               uint16_t aDimension,
409                                               uint8_t* aRetVal) {
410   MOZ_ASSERT(false, "This should never be called");
411   return NS_ERROR_NOT_IMPLEMENTED;
412 }
413 
414 NS_IMETHODIMP
GetInterfaceIsArgNumberForParam(uint16_t aInex,const nsXPTParamInfo * aParam,uint8_t * aRetVal)415 ShimInterfaceInfo::GetInterfaceIsArgNumberForParam(uint16_t aInex,
416                                                    const nsXPTParamInfo* aParam,
417                                                    uint8_t* aRetVal) {
418   MOZ_ASSERT(false, "This should never be called");
419   return NS_ERROR_NOT_IMPLEMENTED;
420 }
421 
422 NS_IMETHODIMP
IsIID(const nsIID * aIID,bool * aRetVal)423 ShimInterfaceInfo::IsIID(const nsIID* aIID, bool* aRetVal) {
424   *aRetVal = mIID.Equals(*aIID);
425   return NS_OK;
426 }
427 
428 NS_IMETHODIMP
GetNameShared(const char ** aName)429 ShimInterfaceInfo::GetNameShared(const char** aName) {
430   *aName = mName.get();
431   return NS_OK;
432 }
433 
434 NS_IMETHODIMP
GetIIDShared(const nsIID ** aIID)435 ShimInterfaceInfo::GetIIDShared(const nsIID** aIID) {
436   *aIID = &mIID;
437   return NS_OK;
438 }
439 
440 NS_IMETHODIMP
IsFunction(bool * aRetVal)441 ShimInterfaceInfo::IsFunction(bool* aRetVal) {
442   *aRetVal = false;
443   return NS_OK;
444 }
445 
446 NS_IMETHODIMP
HasAncestor(const nsIID * aIID,bool * aRetVal)447 ShimInterfaceInfo::HasAncestor(const nsIID* aIID, bool* aRetVal) {
448   *aRetVal = false;
449   return NS_OK;
450 }
451 
NS_IMETHODIMP_(nsresult)452 NS_IMETHODIMP_(nsresult)
453 ShimInterfaceInfo::GetIIDForParamNoAlloc(uint16_t aIndex,
454                                          const nsXPTParamInfo* aInfo,
455                                          nsIID* aIID) {
456   MOZ_ASSERT(false, "This should never be called");
457   return NS_ERROR_NOT_IMPLEMENTED;
458 }
459