Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/dom/events/DataTransferItemList.cpp
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
#include "DataTransferItemList.h"
8
9
#include "nsContentUtils.h"
10
#include "nsIGlobalObject.h"
11
#include "nsIClipboard.h"
12
#include "nsIScriptObjectPrincipal.h"
13
#include "nsIScriptGlobalObject.h"
14
#include "nsIScriptContext.h"
15
#include "nsISupportsPrimitives.h"
16
#include "nsQueryObject.h"
17
#include "nsVariant.h"
18
#include "mozilla/ContentEvents.h"
19
#include "mozilla/EventForwards.h"
20
#include "mozilla/storage/Variant.h"
21
#include "mozilla/dom/DataTransferItemListBinding.h"
22
23
namespace mozilla {
24
namespace dom {
25
26
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DataTransferItemList, mDataTransfer, mItems,
27
                                      mIndexedItems, mFiles)
28
NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransferItemList)
29
NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransferItemList)
30
31
0
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransferItemList)
32
0
  NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
33
0
  NS_INTERFACE_MAP_ENTRY(nsISupports)
34
0
NS_INTERFACE_MAP_END
35
36
JSObject*
37
DataTransferItemList::WrapObject(JSContext* aCx,
38
                                 JS::Handle<JSObject*> aGivenProto)
39
0
{
40
0
  return DataTransferItemList_Binding::Wrap(aCx, this, aGivenProto);
41
0
}
42
43
already_AddRefed<DataTransferItemList>
44
DataTransferItemList::Clone(DataTransfer* aDataTransfer) const
45
0
{
46
0
  RefPtr<DataTransferItemList> list =
47
0
    new DataTransferItemList(aDataTransfer, mIsExternal);
48
0
49
0
  // We need to clone the mItems and mIndexedItems lists while keeping the same
50
0
  // correspondences between the mIndexedItems and mItems lists (namely, if an
51
0
  // item is in mIndexedItems, and mItems it must have the same new identity)
52
0
53
0
  // First, we copy over indexedItems, and clone every entry. Then, we go over
54
0
  // mItems. For every entry, we use its mIndex property to locate it in
55
0
  // mIndexedItems on the original DataTransferItemList, and then copy over the
56
0
  // reference from the same index pair on the new DataTransferItemList
57
0
58
0
  list->mIndexedItems.SetLength(mIndexedItems.Length());
59
0
  list->mItems.SetLength(mItems.Length());
60
0
61
0
  // Copy over mIndexedItems, cloning every entry
62
0
  for (uint32_t i = 0; i < mIndexedItems.Length(); i++) {
63
0
    const nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
64
0
    nsTArray<RefPtr<DataTransferItem>>& newItems = list->mIndexedItems[i];
65
0
    newItems.SetLength(items.Length());
66
0
    for (uint32_t j = 0; j < items.Length(); j++) {
67
0
      newItems[j] = items[j]->Clone(aDataTransfer);
68
0
    }
69
0
  }
70
0
71
0
  // Copy over mItems, getting the actual entries from mIndexedItems
72
0
  for (uint32_t i = 0; i < mItems.Length(); i++) {
73
0
    uint32_t index = mItems[i]->Index();
74
0
    MOZ_ASSERT(index < mIndexedItems.Length());
75
0
    uint32_t subIndex = mIndexedItems[index].IndexOf(mItems[i]);
76
0
77
0
    // Copy over the reference
78
0
    list->mItems[i] = list->mIndexedItems[index][subIndex];
79
0
  }
80
0
81
0
  return list.forget();
82
0
}
83
84
void
85
DataTransferItemList::Remove(uint32_t aIndex,
86
                             nsIPrincipal& aSubjectPrincipal,
87
                             ErrorResult& aRv)
