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

          Line data    Source code
       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 "mozilla/ArrayUtils.h"
       8             : #include "mozilla/BasicEvents.h"
       9             : 
      10             : #include "DataTransfer.h"
      11             : 
      12             : #include "nsIDOMDocument.h"
      13             : #include "nsISupportsPrimitives.h"
      14             : #include "nsIScriptSecurityManager.h"
      15             : #include "mozilla/dom/DOMStringList.h"
      16             : #include "nsArray.h"
      17             : #include "nsError.h"
      18             : #include "nsIDragService.h"
      19             : #include "nsIClipboard.h"
      20             : #include "nsContentUtils.h"
      21             : #include "nsIContent.h"
      22             : #include "nsIBinaryInputStream.h"
      23             : #include "nsIBinaryOutputStream.h"
      24             : #include "nsIStorageStream.h"
      25             : #include "nsStringStream.h"
      26             : #include "nsCRT.h"
      27             : #include "nsIScriptObjectPrincipal.h"
      28             : #include "nsIScriptContext.h"
      29             : #include "nsIDocument.h"
      30             : #include "nsIScriptGlobalObject.h"
      31             : #include "nsVariant.h"
      32             : #include "mozilla/dom/ContentChild.h"
      33             : #include "mozilla/dom/DataTransferBinding.h"
      34             : #include "mozilla/dom/DataTransferItemList.h"
      35             : #include "mozilla/dom/Directory.h"
      36             : #include "mozilla/dom/Element.h"
      37             : #include "mozilla/dom/FileList.h"
      38             : #include "mozilla/dom/BindingUtils.h"
      39             : #include "mozilla/dom/OSFileSystem.h"
      40             : #include "mozilla/dom/Promise.h"
      41             : #include "nsNetUtil.h"
      42             : 
      43             : namespace mozilla {
      44             : namespace dom {
      45             : 
      46             : NS_IMPL_CYCLE_COLLECTION_CLASS(DataTransfer)
      47             : 
      48           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(DataTransfer)
      49           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mParent)
      50           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mItems)
      51           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragTarget)
      52           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK(mDragImage)
      53           0 :   NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
      54           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
      55           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(DataTransfer)
      56           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mParent)
      57           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mItems)
      58           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragTarget)
      59           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mDragImage)
      60           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
      61           0 : NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(DataTransfer)
      62             : 
      63           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransfer)
      64           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransfer)
      65             : 
      66           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransfer)
      67           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      68           0 :   NS_INTERFACE_MAP_ENTRY(mozilla::dom::DataTransfer)
      69           0 :   NS_INTERFACE_MAP_ENTRY(nsIDOMDataTransfer)
      70           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMDataTransfer)
      71           0 : NS_INTERFACE_MAP_END
      72             : 
      73             : // the size of the array
      74             : const char DataTransfer::sEffects[8][9] = {
      75             :   "none", "copy", "move", "copyMove", "link", "copyLink", "linkMove", "all"
      76             : };
      77             : 
      78             : // Used for custom clipboard types.
      79             : enum CustomClipboardTypeId {
      80             :   eCustomClipboardTypeId_None,
      81             :   eCustomClipboardTypeId_String
      82             : };
      83             : 
      84           0 : DataTransfer::DataTransfer(nsISupports* aParent, EventMessage aEventMessage,
      85           0 :                            bool aIsExternal, int32_t aClipboardType)
      86             :   : mParent(aParent)
      87             :   , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE)
      88             :   , mEffectAllowed(nsIDragService::DRAGDROP_ACTION_UNINITIALIZED)
      89             :   , mEventMessage(aEventMessage)
      90             :   , mCursorState(false)
      91             :   , mReadOnly(true)
      92             :   , mIsExternal(aIsExternal)
      93             :   , mUserCancelled(false)
      94             :   , mIsCrossDomainSubFrameDrop(false)
      95             :   , mClipboardType(aClipboardType)
      96             :   , mDragImageX(0)
      97           0 :   , mDragImageY(0)
      98             : {
      99           0 :   mItems = new DataTransferItemList(this, aIsExternal);
     100             :   // For these events, we want to be able to add data to the data transfer, so
     101             :   // clear the readonly state. Otherwise, the data is already present. For
     102             :   // external usage, cache the data from the native clipboard or drag.
     103           0 :   if (aEventMessage == eCut ||
     104           0 :       aEventMessage == eCopy ||
     105             :       aEventMessage == eDragStart) {
     106           0 :     mReadOnly = false;
     107           0 :   } else if (mIsExternal) {
     108           0 :     if (aEventMessage == ePasteNoFormatting) {
     109           0 :       mEventMessage = ePaste;
     110           0 :       CacheExternalClipboardFormats(true);
     111           0 :     } else if (aEventMessage == ePaste) {
     112           0 :       CacheExternalClipboardFormats(false);
     113           0 :     } else if (aEventMessage >= eDragDropEventFirst &&
     114           0 :                aEventMessage <= eDragDropEventLast) {
     115           0 :       CacheExternalDragFormats();
     116             :     }
     117             :   }
     118           0 : }
     119             : 
     120           0 : DataTransfer::DataTransfer(nsISupports* aParent,
     121             :                            EventMessage aEventMessage,
     122             :                            const uint32_t aEffectAllowed,
     123             :                            bool aCursorState,
     124             :                            bool aIsExternal,
     125             :                            bool aUserCancelled,
     126             :                            bool aIsCrossDomainSubFrameDrop,
     127             :                            int32_t aClipboardType,
     128             :                            DataTransferItemList* aItems,
     129             :                            Element* aDragImage,
     130             :                            uint32_t aDragImageX,
     131           0 :                            uint32_t aDragImageY)
     132             :   : mParent(aParent)
     133             :   , mDropEffect(nsIDragService::DRAGDROP_ACTION_NONE)
     134             :   , mEffectAllowed(aEffectAllowed)
     135             :   , mEventMessage(aEventMessage)
     136             :   , mCursorState(aCursorState)
     137             :   , mReadOnly(true)
     138             :   , mIsExternal(aIsExternal)
     139             :   , mUserCancelled(aUserCancelled)
     140             :   , mIsCrossDomainSubFrameDrop(aIsCrossDomainSubFrameDrop)
     141             :   , mClipboardType(aClipboardType)
     142             :   , mDragImage(aDragImage)
     143             :   , mDragImageX(aDragImageX)
     144           0 :   , mDragImageY(aDragImageY)
     145             : {
     146           0 :   MOZ_ASSERT(mParent);
     147           0 :   MOZ_ASSERT(aItems);
     148             : 
     149             :   // We clone the items array after everything else, so that it has a valid
     150             :   // mParent value
     151           0 :   mItems = aItems->Clone(this);
     152             :   // The items are copied from aItems into mItems. There is no need to copy
     153             :   // the actual data in the items as the data transfer will be read only. The
     154             :   // dragstart event is the only time when items are
     155             :   // modifiable, but those events should have been using the first constructor
     156             :   // above.
     157           0 :   NS_ASSERTION(aEventMessage != eDragStart,
     158             :                "invalid event type for DataTransfer constructor");
     159           0 : }
     160             : 
     161           0 : DataTransfer::~DataTransfer()
     162           0 : {}
     163             : 
     164             : // static
     165             : already_AddRefed<DataTransfer>
     166           0 : DataTransfer::Constructor(const GlobalObject& aGlobal,
     167             :                           const nsAString& aEventType, bool aIsExternal,
     168             :                           ErrorResult& aRv)
     169             : {
     170           0 :   nsAutoCString onEventType("on");
     171           0 :   AppendUTF16toUTF8(aEventType, onEventType);
     172           0 :   nsCOMPtr<nsIAtom> eventTypeAtom = NS_Atomize(onEventType);
     173           0 :   if (!eventTypeAtom) {
     174           0 :     aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
     175           0 :     return nullptr;
     176             :   }
     177             : 
     178           0 :   EventMessage eventMessage = nsContentUtils::GetEventMessage(eventTypeAtom);
     179           0 :   RefPtr<DataTransfer> transfer = new DataTransfer(aGlobal.GetAsSupports(),
     180             :                                                      eventMessage, aIsExternal,
     181           0 :                                                      -1);
     182           0 :   return transfer.forget();
     183             : }
     184             : 
     185             : JSObject*
     186           0 : DataTransfer::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     187             : {
     188           0 :   return DataTransferBinding::Wrap(aCx, this, aGivenProto);
     189             : }
     190             : 
     191             : NS_IMETHODIMP
     192           0 : DataTransfer::GetDropEffect(nsAString& aDropEffect)
     193             : {
     194           0 :   nsString dropEffect;
     195           0 :   GetDropEffect(dropEffect);
     196           0 :   aDropEffect = dropEffect;
     197           0 :   return NS_OK;
     198             : }
     199             : 
     200             : NS_IMETHODIMP
     201           0 : DataTransfer::SetDropEffect(const nsAString& aDropEffect)
     202             : {
     203             :   // the drop effect can only be 'none', 'copy', 'move' or 'link'.
     204           0 :   for (uint32_t e = 0; e <= nsIDragService::DRAGDROP_ACTION_LINK; e++) {
     205           0 :     if (aDropEffect.EqualsASCII(sEffects[e])) {
     206             :       // don't allow copyMove
     207           0 :       if (e != (nsIDragService::DRAGDROP_ACTION_COPY |
     208             :                 nsIDragService::DRAGDROP_ACTION_MOVE)) {
     209           0 :         mDropEffect = e;
     210             :       }
     211           0 :       break;
     212             :     }
     213             :   }
     214             : 
     215           0 :   return NS_OK;
     216             : }
     217             : 
     218             : NS_IMETHODIMP
     219           0 : DataTransfer::GetEffectAllowed(nsAString& aEffectAllowed)
     220             : {
     221           0 :   nsString effectAllowed;
     222           0 :   GetEffectAllowed(effectAllowed);
     223           0 :   aEffectAllowed = effectAllowed;
     224           0 :   return NS_OK;
     225             : }
     226             : 
     227             : NS_IMETHODIMP
     228           0 : DataTransfer::SetEffectAllowed(const nsAString& aEffectAllowed)
     229             : {
     230           0 :   if (aEffectAllowed.EqualsLiteral("uninitialized")) {
     231           0 :     mEffectAllowed = nsIDragService::DRAGDROP_ACTION_UNINITIALIZED;
     232           0 :     return NS_OK;
     233             :   }
     234             : 
     235             :   static_assert(nsIDragService::DRAGDROP_ACTION_NONE == 0,
     236             :                 "DRAGDROP_ACTION_NONE constant is wrong");
     237             :   static_assert(nsIDragService::DRAGDROP_ACTION_COPY == 1,
     238             :                 "DRAGDROP_ACTION_COPY constant is wrong");
     239             :   static_assert(nsIDragService::DRAGDROP_ACTION_MOVE == 2,
     240             :                 "DRAGDROP_ACTION_MOVE constant is wrong");
     241             :   static_assert(nsIDragService::DRAGDROP_ACTION_LINK == 4,
     242             :                 "DRAGDROP_ACTION_LINK constant is wrong");
     243             : 
     244           0 :   for (uint32_t e = 0; e < ArrayLength(sEffects); e++) {
     245           0 :     if (aEffectAllowed.EqualsASCII(sEffects[e])) {
     246           0 :       mEffectAllowed = e;
     247           0 :       break;
     248             :     }
     249             :   }
     250             : 
     251           0 :   return NS_OK;
     252             : }
     253             : 
     254             : NS_IMETHODIMP
     255           0 : DataTransfer::GetDropEffectInt(uint32_t* aDropEffect)
     256             : {
     257           0 :   *aDropEffect = mDropEffect;
     258           0 :   return  NS_OK;
     259             : }
     260             : 
     261             : NS_IMETHODIMP
     262           0 : DataTransfer::SetDropEffectInt(uint32_t aDropEffect)
     263             : {
     264           0 :   mDropEffect = aDropEffect;
     265           0 :   return  NS_OK;
     266             : }
     267             : 
     268             : NS_IMETHODIMP
     269           0 : DataTransfer::GetEffectAllowedInt(uint32_t* aEffectAllowed)
     270             : {
     271           0 :   *aEffectAllowed = mEffectAllowed;
     272           0 :   return  NS_OK;
     273             : }
     274             : 
     275             : NS_IMETHODIMP
     276           0 : DataTransfer::SetEffectAllowedInt(uint32_t aEffectAllowed)
     277             : {
     278           0 :   mEffectAllowed = aEffectAllowed;
     279           0 :   return  NS_OK;
     280             : }
     281             : 
     282             : NS_IMETHODIMP
     283           0 : DataTransfer::GetMozUserCancelled(bool* aUserCancelled)
     284             : {
     285           0 :   *aUserCancelled = MozUserCancelled();
     286           0 :   return NS_OK;
     287             : }
     288             : 
     289             : already_AddRefed<FileList>
     290           0 : DataTransfer::GetFiles(nsIPrincipal& aSubjectPrincipal,
     291             :                        ErrorResult& aRv)
     292             : {
     293           0 :   return mItems->Files(&aSubjectPrincipal);
     294             : }
     295             : 
     296             : NS_IMETHODIMP
     297           0 : DataTransfer::GetFiles(nsIDOMFileList** aFileList)
     298             : {
     299           0 :   if (!aFileList) {
     300           0 :     return NS_ERROR_FAILURE;
     301             :   }
     302             : 
     303             :   // The XPCOM interface is only avaliable to system code, and thus we can
     304             :   // assume the system principal. This is consistent with the previous behavour
     305             :   // of this function, which also assumed the system principal.
     306             :   //
     307             :   // This code is also called from C++ code, which expects it to have a System
     308             :   // Principal, and thus the SubjectPrincipal cannot be used.
     309           0 :   RefPtr<FileList> files = mItems->Files(nsContentUtils::GetSystemPrincipal());
     310             : 
     311           0 :   files.forget(aFileList);
     312           0 :   return NS_OK;
     313             : }
     314             : 
     315             : void
     316           0 : DataTransfer::GetTypes(nsTArray<nsString>& aTypes, CallerType aCallerType) const
     317             : {
     318             :   // When called from bindings, aTypes will be empty, but since we might have
     319             :   // Gecko-internal callers too, clear it to be safe.
     320           0 :   aTypes.Clear();
     321             : 
     322           0 :   const nsTArray<RefPtr<DataTransferItem>>* items = mItems->MozItemsAt(0);
     323           0 :   if (NS_WARN_IF(!items)) {
     324           0 :     return;
     325             :   }
     326             : 
     327           0 :   for (uint32_t i = 0; i < items->Length(); i++) {
     328           0 :     DataTransferItem* item = items->ElementAt(i);
     329           0 :     MOZ_ASSERT(item);
     330             : 
     331           0 :     if (item->ChromeOnly() && aCallerType != CallerType::System) {
     332           0 :       continue;
     333             :     }
     334             : 
     335             :     // NOTE: The reason why we get the internal type here is because we want
     336             :     // kFileMime to appear in the types list for backwards compatibility
     337             :     // reasons.
     338           0 :     nsAutoString type;
     339           0 :     item->GetInternalType(type);
     340           0 :     if (item->Kind() != DataTransferItem::KIND_FILE || type.EqualsASCII(kFileMime)) {
     341             :       // If the entry has kind KIND_STRING or KIND_OTHER we want to add it to the list.
     342           0 :       aTypes.AppendElement(type);
     343             :     }
     344             :   }
     345             : 
     346           0 :   for (uint32_t i = 0; i < mItems->Length(); ++i) {
     347           0 :     bool found = false;
     348           0 :     DataTransferItem* item = mItems->IndexedGetter(i, found);
     349           0 :     MOZ_ASSERT(found);
     350           0 :     if (item->Kind() != DataTransferItem::KIND_FILE) {
     351           0 :       continue;
     352             :     }
     353           0 :     aTypes.AppendElement(NS_LITERAL_STRING("Files"));
     354           0 :     break;
     355             :   }
     356             : }
     357             : 
     358             : void
     359           0 : DataTransfer::GetData(const nsAString& aFormat, nsAString& aData,
     360             :                       nsIPrincipal& aSubjectPrincipal,
     361             :                       ErrorResult& aRv)
     362             : {
     363             :   // return an empty string if data for the format was not found
     364           0 :   aData.Truncate();
     365             : 
     366           0 :   nsCOMPtr<nsIVariant> data;
     367             :   nsresult rv =
     368           0 :     GetDataAtInternal(aFormat, 0, &aSubjectPrincipal,
     369           0 :                       getter_AddRefs(data));
     370           0 :   if (NS_FAILED(rv)) {
     371           0 :     if (rv != NS_ERROR_DOM_INDEX_SIZE_ERR) {
     372           0 :       aRv.Throw(rv);
     373             :     }
     374           0 :     return;
     375             :   }
     376             : 
     377           0 :   if (data) {
     378           0 :     nsAutoString stringdata;
     379           0 :     data->GetAsAString(stringdata);
     380             : 
     381             :     // for the URL type, parse out the first URI from the list. The URIs are
     382             :     // separated by newlines
     383           0 :     nsAutoString lowercaseFormat;
     384           0 :     nsContentUtils::ASCIIToLower(aFormat, lowercaseFormat);
     385             : 
     386           0 :     if (lowercaseFormat.EqualsLiteral("url")) {
     387           0 :       int32_t lastidx = 0, idx;
     388           0 :       int32_t length = stringdata.Length();
     389           0 :       while (lastidx < length) {
     390           0 :         idx = stringdata.FindChar('\n', lastidx);
     391             :         // lines beginning with # are comments
     392           0 :         if (stringdata[lastidx] == '#') {
     393           0 :           if (idx == -1) {
     394           0 :             break;
     395             :           }
     396             :         }
     397             :         else {
     398           0 :           if (idx == -1) {
     399           0 :             aData.Assign(Substring(stringdata, lastidx));
     400             :           } else {
     401           0 :             aData.Assign(Substring(stringdata, lastidx, idx - lastidx));
     402             :           }
     403           0 :           aData = nsContentUtils::TrimWhitespace<nsCRT::IsAsciiSpace>(aData,
     404           0 :                                                                       true);
     405           0 :           return;
     406             :         }
     407           0 :         lastidx = idx + 1;
     408             :       }
     409             :     }
     410             :     else {
     411           0 :       aData = stringdata;
     412             :     }
     413             :   }
     414             : }
     415             : 
     416             : void
     417           0 : DataTransfer::SetData(const nsAString& aFormat, const nsAString& aData,
     418             :                       nsIPrincipal& aSubjectPrincipal,
     419             :                       ErrorResult& aRv)
     420             : {
     421           0 :   RefPtr<nsVariantCC> variant = new nsVariantCC();
     422           0 :   variant->SetAsAString(aData);
     423             : 
     424           0 :   aRv = SetDataAtInternal(aFormat, variant, 0, &aSubjectPrincipal);
     425           0 : }
     426             : 
     427             : void
     428           0 : DataTransfer::ClearData(const Optional<nsAString>& aFormat,
     429             :                         nsIPrincipal& aSubjectPrincipal,
     430             :                         ErrorResult& aRv)
     431             : {
     432           0 :   if (mReadOnly) {
     433           0 :     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     434           0 :     return;
     435             :   }
     436             : 
     437           0 :   if (MozItemCount() == 0) {
     438           0 :     return;
     439             :   }
     440             : 
     441           0 :   if (aFormat.WasPassed()) {
     442           0 :     MozClearDataAtHelper(aFormat.Value(), 0, aSubjectPrincipal, aRv);
     443             :   } else {
     444           0 :     MozClearDataAtHelper(EmptyString(), 0, aSubjectPrincipal, aRv);
     445             :   }
     446             : }
     447             : 
     448             : NS_IMETHODIMP
     449           0 : DataTransfer::GetMozItemCount(uint32_t* aCount)
     450             : {
     451           0 :   *aCount = MozItemCount();
     452           0 :   return NS_OK;
     453             : }
     454             : 
     455             : NS_IMETHODIMP
     456           0 : DataTransfer::GetMozCursor(nsAString& aCursorState)
     457             : {
     458           0 :   nsString cursor;
     459           0 :   GetMozCursor(cursor);
     460           0 :   aCursorState = cursor;
     461           0 :   return NS_OK;
     462             : }
     463             : 
     464             : NS_IMETHODIMP
     465           0 : DataTransfer::SetMozCursor(const nsAString& aCursorState)
     466             : {
     467             :   // Lock the cursor to an arrow during the drag.
     468           0 :   mCursorState = aCursorState.EqualsLiteral("default");
     469             : 
     470           0 :   return NS_OK;
     471             : }
     472             : 
     473             : already_AddRefed<nsINode>
     474           0 : DataTransfer::GetMozSourceNode()
     475             : {
     476           0 :   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
     477           0 :   if (!dragSession) {
     478           0 :     return nullptr;
     479             :   }
     480             : 
     481           0 :   nsCOMPtr<nsIDOMNode> sourceNode;
     482           0 :   dragSession->GetSourceNode(getter_AddRefs(sourceNode));
     483           0 :   nsCOMPtr<nsINode> node = do_QueryInterface(sourceNode);
     484           0 :   if (node && !nsContentUtils::LegacyIsCallerNativeCode()
     485           0 :       && !nsContentUtils::CanCallerAccess(node)) {
     486           0 :     return nullptr;
     487             :   }
     488             : 
     489           0 :   return node.forget();
     490             : }
     491             : 
     492             : NS_IMETHODIMP
     493           0 : DataTransfer::GetMozSourceNode(nsIDOMNode** aSourceNode)
     494             : {
     495           0 :   nsCOMPtr<nsINode> sourceNode = GetMozSourceNode();
     496           0 :   if (!sourceNode) {
     497           0 :     *aSourceNode = nullptr;
     498           0 :     return NS_OK;
     499             :   }
     500             : 
     501           0 :   return CallQueryInterface(sourceNode, aSourceNode);
     502             : }
     503             : 
     504             : already_AddRefed<DOMStringList>
     505           0 : DataTransfer::MozTypesAt(uint32_t aIndex, CallerType aCallerType,
     506             :                          ErrorResult& aRv) const
     507             : {
     508             :   // Only the first item is valid for clipboard events
     509           0 :   if (aIndex > 0 &&
     510           0 :       (mEventMessage == eCut || mEventMessage == eCopy ||
     511           0 :        mEventMessage == ePaste)) {
     512           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     513           0 :     return nullptr;
     514             :   }
     515             : 
     516           0 :   RefPtr<DOMStringList> types = new DOMStringList();
     517           0 :   if (aIndex < MozItemCount()) {
     518             :     // note that you can retrieve the types regardless of their principal
     519           0 :     const nsTArray<RefPtr<DataTransferItem>>& items = *mItems->MozItemsAt(aIndex);
     520             : 
     521           0 :     bool addFile = false;
     522           0 :     for (uint32_t i = 0; i < items.Length(); i++) {
     523           0 :       if (items[i]->ChromeOnly() && aCallerType != CallerType::System) {
     524           0 :         continue;
     525             :       }
     526             : 
     527             :       // NOTE: The reason why we get the internal type here is because we want
     528             :       // kFileMime to appear in the types list for backwards compatibility
     529             :       // reasons.
     530           0 :       nsAutoString type;
     531           0 :       items[i]->GetInternalType(type);
     532           0 :       if (NS_WARN_IF(!types->Add(type))) {
     533           0 :         aRv.Throw(NS_ERROR_FAILURE);
     534           0 :         return nullptr;
     535             :       }
     536             : 
     537           0 :       if (items[i]->Kind() == DataTransferItem::KIND_FILE) {
     538           0 :         addFile = true;
     539             :       }
     540             :     }
     541             : 
     542           0 :     if (addFile) {
     543           0 :       types->Add(NS_LITERAL_STRING("Files"));
     544             :     }
     545             :   }
     546             : 
     547           0 :   return types.forget();
     548             : }
     549             : 
     550             : nsresult
     551           0 : DataTransfer::GetDataAtNoSecurityCheck(const nsAString& aFormat,
     552             :                                        uint32_t aIndex,
     553             :                                        nsIVariant** aData)
     554             : {
     555           0 :   return GetDataAtInternal(aFormat, aIndex,
     556           0 :                            nsContentUtils::GetSystemPrincipal(), aData);
     557             : }
     558             : 
     559             : nsresult
     560           0 : DataTransfer::GetDataAtInternal(const nsAString& aFormat, uint32_t aIndex,
     561             :                                 nsIPrincipal* aSubjectPrincipal,
     562             :                                 nsIVariant** aData)
     563             : {
     564           0 :   *aData = nullptr;
     565             : 
     566           0 :   if (aFormat.IsEmpty()) {
     567           0 :     return NS_OK;
     568             :   }
     569             : 
     570           0 :   if (aIndex >= MozItemCount()) {
     571           0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     572             :   }
     573             : 
     574             :   // Only the first item is valid for clipboard events
     575           0 :   if (aIndex > 0 &&
     576           0 :       (mEventMessage == eCut || mEventMessage == eCopy ||
     577           0 :        mEventMessage == ePaste)) {
     578           0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     579             :   }
     580             : 
     581           0 :   nsAutoString format;
     582           0 :   GetRealFormat(aFormat, format);
     583             : 
     584           0 :   MOZ_ASSERT(aSubjectPrincipal);
     585             : 
     586           0 :   RefPtr<DataTransferItem> item = mItems->MozItemByTypeAt(format, aIndex);
     587           0 :   if (!item) {
     588             :     // The index exists but there's no data for the specified format, in this
     589             :     // case we just return undefined
     590           0 :     return NS_OK;
     591             :   }
     592             : 
     593             :   // If we have chrome only content, and we aren't chrome, don't allow access
     594           0 :   if (!nsContentUtils::IsSystemPrincipal(aSubjectPrincipal) && item->ChromeOnly()) {
     595           0 :     return NS_OK;
     596             :   }
     597             : 
     598             :   // DataTransferItem::Data() handles the principal checks
     599           0 :   ErrorResult result;
     600           0 :   nsCOMPtr<nsIVariant> data = item->Data(aSubjectPrincipal, result);
     601           0 :   if (NS_WARN_IF(!data || result.Failed())) {
     602           0 :     return result.StealNSResult();
     603             :   }
     604             : 
     605           0 :   data.forget(aData);
     606           0 :   return NS_OK;
     607             : }
     608             : 
     609             : void
     610           0 : DataTransfer::MozGetDataAt(JSContext* aCx, const nsAString& aFormat,
     611             :                            uint32_t aIndex,
     612             :                            JS::MutableHandle<JS::Value> aRetval,
     613             :                            nsIPrincipal& aSubjectPrincipal,
     614             :                            mozilla::ErrorResult& aRv)
     615             : {
     616           0 :   nsCOMPtr<nsIVariant> data;
     617           0 :   aRv = GetDataAtInternal(aFormat, aIndex, &aSubjectPrincipal,
     618           0 :                           getter_AddRefs(data));
     619           0 :   if (aRv.Failed()) {
     620           0 :     return;
     621             :   }
     622             : 
     623           0 :   if (!data) {
     624           0 :     aRetval.setNull();
     625           0 :     return;
     626             :   }
     627             : 
     628           0 :   JS::Rooted<JS::Value> result(aCx);
     629           0 :   if (!VariantToJsval(aCx, data, aRetval)) {
     630           0 :     aRv = NS_ERROR_FAILURE;
     631           0 :     return;
     632             :   }
     633             : }
     634             : 
     635             : /* static */ bool
     636           0 : DataTransfer::PrincipalMaySetData(const nsAString& aType,
     637             :                                   nsIVariant* aData,
     638             :                                   nsIPrincipal* aPrincipal)
     639             : {
     640           0 :   if (!nsContentUtils::IsSystemPrincipal(aPrincipal)) {
     641           0 :     DataTransferItem::eKind kind = DataTransferItem::KindFromData(aData);
     642           0 :     if (kind == DataTransferItem::KIND_OTHER) {
     643           0 :       NS_WARNING("Disallowing adding non string/file types to DataTransfer");
     644           0 :       return false;
     645             :     }
     646             : 
     647           0 :     if (aType.EqualsASCII(kFileMime) ||
     648           0 :         aType.EqualsASCII(kFilePromiseMime)) {
     649           0 :       NS_WARNING("Disallowing adding x-moz-file or x-moz-file-promize types to DataTransfer");
     650           0 :       return false;
     651             :     }
     652             :   }
     653           0 :   return true;
     654             : }
     655             : 
     656             : void
     657           0 : DataTransfer::TypesListMayHaveChanged()
     658             : {
     659           0 :   DataTransferBinding::ClearCachedTypesValue(this);
     660           0 : }
     661             : 
     662             : nsresult
     663           0 : DataTransfer::SetDataAtInternal(const nsAString& aFormat, nsIVariant* aData,
     664             :                                 uint32_t aIndex,
     665             :                                 nsIPrincipal* aSubjectPrincipal)
     666             : {
     667           0 :   if (aFormat.IsEmpty()) {
     668           0 :     return NS_OK;
     669             :   }
     670             : 
     671           0 :   if (mReadOnly) {
     672           0 :     return NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR;
     673             :   }
     674             : 
     675             :   // Specifying an index less than the current length will replace an existing
     676             :   // item. Specifying an index equal to the current length will add a new item.
     677           0 :   if (aIndex > MozItemCount()) {
     678           0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     679             :   }
     680             : 
     681             :   // Only the first item is valid for clipboard events
     682           0 :   if (aIndex > 0 &&
     683           0 :       (mEventMessage == eCut || mEventMessage == eCopy ||
     684           0 :        mEventMessage == ePaste)) {
     685           0 :     return NS_ERROR_DOM_INDEX_SIZE_ERR;
     686             :   }
     687             : 
     688             :   // Don't allow the custom type to be assigned.
     689           0 :   if (aFormat.EqualsLiteral(kCustomTypesMime)) {
     690           0 :     return NS_ERROR_DOM_NOT_SUPPORTED_ERR;
     691             :   }
     692             : 
     693           0 :   if (!PrincipalMaySetData(aFormat, aData, aSubjectPrincipal)) {
     694           0 :     return NS_ERROR_DOM_SECURITY_ERR;
     695             :   }
     696             : 
     697           0 :   return SetDataWithPrincipal(aFormat, aData, aIndex, aSubjectPrincipal);
     698             : }
     699             : 
     700             : void
     701           0 : DataTransfer::MozSetDataAt(JSContext* aCx, const nsAString& aFormat,
     702             :                            JS::Handle<JS::Value> aData, uint32_t aIndex,
     703             :                            nsIPrincipal& aSubjectPrincipal,
     704             :                            ErrorResult& aRv)
     705             : {
     706           0 :   nsCOMPtr<nsIVariant> data;
     707           0 :   aRv = nsContentUtils::XPConnect()->JSValToVariant(aCx, aData,
     708           0 :                                                     getter_AddRefs(data));
     709           0 :   if (!aRv.Failed()) {
     710           0 :     aRv = SetDataAtInternal(aFormat, data, aIndex, &aSubjectPrincipal);
     711             :   }
     712           0 : }
     713             : 
     714             : void
     715           0 : DataTransfer::MozClearDataAt(const nsAString& aFormat, uint32_t aIndex,
     716             :                              nsIPrincipal& aSubjectPrincipal,
     717             :                              ErrorResult& aRv)
     718             : {
     719           0 :   if (mReadOnly) {
     720           0 :     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     721           0 :     return;
     722             :   }
     723             : 
     724           0 :   if (aIndex >= MozItemCount()) {
     725           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     726           0 :     return;
     727             :   }
     728             : 
     729             :   // Only the first item is valid for clipboard events
     730           0 :   if (aIndex > 0 &&
     731           0 :       (mEventMessage == eCut || mEventMessage == eCopy ||
     732           0 :        mEventMessage == ePaste)) {
     733           0 :     aRv.Throw(NS_ERROR_DOM_INDEX_SIZE_ERR);
     734           0 :     return;
     735             :   }
     736             : 
     737           0 :   MozClearDataAtHelper(aFormat, aIndex, aSubjectPrincipal, aRv);
     738             : 
     739             :   // If we just cleared the 0-th index, and there are still more than 1 indexes
     740             :   // remaining, MozClearDataAt should cause the 1st index to become the 0th
     741             :   // index. This should _only_ happen when the MozClearDataAt function is
     742             :   // explicitly called by script, as this behavior is inconsistent with spec.
     743             :   // (however, so is the MozClearDataAt API)
     744             : 
     745           0 :   if (aIndex == 0 && mItems->MozItemCount() > 1 &&
     746           0 :       mItems->MozItemsAt(0)->Length() == 0) {
     747           0 :     mItems->PopIndexZero();
     748             :   }
     749             : }
     750             : 
     751             : void
     752           0 : DataTransfer::MozClearDataAtHelper(const nsAString& aFormat, uint32_t aIndex,
     753             :                                    nsIPrincipal& aSubjectPrincipal,
     754             :                                    ErrorResult& aRv)
     755             : {
     756           0 :   MOZ_ASSERT(!mReadOnly);
     757           0 :   MOZ_ASSERT(aIndex < MozItemCount());
     758           0 :   MOZ_ASSERT(aIndex == 0 ||
     759             :              (mEventMessage != eCut && mEventMessage != eCopy &&
     760             :               mEventMessage != ePaste));
     761             : 
     762           0 :   nsAutoString format;
     763           0 :   GetRealFormat(aFormat, format);
     764             : 
     765           0 :   mItems->MozRemoveByTypeAt(format, aIndex, aSubjectPrincipal, aRv);
     766           0 : }
     767             : 
     768             : void
     769           0 : DataTransfer::SetDragImage(Element& aImage, int32_t aX, int32_t aY)
     770             : {
     771           0 :   if (!mReadOnly) {
     772           0 :     mDragImage = &aImage;
     773           0 :     mDragImageX = aX;
     774           0 :     mDragImageY = aY;
     775             :   }
     776           0 : }
     777             : 
     778             : NS_IMETHODIMP
     779           0 : DataTransfer::SetDragImage(nsIDOMElement* aImage, int32_t aX, int32_t aY)
     780             : {
     781           0 :   nsCOMPtr<Element> image = do_QueryInterface(aImage);
     782           0 :   if (image) {
     783           0 :     SetDragImage(*image, aX, aY);
     784             :   }
     785           0 :   return NS_OK;
     786             : }
     787             : 
     788             : void
     789           0 : DataTransfer::UpdateDragImage(Element& aImage, int32_t aX, int32_t aY)
     790             : {
     791           0 :   if (mEventMessage < eDragDropEventFirst || mEventMessage > eDragDropEventLast) {
     792           0 :     return;
     793             :   }
     794             : 
     795           0 :   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
     796           0 :   if (dragSession) {
     797           0 :     dragSession->UpdateDragImage(aImage.AsDOMNode(), aX, aY);
     798             :   }
     799             : }
     800             : 
     801             : already_AddRefed<Promise>
     802           0 : DataTransfer::GetFilesAndDirectories(nsIPrincipal& aSubjectPrincipal,
     803             :                                      ErrorResult& aRv)
     804             : {
     805           0 :   nsCOMPtr<nsINode> parentNode = do_QueryInterface(mParent);
     806           0 :   if (!parentNode) {
     807           0 :     aRv.Throw(NS_ERROR_FAILURE);
     808           0 :     return nullptr;
     809             :   }
     810             : 
     811           0 :   nsCOMPtr<nsIGlobalObject> global = parentNode->OwnerDoc()->GetScopeObject();
     812           0 :   MOZ_ASSERT(global);
     813           0 :   if (!global) {
     814           0 :     aRv.Throw(NS_ERROR_FAILURE);
     815           0 :     return nullptr;
     816             :   }
     817             : 
     818           0 :   RefPtr<Promise> p = Promise::Create(global, aRv);
     819           0 :   if (NS_WARN_IF(aRv.Failed())) {
     820           0 :     return nullptr;
     821             :   }
     822             : 
     823           0 :   RefPtr<FileList> files = mItems->Files(&aSubjectPrincipal);
     824           0 :   if (NS_WARN_IF(!files)) {
     825           0 :     return nullptr;
     826             :   }
     827             : 
     828           0 :   Sequence<RefPtr<File>> filesSeq;
     829           0 :   files->ToSequence(filesSeq, aRv);
     830           0 :   if (NS_WARN_IF(aRv.Failed())) {
     831           0 :     return nullptr;
     832             :   }
     833             : 
     834           0 :   p->MaybeResolve(filesSeq);
     835             : 
     836           0 :   return p.forget();
     837             : }
     838             : 
     839             : already_AddRefed<Promise>
     840           0 : DataTransfer::GetFiles(bool aRecursiveFlag,
     841             :                        nsIPrincipal& aSubjectPrincipal,
     842             :                        ErrorResult& aRv)
     843             : {
     844             :   // Currently we don't support directories.
     845           0 :   return GetFilesAndDirectories(aSubjectPrincipal, aRv);
     846             : }
     847             : 
     848             : void
     849           0 : DataTransfer::AddElement(Element& aElement, ErrorResult& aRv)
     850             : {
     851           0 :   if (mReadOnly) {
     852           0 :     aRv.Throw(NS_ERROR_DOM_NO_MODIFICATION_ALLOWED_ERR);
     853           0 :     return;
     854             :   }
     855             : 
     856           0 :   mDragTarget = &aElement;
     857             : }
     858             : 
     859             : NS_IMETHODIMP
     860           0 : DataTransfer::AddElement(nsIDOMElement* aElement)
     861             : {
     862           0 :   NS_ENSURE_TRUE(aElement, NS_ERROR_NULL_POINTER);
     863             : 
     864           0 :   nsCOMPtr<Element> element = do_QueryInterface(aElement);
     865           0 :   NS_ENSURE_TRUE(element, NS_ERROR_INVALID_ARG);
     866             : 
     867           0 :   ErrorResult rv;
     868           0 :   AddElement(*element, rv);
     869           0 :   return rv.StealNSResult();
     870             : }
     871             : 
     872             : nsresult
     873           0 : DataTransfer::Clone(nsISupports* aParent, EventMessage aEventMessage,
     874             :                     bool aUserCancelled, bool aIsCrossDomainSubFrameDrop,
     875             :                     DataTransfer** aNewDataTransfer)
     876             : {
     877             :   RefPtr<DataTransfer> newDataTransfer =
     878           0 :     new DataTransfer(aParent, aEventMessage, mEffectAllowed, mCursorState,
     879           0 :                      mIsExternal, aUserCancelled, aIsCrossDomainSubFrameDrop,
     880             :                      mClipboardType, mItems, mDragImage, mDragImageX,
     881           0 :                      mDragImageY);
     882             : 
     883           0 :   newDataTransfer.forget(aNewDataTransfer);
     884           0 :   return NS_OK;
     885             : }
     886             : 
     887             : already_AddRefed<nsIArray>
     888           0 : DataTransfer::GetTransferables(nsIDOMNode* aDragTarget)
     889             : {
     890           0 :   MOZ_ASSERT(aDragTarget);
     891             : 
     892           0 :   nsCOMPtr<nsINode> dragNode = do_QueryInterface(aDragTarget);
     893           0 :   if (!dragNode) {
     894           0 :     return nullptr;
     895             :   }
     896             : 
     897           0 :   nsIDocument* doc = dragNode->GetComposedDoc();
     898           0 :   if (!doc) {
     899           0 :     return nullptr;
     900             :   }
     901             : 
     902           0 :   return GetTransferables(doc->GetLoadContext());
     903             : }
     904             : 
     905             : already_AddRefed<nsIArray>
     906           0 : DataTransfer::GetTransferables(nsILoadContext* aLoadContext)
     907             : {
     908           0 :   nsCOMPtr<nsIMutableArray> transArray = nsArray::Create();
     909           0 :   if (!transArray) {
     910           0 :     return nullptr;
     911             :   }
     912             : 
     913           0 :   uint32_t count = MozItemCount();
     914           0 :   for (uint32_t i = 0; i < count; i++) {
     915           0 :     nsCOMPtr<nsITransferable> transferable = GetTransferable(i, aLoadContext);
     916           0 :     if (transferable) {
     917           0 :       transArray->AppendElement(transferable, /*weak =*/ false);
     918             :     }
     919             :   }
     920             : 
     921           0 :   return transArray.forget();
     922             : }
     923             : 
     924             : already_AddRefed<nsITransferable>
     925           0 : DataTransfer::GetTransferable(uint32_t aIndex, nsILoadContext* aLoadContext)
     926             : {
     927           0 :   if (aIndex >= MozItemCount()) {
     928           0 :     return nullptr;
     929             :   }
     930             : 
     931           0 :   const nsTArray<RefPtr<DataTransferItem>>& item = *mItems->MozItemsAt(aIndex);
     932           0 :   uint32_t count = item.Length();
     933           0 :   if (!count) {
     934           0 :     return nullptr;
     935             :   }
     936             : 
     937             :   nsCOMPtr<nsITransferable> transferable =
     938           0 :     do_CreateInstance("@mozilla.org/widget/transferable;1");
     939           0 :   if (!transferable) {
     940           0 :     return nullptr;
     941             :   }
     942           0 :   transferable->Init(aLoadContext);
     943             : 
     944           0 :   nsCOMPtr<nsIStorageStream> storageStream;
     945           0 :   nsCOMPtr<nsIBinaryOutputStream> stream;
     946             : 
     947           0 :   bool added = false;
     948           0 :   bool handlingCustomFormats = true;
     949             : 
     950             :   // When writing the custom data, we need to ensure that there is sufficient
     951             :   // space for a (uint32_t) data ending type, and the null byte character at
     952             :   // the end of the nsCString. We claim that space upfront and store it in
     953             :   // baseLength. This value will be set to zero if a write error occurs
     954             :   // indicating that the data and length are no longer valid.
     955           0 :   const uint32_t baseLength = sizeof(uint32_t) + 1;
     956           0 :   uint32_t totalCustomLength = baseLength;
     957             : 
     958             :   const char* knownFormats[] = {
     959             :     kTextMime, kHTMLMime, kNativeHTMLMime, kRTFMime,
     960             :     kURLMime, kURLDataMime, kURLDescriptionMime, kURLPrivateMime,
     961             :     kPNGImageMime, kJPEGImageMime, kGIFImageMime, kNativeImageMime,
     962             :     kFileMime, kFilePromiseMime, kFilePromiseURLMime,
     963             :     kFilePromiseDestFilename, kFilePromiseDirectoryMime,
     964           0 :     kMozTextInternal, kHTMLContext, kHTMLInfo };
     965             : 
     966             :   /*
     967             :    * Two passes are made here to iterate over all of the types. First, look for
     968             :    * any types that are not in the list of known types. For this pass,
     969             :    * handlingCustomFormats will be true. Data that corresponds to unknown types
     970             :    * will be pulled out and inserted into a single type (kCustomTypesMime) by
     971             :    * writing the data into a stream.
     972             :    *
     973             :    * The second pass will iterate over the formats looking for known types.
     974             :    * These are added as is. The unknown types are all then inserted as a single
     975             :    * type (kCustomTypesMime) in the same position of the first custom type. This
     976             :    * model is used to maintain the format order as best as possible.
     977             :    *
     978             :    * The format of the kCustomTypesMime type is one or more of the following
     979             :    * stored sequentially:
     980             :    *   <32-bit> type (only none or string is supported)
     981             :    *   <32-bit> length of format
     982             :    *   <wide string> format
     983             :    *   <32-bit> length of data
     984             :    *   <wide string> data
     985             :    * A type of eCustomClipboardTypeId_None ends the list, without any following
     986             :    * data.
     987             :    */
     988           0 :   do {
     989           0 :     for (uint32_t f = 0; f < count; f++) {
     990           0 :       RefPtr<DataTransferItem> formatitem = item[f];
     991           0 :       nsCOMPtr<nsIVariant> variant = formatitem->DataNoSecurityCheck();
     992           0 :       if (!variant) { // skip empty items
     993           0 :         continue;
     994             :       }
     995             : 
     996           0 :       nsAutoString type;
     997           0 :       formatitem->GetInternalType(type);
     998             : 
     999             :       // If the data is of one of the well-known formats, use it directly.
    1000           0 :       bool isCustomFormat = true;
    1001           0 :       for (uint32_t f = 0; f < ArrayLength(knownFormats); f++) {
    1002           0 :         if (type.EqualsASCII(knownFormats[f])) {
    1003           0 :           isCustomFormat = false;
    1004           0 :           break;
    1005             :         }
    1006             :       }
    1007             : 
    1008             :       uint32_t lengthInBytes;
    1009           0 :       nsCOMPtr<nsISupports> convertedData;
    1010             : 
    1011           0 :       if (handlingCustomFormats) {
    1012           0 :         if (!ConvertFromVariant(variant, getter_AddRefs(convertedData),
    1013             :                                 &lengthInBytes)) {
    1014           0 :           continue;
    1015             :         }
    1016             : 
    1017             :         // When handling custom types, add the data to the stream if this is a
    1018             :         // custom type. If totalCustomLength is 0, then a write error occurred
    1019             :         // on a previous item, so ignore any others.
    1020           0 :         if (isCustomFormat && totalCustomLength > 0) {
    1021             :           // If it isn't a string, just ignore it. The dataTransfer is cached in
    1022             :           // the drag sesion during drag-and-drop, so non-strings will be
    1023             :           // available when dragging locally.
    1024           0 :           nsCOMPtr<nsISupportsString> str(do_QueryInterface(convertedData));
    1025           0 :           if (str) {
    1026           0 :             nsAutoString data;
    1027           0 :             str->GetData(data);
    1028             : 
    1029           0 :             if (!stream) {
    1030             :               // Create a storage stream to write to.
    1031           0 :               NS_NewStorageStream(1024, UINT32_MAX, getter_AddRefs(storageStream));
    1032             : 
    1033           0 :               nsCOMPtr<nsIOutputStream> outputStream;
    1034           0 :               storageStream->GetOutputStream(0, getter_AddRefs(outputStream));
    1035             : 
    1036           0 :               stream = do_CreateInstance("@mozilla.org/binaryoutputstream;1");
    1037           0 :               stream->SetOutputStream(outputStream);
    1038             :             }
    1039             : 
    1040             :             CheckedInt<uint32_t> formatLength =
    1041           0 :               CheckedInt<uint32_t>(type.Length()) * sizeof(nsString::char_type);
    1042             : 
    1043             :             // The total size of the stream is the format length, the data
    1044             :             // length, two integers to hold the lengths and one integer for
    1045             :             // the string flag. Guard against large data by ignoring any that
    1046             :             // don't fit.
    1047           0 :             CheckedInt<uint32_t> newSize = formatLength + totalCustomLength +
    1048           0 :                                            lengthInBytes + (sizeof(uint32_t) * 3);
    1049           0 :             if (newSize.isValid()) {
    1050             :               // If a write error occurs, set totalCustomLength to 0 so that
    1051             :               // further processing gets ignored.
    1052           0 :               nsresult rv = stream->Write32(eCustomClipboardTypeId_String);
    1053           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    1054           0 :                 totalCustomLength = 0;
    1055           0 :                 continue;
    1056             :               }
    1057           0 :               rv = stream->Write32(formatLength.value());
    1058           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    1059           0 :                 totalCustomLength = 0;
    1060           0 :                 continue;
    1061             :               }
    1062           0 :               rv = stream->WriteBytes((const char *)type.get(), formatLength.value());
    1063           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    1064           0 :                 totalCustomLength = 0;
    1065           0 :                 continue;
    1066             :               }
    1067           0 :               rv = stream->Write32(lengthInBytes);
    1068           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    1069           0 :                 totalCustomLength = 0;
    1070           0 :                 continue;
    1071             :               }
    1072           0 :               rv = stream->WriteBytes((const char *)data.get(), lengthInBytes);
    1073           0 :               if (NS_WARN_IF(NS_FAILED(rv))) {
    1074           0 :                 totalCustomLength = 0;
    1075           0 :                 continue;
    1076             :               }
    1077             : 
    1078           0 :               totalCustomLength = newSize.value();
    1079             :             }
    1080             :           }
    1081             :         }
    1082           0 :       } else if (isCustomFormat && stream) {
    1083             :         // This is the second pass of the loop (handlingCustomFormats is false).
    1084             :         // When encountering the first custom format, append all of the stream
    1085             :         // at this position. If totalCustomLength is 0 indicating a write error
    1086             :         // occurred, or no data has been added to it, don't output anything,
    1087           0 :         if (totalCustomLength > baseLength) {
    1088             :           // Write out an end of data terminator.
    1089           0 :           nsresult rv = stream->Write32(eCustomClipboardTypeId_None);
    1090           0 :           if (NS_SUCCEEDED(rv)) {
    1091           0 :             nsCOMPtr<nsIInputStream> inputStream;
    1092           0 :             storageStream->NewInputStream(0, getter_AddRefs(inputStream));
    1093             : 
    1094             :             RefPtr<nsStringBuffer> stringBuffer =
    1095           0 :               nsStringBuffer::Alloc(totalCustomLength);
    1096             : 
    1097             :             // Subtract off the null terminator when reading.
    1098           0 :             totalCustomLength--;
    1099             : 
    1100             :             // Read the data from the stream and add a null-terminator as
    1101             :             // ToString needs it.
    1102             :             uint32_t amountRead;
    1103           0 :             rv = inputStream->Read(static_cast<char*>(stringBuffer->Data()),
    1104           0 :                               totalCustomLength, &amountRead);
    1105           0 :             if (NS_SUCCEEDED(rv)) {
    1106           0 :               static_cast<char*>(stringBuffer->Data())[amountRead] = 0;
    1107             : 
    1108           0 :               nsCString str;
    1109           0 :               stringBuffer->ToString(totalCustomLength, str);
    1110             :               nsCOMPtr<nsISupportsCString>
    1111           0 :                 strSupports(do_CreateInstance(NS_SUPPORTS_CSTRING_CONTRACTID));
    1112           0 :               strSupports->SetData(str);
    1113             : 
    1114           0 :               nsresult rv = transferable->SetTransferData(kCustomTypesMime,
    1115             :                                                           strSupports,
    1116           0 :                                                           totalCustomLength);
    1117           0 :               if (NS_FAILED(rv)) {
    1118           0 :                 return nullptr;
    1119             :               }
    1120             : 
    1121           0 :               added = true;
    1122             :             }
    1123             :           }
    1124             :         }
    1125             : 
    1126             :         // Clear the stream so it doesn't get used again.
    1127           0 :         stream = nullptr;
    1128             :       } else {
    1129             :         // This is the second pass of the loop and a known type is encountered.
    1130             :         // Add it as is.
    1131           0 :         if (!ConvertFromVariant(variant, getter_AddRefs(convertedData),
    1132             :                                 &lengthInBytes)) {
    1133           0 :           continue;
    1134             :         }
    1135             : 
    1136             :         // The underlying drag code uses text/unicode, so use that instead of
    1137             :         // text/plain
    1138             :         const char* format;
    1139           0 :         NS_ConvertUTF16toUTF8 utf8format(type);
    1140           0 :         if (utf8format.EqualsLiteral(kTextMime)) {
    1141           0 :           format = kUnicodeMime;
    1142             :         } else {
    1143           0 :           format = utf8format.get();
    1144             :         }
    1145             : 
    1146             :         // If a converter is set for a format, set the converter for the
    1147             :         // transferable and don't add the item
    1148             :         nsCOMPtr<nsIFormatConverter> converter =
    1149           0 :           do_QueryInterface(convertedData);
    1150           0 :         if (converter) {
    1151           0 :           transferable->AddDataFlavor(format);
    1152           0 :           transferable->SetConverter(converter);
    1153           0 :           continue;
    1154             :         }
    1155             : 
    1156           0 :         nsresult rv = transferable->SetTransferData(format, convertedData,
    1157           0 :                                                     lengthInBytes);
    1158           0 :         if (NS_FAILED(rv)) {
    1159           0 :           return nullptr;
    1160             :         }
    1161             : 
    1162           0 :         added = true;
    1163             :       }
    1164             :     }
    1165             : 
    1166           0 :     handlingCustomFormats = !handlingCustomFormats;
    1167           0 :   } while (!handlingCustomFormats);
    1168             : 
    1169             :   // only return the transferable if data was successfully added to it
    1170           0 :   if (added) {
    1171           0 :     return transferable.forget();
    1172             :   }
    1173             : 
    1174           0 :   return nullptr;
    1175             : }
    1176             : 
    1177             : bool
    1178           0 : DataTransfer::ConvertFromVariant(nsIVariant* aVariant,
    1179             :                                  nsISupports** aSupports,
    1180             :                                  uint32_t* aLength) const
    1181             : {
    1182           0 :   *aSupports = nullptr;
    1183           0 :   *aLength = 0;
    1184             : 
    1185             :   uint16_t type;
    1186           0 :   aVariant->GetDataType(&type);
    1187           0 :   if (type == nsIDataType::VTYPE_INTERFACE ||
    1188           0 :       type == nsIDataType::VTYPE_INTERFACE_IS) {
    1189           0 :     nsCOMPtr<nsISupports> data;
    1190           0 :     if (NS_FAILED(aVariant->GetAsISupports(getter_AddRefs(data)))) {
    1191           0 :       return false;
    1192             :     }
    1193             : 
    1194           0 :     nsCOMPtr<nsIFlavorDataProvider> fdp = do_QueryInterface(data);
    1195           0 :     if (fdp) {
    1196             :       // for flavour data providers, use kFlavorHasDataProvider (which has the
    1197             :       // value 0) as the length.
    1198           0 :       fdp.forget(aSupports);
    1199           0 :       *aLength = nsITransferable::kFlavorHasDataProvider;
    1200             :     }
    1201             :     else {
    1202             :       // wrap the item in an nsISupportsInterfacePointer
    1203             :       nsCOMPtr<nsISupportsInterfacePointer> ptrSupports =
    1204           0 :         do_CreateInstance(NS_SUPPORTS_INTERFACE_POINTER_CONTRACTID);
    1205           0 :       if (!ptrSupports) {
    1206           0 :         return false;
    1207             :       }
    1208             : 
    1209           0 :       ptrSupports->SetData(data);
    1210           0 :       ptrSupports.forget(aSupports);
    1211             : 
    1212           0 :       *aLength = sizeof(nsISupportsInterfacePointer *);
    1213             :     }
    1214             : 
    1215           0 :     return true;
    1216             :   }
    1217             : 
    1218             :   char16_t* chrs;
    1219           0 :   uint32_t len = 0;
    1220           0 :   nsresult rv = aVariant->GetAsWStringWithSize(&len, &chrs);
    1221           0 :   if (NS_FAILED(rv)) {
    1222           0 :     return false;
    1223             :   }
    1224             : 
    1225           0 :   nsAutoString str;
    1226           0 :   str.Adopt(chrs, len);
    1227             : 
    1228             :   nsCOMPtr<nsISupportsString>
    1229           0 :     strSupports(do_CreateInstance(NS_SUPPORTS_STRING_CONTRACTID));
    1230           0 :   if (!strSupports) {
    1231           0 :     return false;
    1232             :   }
    1233             : 
    1234           0 :   strSupports->SetData(str);
    1235             : 
    1236           0 :   strSupports.forget(aSupports);
    1237             : 
    1238             :   // each character is two bytes
    1239           0 :   *aLength = str.Length() << 1;
    1240             : 
    1241           0 :   return true;
    1242             : }
    1243             : 
    1244             : void
    1245           0 : DataTransfer::ClearAll()
    1246             : {
    1247           0 :   mItems->ClearAllItems();
    1248           0 : }
    1249             : 
    1250             : uint32_t
    1251           0 : DataTransfer::MozItemCount() const
    1252             : {
    1253           0 :   return mItems->MozItemCount();
    1254             : }
    1255             : 
    1256             : nsresult
    1257           0 : DataTransfer::SetDataWithPrincipal(const nsAString& aFormat,
    1258             :                                    nsIVariant* aData,
    1259             :                                    uint32_t aIndex,
    1260             :                                    nsIPrincipal* aPrincipal)
    1261             : {
    1262           0 :   nsAutoString format;
    1263           0 :   GetRealFormat(aFormat, format);
    1264             : 
    1265           0 :   ErrorResult rv;
    1266             :   RefPtr<DataTransferItem> item =
    1267           0 :     mItems->SetDataWithPrincipal(format, aData, aIndex, aPrincipal,
    1268             :                                  /* aInsertOnly = */ false,
    1269             :                                  /* aHidden= */ false,
    1270           0 :                                  rv);
    1271           0 :   return rv.StealNSResult();
    1272             : }
    1273             : 
    1274             : void
    1275           0 : DataTransfer::SetDataWithPrincipalFromOtherProcess(const nsAString& aFormat,
    1276             :                                                    nsIVariant* aData,
    1277             :                                                    uint32_t aIndex,
    1278             :                                                    nsIPrincipal* aPrincipal,
    1279             :                                                    bool aHidden)
    1280             : {
    1281           0 :   if (aFormat.EqualsLiteral(kCustomTypesMime)) {
    1282           0 :     FillInExternalCustomTypes(aData, aIndex, aPrincipal);
    1283             :   } else {
    1284           0 :     nsAutoString format;
    1285           0 :     GetRealFormat(aFormat, format);
    1286             : 
    1287           0 :     ErrorResult rv;
    1288             :     RefPtr<DataTransferItem> item =
    1289           0 :       mItems->SetDataWithPrincipal(format, aData, aIndex, aPrincipal,
    1290           0 :                                    /* aInsertOnly = */ false, aHidden, rv);
    1291           0 :     if (NS_WARN_IF(rv.Failed())) {
    1292           0 :       rv.SuppressException();
    1293             :     }
    1294             :   }
    1295           0 : }
    1296             : 
    1297             : void
    1298           0 : DataTransfer::GetRealFormat(const nsAString& aInFormat,
    1299             :                             nsAString& aOutFormat) const
    1300             : {
    1301             :   // treat text/unicode as equivalent to text/plain
    1302           0 :   nsAutoString lowercaseFormat;
    1303           0 :   nsContentUtils::ASCIIToLower(aInFormat, lowercaseFormat);
    1304           0 :   if (lowercaseFormat.EqualsLiteral("text") ||
    1305           0 :       lowercaseFormat.EqualsLiteral("text/unicode")) {
    1306           0 :     aOutFormat.AssignLiteral("text/plain");
    1307           0 :     return;
    1308             :   }
    1309             : 
    1310           0 :   if (lowercaseFormat.EqualsLiteral("url")) {
    1311           0 :     aOutFormat.AssignLiteral("text/uri-list");
    1312           0 :     return;
    1313             :   }
    1314             : 
    1315           0 :   aOutFormat.Assign(lowercaseFormat);
    1316             : }
    1317             : 
    1318             : nsresult
    1319           0 : DataTransfer::CacheExternalData(const char* aFormat, uint32_t aIndex,
    1320             :                                 nsIPrincipal* aPrincipal, bool aHidden)
    1321             : {
    1322           0 :   ErrorResult rv;
    1323           0 :   RefPtr<DataTransferItem> item;
    1324             : 
    1325           0 :   if (strcmp(aFormat, kUnicodeMime) == 0) {
    1326           0 :     item = mItems->SetDataWithPrincipal(NS_LITERAL_STRING("text/plain"), nullptr,
    1327           0 :                                         aIndex, aPrincipal, false, aHidden, rv);
    1328           0 :     if (NS_WARN_IF(rv.Failed())) {
    1329           0 :       return rv.StealNSResult();
    1330             :     }
    1331           0 :     return NS_OK;
    1332             :   }
    1333             : 
    1334           0 :   if (strcmp(aFormat, kURLDataMime) == 0) {
    1335           0 :     item = mItems->SetDataWithPrincipal(NS_LITERAL_STRING("text/uri-list"), nullptr,
    1336           0 :                                         aIndex, aPrincipal, false, aHidden, rv);
    1337           0 :     if (NS_WARN_IF(rv.Failed())) {
    1338           0 :       return rv.StealNSResult();
    1339             :     }
    1340           0 :     return NS_OK;
    1341             :   }
    1342             : 
    1343           0 :   nsAutoString format;
    1344           0 :   GetRealFormat(NS_ConvertUTF8toUTF16(aFormat), format);
    1345           0 :   item = mItems->SetDataWithPrincipal(format, nullptr, aIndex,
    1346           0 :                                       aPrincipal, false, aHidden, rv);
    1347           0 :   if (NS_WARN_IF(rv.Failed())) {
    1348           0 :     return rv.StealNSResult();
    1349             :   }
    1350           0 :   return NS_OK;
    1351             : }
    1352             : 
    1353             : void
    1354           0 : DataTransfer::CacheExternalDragFormats()
    1355             : {
    1356             :   // Called during the constructor to cache the formats available from an
    1357             :   // external drag. The data associated with each format will be set to null.
    1358             :   // This data will instead only be retrieved in FillInExternalDragData when
    1359             :   // asked for, as it may be time consuming for the source application to
    1360             :   // generate it.
    1361             : 
    1362           0 :   nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
    1363           0 :   if (!dragSession) {
    1364           0 :     return;
    1365             :   }
    1366             : 
    1367             :   // make sure that the system principal is used for external drags
    1368           0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    1369           0 :   nsCOMPtr<nsIPrincipal> sysPrincipal;
    1370           0 :   ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal));
    1371             : 
    1372             :   // there isn't a way to get a list of the formats that might be available on
    1373             :   // all platforms, so just check for the types that can actually be imported
    1374             :   // XXXndeakin there are some other formats but those are platform specific.
    1375             :   // NOTE: kFileMime must have index 0
    1376             :   const char* formats[] = { kFileMime, kHTMLMime, kURLMime, kURLDataMime,
    1377           0 :                             kUnicodeMime, kPNGImageMime };
    1378             : 
    1379             :   uint32_t count;
    1380           0 :   dragSession->GetNumDropItems(&count);
    1381           0 :   for (uint32_t c = 0; c < count; c++) {
    1382           0 :     bool hasFileData = false;
    1383           0 :     dragSession->IsDataFlavorSupported(kFileMime, &hasFileData);
    1384             : 
    1385             :     // First, check for the special format that holds custom types.
    1386             :     bool supported;
    1387           0 :     dragSession->IsDataFlavorSupported(kCustomTypesMime, &supported);
    1388           0 :     if (supported) {
    1389           0 :       FillInExternalCustomTypes(c, sysPrincipal);
    1390             :     }
    1391             : 
    1392           0 :     for (uint32_t f = 0; f < ArrayLength(formats); f++) {
    1393             :       // IsDataFlavorSupported doesn't take an index as an argument and just
    1394             :       // checks if any of the items support a particular flavor, even though
    1395             :       // the GetData method does take an index. Here, we just assume that
    1396             :       // every item being dragged has the same set of flavors.
    1397             :       bool supported;
    1398           0 :       dragSession->IsDataFlavorSupported(formats[f], &supported);
    1399             :       // if the format is supported, add an item to the array with null as
    1400             :       // the data. When retrieved, GetRealData will read the data.
    1401           0 :       if (supported) {
    1402           0 :         CacheExternalData(formats[f], c, sysPrincipal, /* hidden = */ f && hasFileData);
    1403             :       }
    1404             :     }
    1405             :   }
    1406             : }
    1407             : 
    1408             : void
    1409           0 : DataTransfer::CacheExternalClipboardFormats(bool aPlainTextOnly)
    1410             : {
    1411           0 :   NS_ASSERTION(mEventMessage == ePaste,
    1412             :                "caching clipboard data for invalid event");
    1413             : 
    1414             :   // Called during the constructor for paste events to cache the formats
    1415             :   // available on the clipboard. As with CacheExternalDragFormats, the
    1416             :   // data will only be retrieved when needed.
    1417             : 
    1418             :   nsCOMPtr<nsIClipboard> clipboard =
    1419           0 :     do_GetService("@mozilla.org/widget/clipboard;1");
    1420           0 :   if (!clipboard || mClipboardType < 0) {
    1421           0 :     return;
    1422             :   }
    1423             : 
    1424           0 :   nsIScriptSecurityManager* ssm = nsContentUtils::GetSecurityManager();
    1425           0 :   nsCOMPtr<nsIPrincipal> sysPrincipal;
    1426           0 :   ssm->GetSystemPrincipal(getter_AddRefs(sysPrincipal));
    1427             : 
    1428           0 :   if (aPlainTextOnly) {
    1429             :     bool supported;
    1430           0 :     const char* unicodeMime[] = { kUnicodeMime };
    1431           0 :     clipboard->HasDataMatchingFlavors(unicodeMime, 1, mClipboardType,
    1432           0 :                                       &supported);
    1433           0 :     if (supported) {
    1434           0 :       CacheExternalData(kUnicodeMime, 0, sysPrincipal, false);
    1435             :     }
    1436           0 :     return;
    1437             :   }
    1438             : 
    1439             :   // Check if the clipboard has any files
    1440           0 :   bool hasFileData = false;
    1441           0 :   const char *fileMime[] = { kFileMime };
    1442           0 :   clipboard->HasDataMatchingFlavors(fileMime, 1, mClipboardType, &hasFileData);
    1443             : 
    1444             :   // We will be ignoring any application/x-moz-file files found in the paste
    1445             :   // datatransfer within e10s, as they will fail to be sent over IPC. Because of
    1446             :   // that, we will unset hasFileData, whether or not it would have been set.
    1447             :   // (bug 1308007)
    1448           0 :   if (XRE_IsContentProcess()) {
    1449           0 :     hasFileData = false;
    1450             :   }
    1451             : 
    1452             :   // there isn't a way to get a list of the formats that might be available on
    1453             :   // all platforms, so just check for the types that can actually be imported.
    1454             :   // NOTE: kCustomTypesMime must have index 0, kFileMime index 1
    1455             :   const char* formats[] = { kCustomTypesMime, kFileMime, kHTMLMime, kRTFMime,
    1456           0 :                             kURLMime, kURLDataMime, kUnicodeMime, kPNGImageMime };
    1457             : 
    1458           0 :   for (uint32_t f = 0; f < mozilla::ArrayLength(formats); ++f) {
    1459             :     // check each format one at a time
    1460             :     bool supported;
    1461           0 :     clipboard->HasDataMatchingFlavors(&(formats[f]), 1, mClipboardType,
    1462           0 :                                       &supported);
    1463             :     // if the format is supported, add an item to the array with null as
    1464             :     // the data. When retrieved, GetRealData will read the data.
    1465           0 :     if (supported) {
    1466           0 :       if (f == 0) {
    1467           0 :         FillInExternalCustomTypes(0, sysPrincipal);
    1468             :       } else {
    1469             :         // In non-e10s we support pasting files from explorer.exe.
    1470             :         // Unfortunately, we fail to send that data over IPC in e10s, so we
    1471             :         // don't want to add the item to the DataTransfer and end up producing a
    1472             :         // null `application/x-moz-file`. (bug 1308007)
    1473           0 :         if (XRE_IsContentProcess() && f == 1) {
    1474           0 :           continue;
    1475             :         }
    1476             : 
    1477             :         // If we aren't the file data, and we have file data, we want to be hidden
    1478           0 :         CacheExternalData(formats[f], 0, sysPrincipal, /* hidden = */ f != 1 && hasFileData);
    1479             :       }
    1480             :     }
    1481             :   }
    1482             : }
    1483             : 
    1484             : void
    1485           0 : DataTransfer::FillAllExternalData()
    1486             : {
    1487           0 :   if (mIsExternal) {
    1488           0 :     for (uint32_t i = 0; i < MozItemCount(); ++i) {
    1489           0 :       const nsTArray<RefPtr<DataTransferItem>>& items = *mItems->MozItemsAt(i);
    1490           0 :       for (uint32_t j = 0; j < items.Length(); ++j) {
    1491           0 :         MOZ_ASSERT(items[j]->Index() == i);
    1492             : 
    1493           0 :         items[j]->FillInExternalData();
    1494             :       }
    1495             :     }
    1496             :   }
    1497           0 : }
    1498             : 
    1499             : void
    1500           0 : DataTransfer::FillInExternalCustomTypes(uint32_t aIndex,
    1501             :                                         nsIPrincipal* aPrincipal)
    1502             : {
    1503             :   RefPtr<DataTransferItem> item = new DataTransferItem(this,
    1504           0 :                                                        NS_LITERAL_STRING(kCustomTypesMime),
    1505           0 :                                                        DataTransferItem::KIND_STRING);
    1506           0 :   item->SetIndex(aIndex);
    1507             : 
    1508           0 :   nsCOMPtr<nsIVariant> variant = item->DataNoSecurityCheck();
    1509           0 :   if (!variant) {
    1510           0 :     return;
    1511             :   }
    1512             : 
    1513           0 :   FillInExternalCustomTypes(variant, aIndex, aPrincipal);
    1514             : }
    1515             : 
    1516             : void
    1517           0 : DataTransfer::FillInExternalCustomTypes(nsIVariant* aData, uint32_t aIndex,
    1518             :                                         nsIPrincipal* aPrincipal)
    1519             : {
    1520             :   char* chrs;
    1521           0 :   uint32_t len = 0;
    1522           0 :   nsresult rv = aData->GetAsStringWithSize(&len, &chrs);
    1523           0 :   if (NS_FAILED(rv)) {
    1524           0 :     return;
    1525             :   }
    1526             : 
    1527           0 :   nsAutoCString str;
    1528           0 :   str.Adopt(chrs, len);
    1529             : 
    1530           0 :   nsCOMPtr<nsIInputStream> stringStream;
    1531           0 :   NS_NewCStringInputStream(getter_AddRefs(stringStream), str);
    1532             : 
    1533             :   nsCOMPtr<nsIBinaryInputStream> stream =
    1534           0 :     do_CreateInstance("@mozilla.org/binaryinputstream;1");
    1535           0 :   if (!stream) {
    1536           0 :     return;
    1537             :   }
    1538             : 
    1539           0 :   rv = stream->SetInputStream(stringStream);
    1540           0 :   NS_ENSURE_SUCCESS_VOID(rv);
    1541             : 
    1542             :   uint32_t type;
    1543           0 :   do {
    1544           0 :     rv = stream->Read32(&type);
    1545           0 :     NS_ENSURE_SUCCESS_VOID(rv);
    1546           0 :     if (type == eCustomClipboardTypeId_String) {
    1547             :       uint32_t formatLength;
    1548           0 :       rv = stream->Read32(&formatLength);
    1549           0 :       NS_ENSURE_SUCCESS_VOID(rv);
    1550             :       char* formatBytes;
    1551           0 :       rv = stream->ReadBytes(formatLength, &formatBytes);
    1552           0 :       NS_ENSURE_SUCCESS_VOID(rv);
    1553           0 :       nsAutoString format;
    1554           0 :       format.Adopt(reinterpret_cast<char16_t*>(formatBytes),
    1555           0 :                    formatLength / sizeof(char16_t));
    1556             : 
    1557             :       uint32_t dataLength;
    1558           0 :       rv = stream->Read32(&dataLength);
    1559           0 :       NS_ENSURE_SUCCESS_VOID(rv);
    1560             :       char* dataBytes;
    1561           0 :       rv = stream->ReadBytes(dataLength, &dataBytes);
    1562           0 :       NS_ENSURE_SUCCESS_VOID(rv);
    1563           0 :       nsAutoString data;
    1564           0 :       data.Adopt(reinterpret_cast<char16_t*>(dataBytes),
    1565           0 :                  dataLength / sizeof(char16_t));
    1566             : 
    1567           0 :       RefPtr<nsVariantCC> variant = new nsVariantCC();
    1568           0 :       rv = variant->SetAsAString(data);
    1569           0 :       NS_ENSURE_SUCCESS_VOID(rv);
    1570             : 
    1571           0 :       SetDataWithPrincipal(format, variant, aIndex, aPrincipal);
    1572             :     }
    1573           0 :   } while (type != eCustomClipboardTypeId_None);
    1574             : }
    1575             : 
    1576             : } // namespace dom
    1577             : } // namespace mozilla

Generated by: LCOV version 1.13