/work/obj-fuzz/dist/include/mozilla/dom/DataTransfer.h
Line | Count | Source (jump to first uncovered line) |
1 | | /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
2 | | /* vim: set ts=8 sts=2 et sw=2 tw=80: */ |
3 | | /* This Source Code Form is subject to the terms of the Mozilla Public |
4 | | * License, v. 2.0. If a copy of the MPL was not distributed with this |
5 | | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
6 | | |
7 | | #ifndef mozilla_dom_DataTransfer_h |
8 | | #define mozilla_dom_DataTransfer_h |
9 | | |
10 | | #include "nsString.h" |
11 | | #include "nsTArray.h" |
12 | | #include "nsIVariant.h" |
13 | | #include "nsIPrincipal.h" |
14 | | #include "nsIDragService.h" |
15 | | #include "nsCycleCollectionParticipant.h" |
16 | | |
17 | | #include "mozilla/ArrayUtils.h" |
18 | | #include "mozilla/Assertions.h" |
19 | | #include "mozilla/Attributes.h" |
20 | | #include "mozilla/EventForwards.h" |
21 | | #include "mozilla/dom/BindingDeclarations.h" |
22 | | #include "mozilla/dom/File.h" |
23 | | |
24 | | class nsINode; |
25 | | class nsITransferable; |
26 | | class nsILoadContext; |
27 | | |
28 | | namespace mozilla { |
29 | | |
30 | | class EventStateManager; |
31 | | |
32 | | namespace dom { |
33 | | |
34 | | class DataTransferItem; |
35 | | class DataTransferItemList; |
36 | | class DOMStringList; |
37 | | class Element; |
38 | | class FileList; |
39 | | class Promise; |
40 | | template<typename T> class Optional; |
41 | | |
42 | | #define NS_DATATRANSFER_IID \ |
43 | | { 0x6c5f90d1, 0xa886, 0x42c8, \ |
44 | | { 0x85, 0x06, 0x10, 0xbe, 0x5c, 0x0d, 0xc6, 0x77 } } |
45 | | |
46 | | class DataTransfer final : public nsISupports, |
47 | | public nsWrapperCache |
48 | | { |
49 | | public: |
50 | | NS_DECLARE_STATIC_IID_ACCESSOR(NS_DATATRANSFER_IID) |
51 | | |
52 | | NS_DECL_CYCLE_COLLECTING_ISUPPORTS |
53 | | |
54 | | NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(DataTransfer) |
55 | | |
56 | | friend class mozilla::EventStateManager; |
57 | | |
58 | | /// An enum which represents which "Drag Data Store Mode" the DataTransfer is |
59 | | /// in according to the spec. |
60 | | enum class Mode : uint8_t { |
61 | | ReadWrite, |
62 | | ReadOnly, |
63 | | Protected, |
64 | | }; |
65 | | |
66 | | protected: |
67 | | |
68 | | // hide the default constructor |
69 | | DataTransfer(); |
70 | | |
71 | | // this constructor is used only by the Clone method to copy the fields as |
72 | | // needed to a new data transfer. |
73 | | // NOTE: Do not call this method directly. |
74 | | DataTransfer(nsISupports* aParent, |
75 | | EventMessage aEventMessage, |
76 | | const uint32_t aEffectAllowed, |
77 | | bool aCursorState, |
78 | | bool aIsExternal, |
79 | | bool aUserCancelled, |
80 | | bool aIsCrossDomainSubFrameDrop, |
81 | | int32_t aClipboardType, |
82 | | DataTransferItemList* aItems, |
83 | | Element* aDragImage, |
84 | | uint32_t aDragImageX, |
85 | | uint32_t aDragImageY); |
86 | | |
87 | | ~DataTransfer(); |
88 | | |
89 | | static const char sEffects[8][9]; |
90 | | |
91 | | public: |
92 | | // Constructor for DataTransfer. |
93 | | // |
94 | | // aIsExternal must only be true when used to create a dataTransfer for a |
95 | | // paste or a drag that was started without using a data transfer. The |
96 | | // latter will occur when an external drag occurs, that is, a drag where the |
97 | | // source is another application, or a drag is started by calling the drag |
98 | | // service directly. For clipboard operations, aClipboardType indicates |
99 | | // which clipboard to use, from nsIClipboard, or -1 for non-clipboard |
100 | | // operations, or if access to the system clipboard should not be allowed. |
101 | | DataTransfer(nsISupports* aParent, EventMessage aEventMessage, |
102 | | bool aIsExternal, int32_t aClipboardType); |
103 | | |
104 | | virtual JSObject* |
105 | | WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override; |
106 | | |
107 | | nsISupports* GetParentObject() const |
108 | 0 | { |
109 | 0 | return mParent; |
110 | 0 | } |
111 | | |
112 | | void SetParentObject(nsISupports* aNewParent) |
113 | 0 | { |
114 | 0 | MOZ_ASSERT(aNewParent); |
115 | 0 | // Setting the parent after we've been wrapped is pointless, so |
116 | 0 | // make sure we aren't wrapped yet. |
117 | 0 | MOZ_ASSERT(!GetWrapperPreserveColor()); |
118 | 0 | mParent = aNewParent; |
119 | 0 | } |
120 | | |
121 | | static already_AddRefed<DataTransfer> |
122 | | Constructor(const GlobalObject& aGlobal, ErrorResult& aRv); |
123 | | |
124 | | /** |
125 | | * The actual effect that will be used, and should always be one of the |
126 | | * possible values of effectAllowed. |
127 | | * |
128 | | * For dragstart, drag and dragleave events, the dropEffect is initialized |
129 | | * to none. Any value assigned to the dropEffect will be set, but the value |
130 | | * isn't used for anything. |
131 | | * |
132 | | * For the dragenter and dragover events, the dropEffect will be initialized |
133 | | * based on what action the user is requesting. How this is determined is |
134 | | * platform specific, but typically the user can press modifier keys to |
135 | | * adjust which action is desired. Within an event handler for the dragenter |
136 | | * and dragover events, the dropEffect should be modified if the action the |
137 | | * user is requesting is not the one that is desired. |
138 | | * |
139 | | * For the drop and dragend events, the dropEffect will be initialized to |
140 | | * the action that was desired, which will be the value that the dropEffect |
141 | | * had after the last dragenter or dragover event. |
142 | | * |
143 | | * Possible values: |
144 | | * copy - a copy of the source item is made at the new location |
145 | | * move - an item is moved to a new location |
146 | | * link - a link is established to the source at the new location |
147 | | * none - the item may not be dropped |
148 | | * |
149 | | * Assigning any other value has no effect and retains the old value. |
150 | | */ |
151 | | void GetDropEffect(nsAString& aDropEffect) |
152 | 0 | { |
153 | 0 | aDropEffect.AssignASCII(sEffects[mDropEffect]); |
154 | 0 | } |
155 | | void SetDropEffect(const nsAString& aDropEffect); |
156 | | |
157 | | /* |
158 | | * Specifies the effects that are allowed for this drag. You may set this in |
159 | | * the dragstart event to set the desired effects for the source, and within |
160 | | * the dragenter and dragover events to set the desired effects for the |
161 | | * target. The value is not used for other events. |
162 | | * |
163 | | * Possible values: |
164 | | * copy - a copy of the source item is made at the new location |
165 | | * move - an item is moved to a new location |
166 | | * link - a link is established to the source at the new location |
167 | | * copyLink, copyMove, linkMove, all - combinations of the above |
168 | | * none - the item may not be dropped |
169 | | * uninitialized - the default value when the effect has not been set, |
170 | | * equivalent to all. |
171 | | * |
172 | | * Assigning any other value has no effect and retains the old value. |
173 | | */ |
174 | | void GetEffectAllowed(nsAString& aEffectAllowed) |
175 | 0 | { |
176 | 0 | if (mEffectAllowed == nsIDragService::DRAGDROP_ACTION_UNINITIALIZED) { |
177 | 0 | aEffectAllowed.AssignLiteral("uninitialized"); |
178 | 0 | } else { |
179 | 0 | aEffectAllowed.AssignASCII(sEffects[mEffectAllowed]); |
180 | 0 | } |
181 | 0 | } |
182 | | void SetEffectAllowed(const nsAString& aEffectAllowed); |
183 | | |
184 | | /** |
185 | | * Set the image to be used for dragging if a custom one is desired. Most of |
186 | | * the time, this would not be set, as a default image is created from the |
187 | | * node that was dragged. |
188 | | * |
189 | | * If the node is an HTML img element, an HTML canvas element or a XUL image |
190 | | * element, the image data is used. Otherwise, image should be a visible |
191 | | * node and the drag image will be created from this. If image is null, any |
192 | | * custom drag image is cleared and the default is used instead. |
193 | | * |
194 | | * The coordinates specify the offset into the image where the mouse cursor |
195 | | * should be. To center the image for instance, use values that are half the |
196 | | * width and height. |
197 | | * |
198 | | * @param image a node to use |
199 | | * @param x the horizontal offset |
200 | | * @param y the vertical offset |
201 | | */ |
202 | | void SetDragImage(Element& aElement, int32_t aX, int32_t aY); |
203 | | void UpdateDragImage(Element& aElement, int32_t aX, int32_t aY); |
204 | | |
205 | | void GetTypes(nsTArray<nsString>& aTypes, CallerType aCallerType) const; |
206 | | |
207 | | void GetData(const nsAString& aFormat, nsAString& aData, |
208 | | nsIPrincipal& aSubjectPrincipal, |
209 | | ErrorResult& aRv); |
210 | | |
211 | | void SetData(const nsAString& aFormat, const nsAString& aData, |
212 | | nsIPrincipal& aSubjectPrincipal, |
213 | | ErrorResult& aRv); |
214 | | |
215 | | void ClearData(const mozilla::dom::Optional<nsAString>& aFormat, |
216 | | nsIPrincipal& aSubjectPrincipal, |
217 | | mozilla::ErrorResult& aRv); |
218 | | |
219 | | /** |
220 | | * Holds a list of all the local files available on this data transfer. |
221 | | * A dataTransfer containing no files will return an empty list, and an |
222 | | * invalid index access on the resulting file list will return null. |
223 | | */ |
224 | | already_AddRefed<FileList> |
225 | | GetFiles(nsIPrincipal& aSubjectPrincipal); |
226 | | |
227 | | already_AddRefed<Promise> |
228 | | GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal, |
229 | | mozilla::ErrorResult& aRv); |
230 | | |
231 | | already_AddRefed<Promise> |
232 | | GetFiles(bool aRecursiveFlag, |
233 | | nsIPrincipal& aSubjectPrincipal, |
234 | | ErrorResult& aRv); |
235 | | |
236 | | |
237 | | void AddElement(Element& aElement, mozilla::ErrorResult& aRv); |
238 | | |
239 | | uint32_t MozItemCount() const; |
240 | | |
241 | | void GetMozCursor(nsAString& aCursor) |
242 | 0 | { |
243 | 0 | if (mCursorState) { |
244 | 0 | aCursor.AssignLiteral("default"); |
245 | 0 | } else { |
246 | 0 | aCursor.AssignLiteral("auto"); |
247 | 0 | } |
248 | 0 | } |
249 | | void SetMozCursor(const nsAString& aCursor); |
250 | | |
251 | | already_AddRefed<DOMStringList> MozTypesAt(uint32_t aIndex, |
252 | | CallerType aCallerType, |
253 | | mozilla::ErrorResult& aRv) const; |
254 | | |
255 | | void MozClearDataAt(const nsAString& aFormat, uint32_t aIndex, |
256 | | nsIPrincipal& aSubjectPrincipal, |
257 | | mozilla::ErrorResult& aRv); |
258 | | |
259 | | void MozSetDataAt(JSContext* aCx, const nsAString& aFormat, |
260 | | JS::Handle<JS::Value> aData, uint32_t aIndex, |
261 | | nsIPrincipal& aSubjectPrincipal, |
262 | | mozilla::ErrorResult& aRv); |
263 | | |
264 | | void MozGetDataAt(JSContext* aCx, const nsAString& aFormat, |
265 | | uint32_t aIndex, JS::MutableHandle<JS::Value> aRetval, |
266 | | nsIPrincipal& aSubjectPrincipal, |
267 | | mozilla::ErrorResult& aRv); |
268 | | |
269 | | bool MozUserCancelled() const |
270 | 0 | { |
271 | 0 | return mUserCancelled; |
272 | 0 | } |
273 | | |
274 | | already_AddRefed<nsINode> GetMozSourceNode(); |
275 | | |
276 | | /* |
277 | | * Integer version of dropEffect, set to one of the constants in nsIDragService. |
278 | | */ |
279 | | uint32_t DropEffectInt() const |
280 | 0 | { |
281 | 0 | return mDropEffect; |
282 | 0 | } |
283 | | void SetDropEffectInt(uint32_t aDropEffectInt) |
284 | 0 | { |
285 | 0 | MOZ_RELEASE_ASSERT(aDropEffectInt < ArrayLength(sEffects), |
286 | 0 | "Bogus drop effect value"); |
287 | 0 | mDropEffect = aDropEffectInt; |
288 | 0 | } |
289 | | |
290 | | /* |
291 | | * Integer version of effectAllowed, set to one or a combination of the |
292 | | * constants in nsIDragService. |
293 | | */ |
294 | | uint32_t EffectAllowedInt() const |
295 | 0 | { |
296 | 0 | return mEffectAllowed; |
297 | 0 | } |
298 | | |
299 | | void GetMozTriggeringPrincipalURISpec(nsAString& aPrincipalURISpec); |
300 | | |
301 | | mozilla::dom::Element* GetDragTarget() const |
302 | 0 | { |
303 | 0 | return mDragTarget; |
304 | 0 | } |
305 | | |
306 | | nsresult GetDataAtNoSecurityCheck(const nsAString& aFormat, uint32_t aIndex, |
307 | | nsIVariant** aData); |
308 | | |
309 | 0 | DataTransferItemList* Items() const { |
310 | 0 | return mItems; |
311 | 0 | } |
312 | | |
313 | | // Returns the current "Drag Data Store Mode" of the DataTransfer. This |
314 | | // determines what modifications may be performed on the DataTransfer, and |
315 | | // what data may be read from it. |
316 | 0 | Mode GetMode() const { |
317 | 0 | return mMode; |
318 | 0 | } |
319 | | void SetMode(Mode aMode); |
320 | | |
321 | | // Helper method. Is true if the DataTransfer's mode is ReadOnly or Protected, |
322 | | // which means that the DataTransfer cannot be modified. |
323 | | bool IsReadOnly() const { |
324 | | return mMode != Mode::ReadWrite; |
325 | | } |
326 | | // Helper method. Is true if the DataTransfer's mode is Protected, which means |
327 | | // that DataTransfer type information may be read, but data may not be. |
328 | | bool IsProtected() const { |
329 | | return mMode == Mode::Protected; |
330 | | } |
331 | | |
332 | | int32_t ClipboardType() const { |
333 | | return mClipboardType; |
334 | | } |
335 | | EventMessage GetEventMessage() const { |
336 | | return mEventMessage; |
337 | | } |
338 | | bool IsCrossDomainSubFrameDrop() const { |
339 | | return mIsCrossDomainSubFrameDrop; |
340 | | } |
341 | | |
342 | | // converts the data into an array of nsITransferable objects to be used for |
343 | | // drag and drop or clipboard operations. |
344 | | already_AddRefed<nsIArray> GetTransferables(nsINode* aDragTarget); |
345 | | |
346 | | already_AddRefed<nsIArray> |
347 | | GetTransferables(nsILoadContext* aLoadContext); |
348 | | |
349 | | // converts the data for a single item at aIndex into an nsITransferable |
350 | | // object. |
351 | | already_AddRefed<nsITransferable> |
352 | | GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext); |
353 | | |
354 | | // converts the data in the variant to an nsISupportString if possible or |
355 | | // an nsISupports or null otherwise. |
356 | | bool ConvertFromVariant(nsIVariant* aVariant, |
357 | | nsISupports** aSupports, |
358 | | uint32_t* aLength) const; |
359 | | |
360 | | // Disconnects the DataTransfer from the Drag Data Store. If the |
361 | | // dom.dataTransfer.disconnect pref is enabled, this will clear the |
362 | | // DataTransfer and set it to the `Protected` state, otherwise this method is |
363 | | // a no-op. |
364 | | void Disconnect(); |
365 | | |
366 | | // clears all of the data |
367 | | void ClearAll(); |
368 | | |
369 | | // Similar to SetData except also specifies the principal to store. |
370 | | // aData may be null when called from CacheExternalDragFormats or |
371 | | // CacheExternalClipboardFormats. |
372 | | nsresult SetDataWithPrincipal(const nsAString& aFormat, |
373 | | nsIVariant* aData, |
374 | | uint32_t aIndex, |
375 | | nsIPrincipal* aPrincipal, |
376 | | bool aHidden=false); |
377 | | |
378 | | // Variation of SetDataWithPrincipal with handles extracting |
379 | | // kCustomTypesMime data into separate types. |
380 | | void SetDataWithPrincipalFromOtherProcess(const nsAString& aFormat, |
381 | | nsIVariant* aData, |
382 | | uint32_t aIndex, |
383 | | nsIPrincipal* aPrincipal, |
384 | | bool aHidden); |
385 | | |
386 | | // returns a weak reference to the drag image |
387 | | Element* GetDragImage(int32_t* aX, int32_t* aY) const |
388 | 0 | { |
389 | 0 | *aX = mDragImageX; |
390 | 0 | *aY = mDragImageY; |
391 | 0 | return mDragImage; |
392 | 0 | } |
393 | | |
394 | | // This method makes a copy of the DataTransfer object, with a few properties |
395 | | // changed, and the mode updated to reflect the correct mode for the given |
396 | | // event. This method is used during the drag operation to generate the |
397 | | // DataTransfer objects for each event after `dragstart`. Event objects will |
398 | | // lazily clone the DataTransfer stored in the DragSession (which is a clone |
399 | | // of the DataTransfer used in the `dragstart` event) when requested. |
400 | | nsresult Clone(nsISupports* aParent, EventMessage aEventMessage, |
401 | | bool aUserCancelled, bool aIsCrossDomainSubFrameDrop, |
402 | | DataTransfer** aResult); |
403 | | |
404 | | // converts some formats used for compatibility in aInFormat into aOutFormat. |
405 | | // Text and text/unicode become text/plain, and URL becomes text/uri-list |
406 | | void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat) const; |
407 | | |
408 | | static bool PrincipalMaySetData(const nsAString& aFormat, |
409 | | nsIVariant* aData, |
410 | | nsIPrincipal* aPrincipal); |
411 | | |
412 | | // Notify the DataTransfer that the list returned from GetTypes may have |
413 | | // changed. This can happen due to items we care about for purposes of |
414 | | // GetTypes being added or removed or changing item kinds. |
415 | | void TypesListMayHaveChanged(); |
416 | | |
417 | | // Testing method used to emulate internal DataTransfer management. |
418 | | // NOTE: Please don't use this. See the comments in the webidl for more. |
419 | | already_AddRefed<DataTransfer> MozCloneForEvent(const nsAString& aEvent, |
420 | | ErrorResult& aRv); |
421 | | |
422 | | // Retrieve a list of clipboard formats supported |
423 | | // |
424 | | // If kFileMime is supported, then it will be placed either at |
425 | | // index 0 or at index 1 in aResult |
426 | | static void |
427 | | GetExternalClipboardFormats(const int32_t& aWhichClipboard, |
428 | | const bool& aPlainTextOnly, |
429 | | nsTArray<nsCString>* aResult); |
430 | | |
431 | | // Returns true if moz* APIs should be exposed (true for chrome code or if |
432 | | // dom.datatransfer.moz pref is enabled). |
433 | | // The affected moz* APIs are mozItemCount, mozTypesAt, mozClearDataAt, mozSetDataAt, mozGetDataAt |
434 | | static bool MozAtAPIsEnabled(JSContext* cx, JSObject* obj); |
435 | | |
436 | | protected: |
437 | | |
438 | | // caches text and uri-list data formats that exist in the drag service or |
439 | | // clipboard for retrieval later. |
440 | | nsresult CacheExternalData(const char* aFormat, uint32_t aIndex, |
441 | | nsIPrincipal* aPrincipal, bool aHidden); |
442 | | |
443 | | // caches the formats that exist in the drag service that were added by an |
444 | | // external drag |
445 | | void CacheExternalDragFormats(); |
446 | | |
447 | | // caches the formats that exist in the clipboard |
448 | | void CacheExternalClipboardFormats(bool aPlainTextOnly); |
449 | | |
450 | | FileList* GetFilesInternal(ErrorResult& aRv, nsIPrincipal* aSubjectPrincipal); |
451 | | nsresult GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex, |
452 | | nsIPrincipal* aSubjectPrincipal, |
453 | | nsIVariant** aData); |
454 | | |
455 | | nsresult SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData, |
456 | | uint32_t aIndex, nsIPrincipal* aSubjectPrincipal); |
457 | | |
458 | | friend class ContentParent; |
459 | | friend class Clipboard; |
460 | | |
461 | | void FillAllExternalData(); |
462 | | |
463 | | void FillInExternalCustomTypes(uint32_t aIndex, nsIPrincipal* aPrincipal); |
464 | | |
465 | | void FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex, |
466 | | nsIPrincipal* aPrincipal); |
467 | | |
468 | | void MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex, |
469 | | nsIPrincipal& aSubjectPrincipal, |
470 | | mozilla::ErrorResult& aRv); |
471 | | |
472 | | nsCOMPtr<nsISupports> mParent; |
473 | | |
474 | | // the drop effect and effect allowed |
475 | | uint32_t mDropEffect; |
476 | | uint32_t mEffectAllowed; |
477 | | |
478 | | // the event message this data transfer is for. This will correspond to an |
479 | | // event->mMessage value. |
480 | | EventMessage mEventMessage; |
481 | | |
482 | | // Indicates the behavior of the cursor during drag operations |
483 | | bool mCursorState; |
484 | | |
485 | | // The current "Drag Data Store Mode" which the DataTransfer is in. |
486 | | Mode mMode; |
487 | | |
488 | | // true for drags started without a data transfer, for example, those from |
489 | | // another application. |
490 | | bool mIsExternal; |
491 | | |
492 | | // true if the user cancelled the drag. Used only for the dragend event. |
493 | | bool mUserCancelled; |
494 | | |
495 | | // true if this is a cross-domain drop from a subframe where access to the |
496 | | // data should be prevented |
497 | | bool mIsCrossDomainSubFrameDrop; |
498 | | |
499 | | // Indicates which clipboard type to use for clipboard operations. Ignored for |
500 | | // drag and drop. |
501 | | int32_t mClipboardType; |
502 | | |
503 | | // The items contained with the DataTransfer |
504 | | RefPtr<DataTransferItemList> mItems; |
505 | | |
506 | | // the target of the drag. The drag and dragend events will fire at this. |
507 | | nsCOMPtr<mozilla::dom::Element> mDragTarget; |
508 | | |
509 | | // the custom drag image and coordinates within the image. If mDragImage is |
510 | | // null, the default image is created from the drag target. |
511 | | nsCOMPtr<mozilla::dom::Element> mDragImage; |
512 | | uint32_t mDragImageX; |
513 | | uint32_t mDragImageY; |
514 | | }; |
515 | | |
516 | | NS_DEFINE_STATIC_IID_ACCESSOR(DataTransfer, NS_DATATRANSFER_IID) |
517 | | |
518 | | } // namespace dom |
519 | | } // namespace mozilla |
520 | | |
521 | | #endif /* mozilla_dom_DataTransfer_h */ |