88
0
{
89
0
  if (mDataTransfer->IsReadOnly()) {
90
0
    aRv.Throw(NS_ERROR_DOM_INVALID_STATE_ERR);
91
0
    return;
92
0
  }
93
0
94
0
  if (aIndex >= Length()) {
95
0
    return;
96
0
  }
97
0
98
0
  ClearDataHelper(mItems[aIndex], aIndex, -1, aSubjectPrincipal, aRv);
99
0
}
100
101
DataTransferItem*
102
DataTransferItemList::IndexedGetter(uint32_t aIndex, bool& aFound) const
103
0
{
104
0
  if (aIndex >= mItems.Length()) {
105
0
    aFound = false;
106
0
    return nullptr;
107
0
  }
108
0
109
0
  MOZ_ASSERT(mItems[aIndex]);
110
0
  aFound = true;
111
0
  return mItems[aIndex];
112
0
}
113
114
uint32_t
115
DataTransferItemList::MozItemCount() const
116
0
{
117
0
  uint32_t length = mIndexedItems.Length();
118
0
  // XXX: Compat hack - Index 0 always exists due to changes in internals, but
119
0
  // if it is empty, scripts using the moz* APIs should see it as not existing.
120
0
  if (length == 1 && mIndexedItems[0].IsEmpty()) {
121
0
    return 0;
122
0
  }
123
0
  return length;
124
0
}
125
126
void
127
DataTransferItemList::Clear(nsIPrincipal& aSubjectPrincipal,
128
                            ErrorResult& aRv)
129
0
{
130
0
  if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
131
0
    return;
132
0
  }
133
0
134
0
  uint32_t count = Length();
135
0
  for (uint32_t i = 0; i < count; i++) {
136
0
    // We always remove the last item first, to avoid moving items around in
137
0
    // memory as much
138
0
    Remove(Length() - 1, aSubjectPrincipal, aRv);
139
0
    ENSURE_SUCCESS_VOID(aRv);
140
0
  }
141
0
142
0
  MOZ_ASSERT(Length() == 0);
143
0
}
144
145
DataTransferItem*
146
DataTransferItemList::Add(const nsAString& aData,
147
                          const nsAString& aType,
148
                          nsIPrincipal& aSubjectPrincipal,
149
                          ErrorResult& aRv)
150
0
{
151
0
  if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
152
0
    return nullptr;
153
0
  }
154
0
155
0
  RefPtr<nsVariantCC> data(new nsVariantCC());
156
0
  data->SetAsAString(aData);
157
0
158
0
  nsAutoString format;
159
0
  mDataTransfer->GetRealFormat(aType, format);
160
0
161
0
  if (!DataTransfer::PrincipalMaySetData(format, data, &aSubjectPrincipal)) {
162
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
163
0
    return nullptr;
164
0
  }
165
0
166
0
  // We add the textual data to index 0. We set aInsertOnly to true, as we don't
167
0
  // want to update an existing entry if it is already present, as per the spec.
168
0
  RefPtr<DataTransferItem> item =
169
0
    SetDataWithPrincipal(format, data, 0, &aSubjectPrincipal,
170
0
                         /* aInsertOnly = */ true,
171
0
                         /* aHidden = */ false,
172
0
                         aRv);
173
0
  if (NS_WARN_IF(aRv.Failed())) {
174
0
    return nullptr;
175
0
  }
176
0
  MOZ_ASSERT(item->Kind() != DataTransferItem::KIND_FILE);
177
0
178
0
  return item;
179
0
}
180
181
DataTransferItem*
182
DataTransferItemList::Add(File& aData,
183
                          nsIPrincipal& aSubjectPrincipal,
184
                          ErrorResult& aRv)
