LCOV - code coverage report
Current view: top level - dom/events - DataTransferItemList.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 243 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 26 0.0 %
Legend: Lines: hit not hit

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

Generated by: LCOV version 1.13