Bug 1298243 part 5. Notify the DataTransfer whenever its types list changes. r=mystor
authorBoris Zbarsky <bzbarsky@mit.edu>
Mon, 10 Oct 2016 21:07:47 -0400
changeset 317389 d15ec8c5a75f89e80f90491526303255d6d4723c
parent 317388 5725d27a0bf144266dcc7a98062c935fe8e536bf
child 317390 1493789a0ce5976af2c78fb8b8f5dc3fff475ac7
push id30804
push usercbook@mozilla.com
push dateTue, 11 Oct 2016 10:01:46 +0000
treeherdermozilla-central@7ae377917236 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmystor
bugs1298243
milestone52.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1298243 part 5. Notify the DataTransfer whenever its types list changes. r=mystor
dom/events/DataTransfer.cpp
dom/events/DataTransfer.h
dom/events/DataTransferItem.cpp
dom/events/DataTransferItemList.cpp
--- a/dom/events/DataTransfer.cpp
+++ b/dom/events/DataTransfer.cpp
@@ -687,16 +687,23 @@ DataTransfer::PrincipalMaySetData(const 
         aType.EqualsASCII(kFilePromiseMime)) {
       NS_WARNING("Disallowing adding x-moz-file or x-moz-file-promize types to DataTransfer");
       return false;
     }
   }
   return true;
 }
 
+void
+DataTransfer::TypesListMayHaveChanged()
+{
+  // For now do nothing; we'll want to clear our cached types list once we start
+  // caching it.
+}
+
 nsresult
 DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
                                 uint32_t aIndex,
                                 nsIPrincipal* aSubjectPrincipal)
 {
   if (aFormat.IsEmpty()) {
     return NS_OK;
   }
--- a/dom/events/DataTransfer.h
+++ b/dom/events/DataTransfer.h
@@ -284,16 +284,21 @@ public:
   // converts some formats used for compatibility in aInFormat into aOutFormat.
   // Text and text/unicode become text/plain, and URL becomes text/uri-list
   void GetRealFormat(const nsAString& aInFormat, nsAString& aOutFormat) const;
 
   static bool PrincipalMaySetData(const nsAString& aFormat,
                                   nsIVariant* aData,
                                   nsIPrincipal* aPrincipal);
 
+  // Notify the DataTransfer that the list returned from GetTypes may have
+  // changed.  This can happen due to items we care about for purposes of
+  // GetTypes being added or removed or changing item kinds.
+  void TypesListMayHaveChanged();
+
 protected:
 
   // caches text and uri-list data formats that exist in the drag service or
   // clipboard for retrieval later.
   nsresult CacheExternalData(const char* aFormat, uint32_t aIndex,
                              nsIPrincipal* aPrincipal, bool aHidden);
 
   // caches the formats that exist in the drag service that were added by an
--- a/dom/events/DataTransferItem.cpp
+++ b/dom/events/DataTransferItem.cpp
@@ -219,21 +219,20 @@ DataTransferItem::FillInExternalData()
         supportscstr->GetData(str);
         variant->SetAsACString(str);
       }
     }
   }
 
   SetData(variant);
 
-#ifdef DEBUG
   if (oldKind != Kind()) {
     NS_WARNING("Clipboard data provided by the OS does not match predicted kind");
+    mDataTransfer->TypesListMayHaveChanged();
   }
-#endif
 }
 
 already_AddRefed<File>
 DataTransferItem::GetAsFile(const Maybe<nsIPrincipal*>& aSubjectPrincipal,
                             ErrorResult& aRv)
 {
   MOZ_ASSERT(aSubjectPrincipal.isSome());
 
--- a/dom/events/DataTransferItemList.cpp
+++ b/dom/events/DataTransferItemList.cpp
@@ -365,16 +365,20 @@ DataTransferItemList::SetDataWithPrincip
                         || !subsumes))) {
           aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
           return nullptr;
         }
         item->SetPrincipal(aPrincipal);
 
         DataTransferItem::eKind oldKind = item->Kind();
         item->SetData(aData);
+        if (oldKind != item->Kind()) {
+          // Types list may have changed, even if aIndex == 0.
+          mDataTransfer->TypesListMayHaveChanged();
+        }
 
         if (aIndex != 0) {
           // If the item changes from being a file to not a file or vice-versa,
           // its presence in the mItems array may need to change.
           if (item->Kind() == DataTransferItem::KIND_FILE &&
               oldKind != DataTransferItem::KIND_FILE) {
             // not file => file
             mItems.AppendElement(item);
@@ -428,19 +432,25 @@ DataTransferItemList::AppendNewItem(uint
   item->SetChromeOnly(aHidden);
 
   mIndexedItems[aIndex].AppendElement(item);
 
   // We only want to add the item to the main mItems list if the index we are
   // adding to is 0, or the item we are adding is a file. If we add an item
   // which is not a file to a non-zero index, invariants could be broken.
   // (namely the invariant that there are not 2 non-file entries in the items
-  // array with the same type)
-  if (!aHidden && (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0)) {
-    mItems.AppendElement(item);
+  // array with the same type).
+  //
+  // We also want to update our DataTransfer's type list any time we're adding a
+  // KIND_FILE item, or an item at index 0.
+  if (item->Kind() == DataTransferItem::KIND_FILE || aIndex == 0) {
+    if (!aHidden) {
+      mItems.AppendElement(item);
+    }
+    mDataTransfer->TypesListMayHaveChanged();
   }
 
   return item;
 }
 
 const nsTArray<RefPtr<DataTransferItem>>*
 DataTransferItemList::MozItemsAt(uint32_t aIndex) // -- INDEXED
 {
@@ -470,16 +480,17 @@ DataTransferItemList::PopIndexZero()
 
 void
 DataTransferItemList::ClearAllItems()
 {
   // We always need to have index 0, so don't delete that one
   mItems.Clear();
   mIndexedItems.Clear();
   mIndexedItems.SetLength(1);
+  mDataTransfer->TypesListMayHaveChanged();
 
   // Re-generate files (into an empty list)
   RegenerateFiles();
 }
 
 void
 DataTransferItemList::ClearDataHelper(DataTransferItem* aItem,
                                       uint32_t aIndexHint,
@@ -512,16 +523,18 @@ DataTransferItemList::ClearDataHelper(Da
   MOZ_ASSERT(aItem->Index() < mIndexedItems.Length());
   nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[aItem->Index()];
   if (aMozOffsetHint < items.Length() && aItem == items[aMozOffsetHint]) {
     items.RemoveElementAt(aMozOffsetHint);
   } else {
     items.RemoveElement(aItem);
   }
 
+  mDataTransfer->TypesListMayHaveChanged();
+
   // Check if we should remove the index. We never remove index 0.
   if (items.Length() == 0 && aItem->Index() != 0) {
     mIndexedItems.RemoveElementAt(aItem->Index());
 
     // Update the index of every element which has now been shifted
     for (uint32_t i = aItem->Index(); i < mIndexedItems.Length(); i++) {
       nsTArray<RefPtr<DataTransferItem>>& items = mIndexedItems[i];
       for (uint32_t j = 0; j < items.Length(); j++) {