185
0
{
186
0
  if (mDataTransfer->IsReadOnly()) {
187
0
    return nullptr;
188
0
  }
189
0
190
0
  nsCOMPtr<nsISupports> supports = do_QueryObject(&aData);
191
0
  nsCOMPtr<nsIWritableVariant> data = new nsVariant();
192
0
  data->SetAsISupports(supports);
193
0
194
0
  nsAutoString type;
195
0
  aData.GetType(type);
196
0
197
0
  if (!DataTransfer::PrincipalMaySetData(type, data, &aSubjectPrincipal)) {
198
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
199
0
    return nullptr;
200
0
  }
201
0
202
0
  // We need to add this as a new item, as multiple files can't exist in the
203
0
  // same item in the Moz DataTransfer layout. It will be appended at the end of
204
0
  // the internal specced layout.
205
0
  uint32_t index = mIndexedItems.Length();
206
0
  RefPtr<DataTransferItem> item =
207
0
    SetDataWithPrincipal(type, data, index, &aSubjectPrincipal,
208
0
                         /* aInsertOnly = */ true,
209
0
                         /* aHidden = */ false,
210
0
                         aRv);
211
0
  if (NS_WARN_IF(aRv.Failed())) {
212
0
    return nullptr;
213
0
  }
214
0
  MOZ_ASSERT(item->Kind() == DataTransferItem::KIND_FILE);
215
0
216
0
  return item;
217
0
}
218
219
already_AddRefed<FileList>
220
DataTransferItemList::Files(nsIPrincipal* aPrincipal)
221
0
{
222
0
  // The DataTransfer can hold data with varying principals, coming from
223
0
  // different windows. This means that permissions checks need to be made when
224
0
  // accessing data from the DataTransfer. With the accessor methods, this is
225
0
  // checked by DataTransferItem::Data(), however with files, we keep a cached
226
0
  // live copy of the files list for spec compliance.
227
0
  //
228
0
  // A DataTransfer is only exposed to one webpage, and chrome code. The chrome
229
0
  // code should be able to see all files on the DataTransfer, while the webpage
230
0
  // should only be able to see the files it can see. As chrome code doesn't
231
0
  // need as strict spec compliance as web visible code, we generate a new
232
0
  // FileList object every time you access the Files list from chrome code, but
233
0
  // re-use the cached one when accessing from non-chrome code.
234
0
  //
235
0
  // It is not legal to expose an identical DataTransfer object is to multiple
236
0
  // different principals without using the `Clone` method or similar to copy it
237
0
  // first. If that happens, this method will assert, and return nullptr in
238
0
  // release builds. If this functionality is required in the future, a more
239
0
  // advanced caching mechanism for the FileList objects will be required.
240
0
  RefPtr<FileList> files;
241
0
  if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
242
0
    files = new FileList(mDataTransfer);
243
0
    GenerateFiles(files, aPrincipal);
244
0
    return files.forget();
245
0
  }
246
0
247
0
  if (!mFiles) {
248
0
    mFiles = new FileList(mDataTransfer);
249
0
    mFilesPrincipal = aPrincipal;
250
0
    RegenerateFiles();
251
0
  }
252
0
253
0
  if (!aPrincipal->Subsumes(mFilesPrincipal)) {
254
0
    MOZ_ASSERT(false, "This DataTransfer should only be accessed by the system "
255
0
               "and a single principal");
256
0
    return nullptr;
257
0
  }
258
0
259
0
  files = mFiles;
260
0
  return files.forget();
261
0
}
262
263
void
264
DataTransferItemList::MozRemoveByTypeAt(const nsAString& aType,
265
                                        uint32_t aIndex,
266
                                        nsIPrincipal& aSubjectPrincipal,
267
                                        ErrorResult& aRv)
268
0
{
269
0
  if (NS_WARN_IF(mDataTransfer->IsReadOnly() ||
270
0
                 aIndex >= mIndexedItems.Length())) {
271
0
    return;
272
0
  }
273
0
274
0
  bool removeAll = aType.IsEmpty();
275
0
276
0
  nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aIndex];
277
0
  uint32_t count = items.Length();
278
0
  // We remove the last item of the list repeatedly - that way we don't
279
0
  // have to worry about modifying the loop iterator
280
0
  if (removeAll) {
281
0
    for (uint32_t i = 0; i < count; ++i) {
282
0
      uint32_t index = items.Length() - 1;
283
0
      MOZ_ASSERT(index == count - i - 1);
284
0
285
0
      ClearDataHelper(items[index], -1, index, aSubjectPrincipal, aRv);
286
0
      if (NS_WARN_IF(aRv.Failed())) {
287
0
        return;
288
0
      }
289
0
    }
290
0
291
0
    // items is no longer a valid reference, as removing the last element from
292
0
    // it via ClearDataHelper invalidated it. so we can't MOZ_ASSERT that the
293
0
    // length is now 0.
294
0
    return;
295
0
  }
