Coverage Report

Created: 2018-09-25 14:53

/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 */