296
0
297
0
  for (uint32_t i = 0; i < count; ++i) {
298
0
    // NOTE: As this is a moz-prefixed API, it works based on internal types.
299
0
    nsAutoString type;
300
0
    items[i]->GetInternalType(type);
301
0
    if (type == aType) {
302
0
      ClearDataHelper(items[i], -1, i, aSubjectPrincipal, aRv);
303
0
      return;
304
0
    }
305
0
  }
306
0
}
307
308
DataTransferItem*
309
DataTransferItemList::MozItemByTypeAt(const nsAString& aType, uint32_t aIndex)
310
0
{
311
0
  if (NS_WARN_IF(aIndex >= mIndexedItems.Length())) {
312
0
    return nullptr;
313
0
  }
314
0
315
0
  uint32_t count = mIndexedItems[aIndex].Length();
316
0
  for (uint32_t i = 0; i < count; i++) {
317
0
    RefPtr<DataTransferItem> item = mIndexedItems[aIndex][i];
318
0
    // NOTE: As this is a moz-prefixed API it works on internal types
319
0
    nsString type;
320
0
    item->GetInternalType(type);
321
0
    if (type.Equals(aType)) {
322
0
      return item;
323
0
    }
324
0
  }
325
0
326
0
  return nullptr;
327
0
}
328
329
already_AddRefed<DataTransferItem>
330
DataTransferItemList::SetDataWithPrincipal(const nsAString& aType,
331
                                           nsIVariant* aData,
332
                                           uint32_t aIndex,
333
                                           nsIPrincipal* aPrincipal,
334
                                           bool aInsertOnly,
335
                                           bool aHidden,
336
                                           ErrorResult& aRv)
337
0
{
338
0
  if (aIndex < mIndexedItems.Length()) {
339
0
    nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aIndex];
340
0
    uint32_t count = items.Length();
341
0
    for (uint32_t i = 0; i < count; i++) {
342
0
      RefPtr<DataTransferItem> item = items[i];
343
0
      nsString type;
344
0
      item->GetInternalType(type);
345
0
      if (type.Equals(aType)) {
346
0
        if (NS_WARN_IF(aInsertOnly)) {
347
0
          aRv.Throw(NS_ERROR_DOM_NOT_SUPPORTED_ERR);
348
0
          return nullptr;
349
0
        }
350
0
351
0
        // don't allow replacing data that has a stronger principal
352
0
        bool subsumes;
353
0
        if (NS_WARN_IF(item->Principal() && aPrincipal &&
354
0
                       (NS_FAILED(aPrincipal->Subsumes(item->Principal(),
355
0
                                                       &subsumes))
356
0
                        || !subsumes))) {
357
0
          aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
358
0
          return nullptr;
359
0
        }
360
0
        item->SetPrincipal(aPrincipal);
361
0
362
0
        DataTransferItem::eKind oldKind = item->Kind();
363
0
        item->SetData(aData);
364
0
365
0
        mDataTransfer->TypesListMayHaveChanged();
366
0
367
0
        if (aIndex != 0) {
368
0
          // If the item changes from being a file to not a file or vice-versa,
369
0
          // its presence in the mItems array may need to change.
370
0
          if (item->Kind() == DataTransferItem::KIND_FILE &&
371
0
              oldKind != DataTransferItem::KIND_FILE) {
372
0
            // not file => file
373
0
            mItems.AppendElement(item);
374
0
          } else if (item->Kind() != DataTransferItem::KIND_FILE &&
375
0
                     oldKind == DataTransferItem::KIND_FILE) {
376
0
            // file => not file
377
0
            mItems.RemoveElement(item);
378
0
          }
379
0
        }
380
0
381
0
        // Regenerate the Files array if we have modified a file's status
382
0
        if (item->Kind() == DataTransferItem::KIND_FILE ||
383
0
            oldKind == DataTransferItem::KIND_FILE) {
384
0
          RegenerateFiles();
385
0
        }
386
0
387
0
        return item.forget();
388
0
      }
389
0
    }
390
0
  } else {
391
0
    // Make sure that we aren't adding past the end of the mIndexedItems array.
392
0
    // XXX Should this be a MOZ_ASSERT instead?
393
0
    aIndex = mIndexedItems.Length();
394
0
  }
395
0
396
0
  // Add the new item
397
0
  RefPtr<DataTransferItem> item = AppendNewItem(aIndex, aType, aData, aPrincipal, aHidden);
398
0
399
0
  if (item->Kind() == DataTransferItem::KIND_FILE) {
400
0
    RegenerateFiles();
401
0
  }
402
0
403
0
  return item.forget();
404
0
}
405
406
DataTransferItem*
407
DataTransferItemList::AppendNewItem(uint32_t aIndex,
408
                                    const nsAString& aType,
409
                                    nsIVariant* aData,
410
                                    nsIPrincipal* aPrincipal,
411
                                    bool aHidden)
412
0
{
413
0
  if (mIndexedItems.Length() <= aIndex) {
414
0
    MOZ_ASSERT(mIndexedItems.Length() == aIndex);
415
0
    mIndexedItems.AppendElement();
416
0
  }
417
0
  RefPtr<DataTransferItem> item = new DataTransferItem(mDataTransfer, aType);
418
0
  item->SetIndex(aIndex);
419
0
  item->SetPrincipal(aPrincipal);
420
0
  item->SetData(aData);
421
0
  item->SetChromeOnly(aHidden);
422
0
423
0
  mIndexedItems[aIndex].AppendElement(item);
424
0
425
0
  // We only want to add the item to the main mItems list if the index we are
426
0
  // adding to is 0, or the item we are adding is a file. If we add an item
427
0
  // which is not a file to a non-zero index, invariants could be broken.
428
0
  // (namely the invariant that there are not 2 non-file entries in the items
429
0
  // array with the same type).
430
0
  //
431
0
  // We also want to update our DataTransfer's type list any time we're adding a
432
0
  // KIND_FILE item, or an item at index 0.
433
0
  if (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0) {
434
0
    if (!aHidden) {
435
0
      mItems.AppendElement(item);
436
0
    }
437
0
    mDataTransfer->TypesListMayHaveChanged();
438
0
  }
439
0
440
0
  return item;
441
0
}
442
443
const nsTArray<RefPtr<DataTransferItem>>*
444
DataTransferItemList::MozItemsAt(uint32_t aIndex) // -- INDEXED
445
0
{
446
0
  if (aIndex >= mIndexedItems.Length()) {
447
0
    return nullptr;
448
0
  }
449
0
450
0
  return &mIndexedItems[aIndex];
451
0
}
452
453
void
454
DataTransferItemList::PopIndexZero()
455
0
{
456
0
  MOZ_ASSERT(mIndexedItems.Length() > 1);
457
0
  MOZ_ASSERT(mIndexedItems[0].IsEmpty());
458
0
459
0
  mIndexedItems.RemoveElementAt(0);
460
0
461
0
  // Update the index of every element which has now been shifted
462
0
  for (uint32_t i = 0; i < mIndexedItems.Length(); i++) {
463
0
    nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
464
0
    for (uint32_t j = 0; j < items.Length(); j++) {
465
0
      items[j]->SetIndex(i);
466
0
    }
467
0
  }
468
0
}
469
470
void
471
DataTransferItemList::ClearAllItems()
472
0
{
473
0
  // We always need to have index 0, so don't delete that one
474
0
  mItems.Clear();
475
0
  mIndexedItems.Clear();
476
0
  mIndexedItems.SetLength(1);
477
0
  mDataTransfer->TypesListMayHaveChanged();
478
0
479
0
  // Re-generate files (into an empty list)
480
0
  RegenerateFiles();
481
0
}
482
483
void
484
DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
485
                                      uint32_t aIndexHint,
486
                                      uint32_t aMozOffsetHint,
487
                                      nsIPrincipal& aSubjectPrincipal,
488
                                      ErrorResult& aRv)
489
0
{
490
0
  MOZ_ASSERT(aItem);
491
0
  if (NS_WARN_IF(mDataTransfer->IsReadOnly())) {
492
0
    return;
493
0
  }
494
0
495
0
  if (aItem->Principal() && !aSubjectPrincipal.Subsumes(aItem->Principal())) {
496
0
    aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
497
0
    return;
498
0
  }
499
0
500
0
  // Check if the aIndexHint is actually the index, and then remove the item
501
0
  // from aItems
502
0
  bool found;
503
0
  if (IndexedGetter(aIndexHint, found) == aItem) {
504
0
    mItems.RemoveElementAt(aIndexHint);
505
0
  } else {
506
0
    mItems.RemoveElement(aItem);
507
0
  }
508
0
509
0
  // Check if the aMozIndexHint and aMozOffsetHint are actually the index and
510
0
  // offset, and then remove them from mIndexedItems
511
0
  MOZ_ASSERT(aItem->Index() < mIndexedItems.Length());
512
0
  nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aItem->Index()];
513
0
  if (aMozOffsetHint < items.Length() && aItem == items[aMozOffsetHint]) {
514
0
    items.RemoveElementAt(aMozOffsetHint);
515
0
  } else {
516
0
    items.RemoveElement(aItem);
517
0
  }
518
0
519
0
  mDataTransfer->TypesListMayHaveChanged();
520
0
521
0
  // Check if we should remove the index. We never remove index 0.
522
0
  if (items.Length() == 0 && aItem->Index() != 0) {
523
0
    mIndexedItems.RemoveElementAt(aItem->Index());
524
0
525
0
    // Update the index of every element which has now been shifted
526
0
    for (uint32_t i = aItem->Index(); i < mIndexedItems.Length(); i++) {
527
0
      nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
528
0
      for (uint32_t j = 0; j < items.Length(); j++) {
529
0
        items[j]->SetIndex(i);
530
0
      }
531
0
    }
532
0
  }
533
0
534
0
  // Give the removed item the invalid index
535
0
  aItem->SetIndex(-1);
536
0
537
0
  if (aItem->Kind() == DataTransferItem::KIND_FILE) {
538
0
    RegenerateFiles();
539
0
  }
540
0
}
541
542
void
543
DataTransferItemList::RegenerateFiles()
544
0
{
545
0
  // We don't want to regenerate the files list unless we already have a files
546
0
  // list. That way we can avoid the unnecessary work if the user never touches
547
0
  // the files list.
548
0
  if (mFiles) {
549
0
    // We clear the list rather than performing smaller updates, because it
550
0
    // simplifies the logic greatly on this code path, which should be very
551
0
    // infrequently used.
552
0
    mFiles->Clear();
553
0
554
0
    DataTransferItemList::GenerateFiles(mFiles, mFilesPrincipal);
555
0
  }
556
0
}
557
558
void
559
DataTransferItemList::GenerateFiles(FileList* aFiles,
560
                                    nsIPrincipal* aFilesPrincipal)
561
0
{
562
0
  MOZ_ASSERT(aFiles);
563
0
  MOZ_ASSERT(aFilesPrincipal);
564
0
565
0
  // For non-system principals, the Files list should be empty if the
566
0
  // DataTransfer is protected.
567
0
  if (!nsContentUtils::IsSystemPrincipal(aFilesPrincipal) &&
568
0
      mDataTransfer->IsProtected()) {
569
0
    return;
570
0
  }
571
0
572
0
  uint32_t count = Length();
573
0
  for (uint32_t i = 0; i < count; i++) {
574
0
    bool found;
575
0
    RefPtr<DataTransferItem> item = IndexedGetter(i, found);
576
0
    MOZ_ASSERT(found);
577
0
578
0
    if (item->Kind() == DataTransferItem::KIND_FILE) {
579
0
      RefPtr<File> file = item->GetAsFile(*aFilesPrincipal, IgnoreErrors());
580
0
      if (NS_WARN_IF(!file)) {
581
0
        continue;
582
0
      }
583
0
      aFiles->Append(file);
584
0
    }
585
0
  }
586
0
}
587
588
} // namespace mozilla
589
} // namespace dom