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

          Line data    Source code
       1             : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
       2             : /* This Source Code Form is subject to the terms of the Mozilla Public
       3             :  * License, v. 2.0. If a copy of the MPL was not distributed with this
       4             :  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
       5             : 
       6             : #include "DataTransferItem.h"
       7             : #include "DataTransferItemList.h"
       8             : 
       9             : #include "mozilla/ContentEvents.h"
      10             : #include "mozilla/EventForwards.h"
      11             : #include "mozilla/dom/DataTransferItemBinding.h"
      12             : #include "mozilla/dom/Directory.h"
      13             : #include "mozilla/dom/Event.h"
      14             : #include "mozilla/dom/FileSystem.h"
      15             : #include "mozilla/dom/FileSystemDirectoryEntry.h"
      16             : #include "mozilla/dom/FileSystemFileEntry.h"
      17             : #include "nsIClipboard.h"
      18             : #include "nsISupportsPrimitives.h"
      19             : #include "nsIScriptObjectPrincipal.h"
      20             : #include "nsNetUtil.h"
      21             : #include "nsQueryObject.h"
      22             : #include "nsContentUtils.h"
      23             : #include "nsVariant.h"
      24             : 
      25             : namespace {
      26             : 
      27             : struct FileMimeNameData
      28             : {
      29             :   const char* mMimeName;
      30             :   const char* mFileName;
      31             : };
      32             : 
      33             : FileMimeNameData kFileMimeNameMap[] = {
      34             :   { kFileMime, "GenericFileName" },
      35             :   { kPNGImageMime, "GenericImageNamePNG" },
      36             : };
      37             : 
      38             : } // anonymous namespace
      39             : 
      40             : namespace mozilla {
      41             : namespace dom {
      42             : 
      43           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(DataTransferItem, mData,
      44             :                                       mPrincipal, mDataTransfer, mCachedFile)
      45           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(DataTransferItem)
      46           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(DataTransferItem)
      47             : 
      48           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(DataTransferItem)
      49           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      50           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
      51           0 : NS_INTERFACE_MAP_END
      52             : 
      53             : JSObject*
      54           0 : DataTransferItem::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      55             : {
      56           0 :   return DataTransferItemBinding::Wrap(aCx, this, aGivenProto);
      57             : }
      58             : 
      59             : already_AddRefed<DataTransferItem>
      60           0 : DataTransferItem::Clone(DataTransfer* aDataTransfer) const
      61             : {
      62           0 :   MOZ_ASSERT(aDataTransfer);
      63             : 
      64           0 :   RefPtr<DataTransferItem> it = new DataTransferItem(aDataTransfer, mType);
      65             : 
      66             :   // Copy over all of the fields
      67           0 :   it->mKind = mKind;
      68           0 :   it->mIndex = mIndex;
      69           0 :   it->mData = mData;
      70           0 :   it->mPrincipal = mPrincipal;
      71           0 :   it->mChromeOnly = mChromeOnly;
      72             : 
      73           0 :   return it.forget();
      74             : }
      75             : 
      76             : void
      77           0 : DataTransferItem::SetData(nsIVariant* aData)
      78             : {
      79             :   // Invalidate our file cache, we will regenerate it with the new data
      80           0 :   mCachedFile = nullptr;
      81             : 
      82           0 :   if (!aData) {
      83             :     // We are holding a temporary null which will later be filled.
      84             :     // These are provided by the system, and have guaranteed properties about
      85             :     // their kind based on their type.
      86           0 :     MOZ_ASSERT(!mType.IsEmpty());
      87             : 
      88           0 :     mKind = KIND_STRING;
      89           0 :     for (uint32_t i = 0; i < ArrayLength(kFileMimeNameMap); ++i) {
      90           0 :       if (mType.EqualsASCII(kFileMimeNameMap[i].mMimeName)) {
      91           0 :         mKind = KIND_FILE;
      92           0 :         break;
      93             :       }
      94             :     }
      95             : 
      96           0 :     mData = nullptr;
      97           0 :     return;
      98             :   }
      99             : 
     100           0 :   mData = aData;
     101           0 :   mKind = KindFromData(mData);
     102             : }
     103             : 
     104             : /* static */ DataTransferItem::eKind
     105           0 : DataTransferItem::KindFromData(nsIVariant* aData)
     106             : {
     107           0 :   nsCOMPtr<nsISupports> supports;
     108           0 :   nsresult rv = aData->GetAsISupports(getter_AddRefs(supports));
     109           0 :   if (NS_SUCCEEDED(rv) && supports) {
     110             :     // Check if we have one of the supported file data formats
     111           0 :     if (nsCOMPtr<nsIDOMBlob>(do_QueryInterface(supports)) ||
     112           0 :         nsCOMPtr<BlobImpl>(do_QueryInterface(supports)) ||
     113           0 :         nsCOMPtr<nsIFile>(do_QueryInterface(supports))) {
     114           0 :       return KIND_FILE;
     115             :     }
     116             :   }
     117             : 
     118           0 :   nsAutoString string;
     119             :   // If we can't get the data type as a string, that means that the object
     120             :   // should be considered to be of the "other" type. This is impossible
     121             :   // through the APIs defined by the spec, but we provide extra Moz* APIs,
     122             :   // which allow setting of non-string data. We determine whether we can
     123             :   // consider it a string, by calling GetAsAString, and checking for success.
     124           0 :   rv = aData->GetAsAString(string);
     125           0 :   if (NS_SUCCEEDED(rv)) {
     126           0 :     return KIND_STRING;
     127             :   }
     128             : 
     129           0 :   return KIND_OTHER;
     130             : }
     131             : 
     132             : void
     133           0 : DataTransferItem::FillInExternalData()
     134             : {
     135           0 :   if (mData) {
     136           0 :     return;
     137             :   }
     138             : 
     139           0 :   NS_ConvertUTF16toUTF8 utf8format(mType);
     140           0 :   const char* format = utf8format.get();
     141           0 :   if (strcmp(format, "text/plain") == 0) {
     142           0 :     format = kUnicodeMime;
     143           0 :   } else if (strcmp(format, "text/uri-list") == 0) {
     144           0 :     format = kURLDataMime;
     145             :   }
     146             : 
     147             :   nsCOMPtr<nsITransferable> trans =
     148           0 :     do_CreateInstance("@mozilla.org/widget/transferable;1");
     149           0 :   if (NS_WARN_IF(!trans)) {
     150           0 :     return;
     151             :   }
     152             : 
     153           0 :   trans->Init(nullptr);
     154           0 :   trans->AddDataFlavor(format);
     155             : 
     156           0 :   if (mDataTransfer->GetEventMessage() == ePaste) {
     157           0 :     MOZ_ASSERT(mIndex == 0, "index in clipboard must be 0");
     158             : 
     159             :     nsCOMPtr<nsIClipboard> clipboard =
     160           0 :       do_GetService("@mozilla.org/widget/clipboard;1");
     161           0 :     if (!clipboard || mDataTransfer->ClipboardType() < 0) {
     162           0 :       return;
     163             :     }
     164             : 
     165           0 :     nsresult rv = clipboard->GetData(trans, mDataTransfer->ClipboardType());
     166           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     167           0 :       return;
     168             :     }
     169             :   } else {
     170           0 :     nsCOMPtr<nsIDragSession> dragSession = nsContentUtils::GetDragSession();
     171           0 :     if (!dragSession) {
     172           0 :       return;
     173             :     }
     174             : 
     175           0 :     nsresult rv = dragSession->GetData(trans, mIndex);
     176           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     177           0 :       return;
     178             :     }
     179             :   }
     180             : 
     181           0 :   uint32_t length = 0;
     182           0 :   nsCOMPtr<nsISupports> data;
     183           0 :   nsresult rv = trans->GetTransferData(format, getter_AddRefs(data), &length);
     184           0 :   if (NS_WARN_IF(NS_FAILED(rv) || !data)) {
     185           0 :     return;
     186             :   }
     187             : 
     188             :   // Fill the variant
     189           0 :   RefPtr<nsVariantCC> variant = new nsVariantCC();
     190             : 
     191           0 :   eKind oldKind = Kind();
     192           0 :   if (oldKind == KIND_FILE) {
     193             :     // Because this is an external piece of data, mType is one of kFileMime,
     194             :     // kPNGImageMime, kJPEGImageMime, or kGIFImageMime. Some of these types
     195             :     // are passed in as a nsIInputStream which must be converted to a
     196             :     // dom::File before storing.
     197           0 :     if (nsCOMPtr<nsIInputStream> istream = do_QueryInterface(data)) {
     198           0 :       RefPtr<File> file = CreateFileFromInputStream(istream);
     199           0 :       if (NS_WARN_IF(!file)) {
     200           0 :         return;
     201             :       }
     202           0 :       data = do_QueryObject(file);
     203             :     }
     204             : 
     205           0 :     variant->SetAsISupports(data);
     206             :   } else {
     207             :     // We have an external piece of string data. Extract it and store it in the variant
     208           0 :     MOZ_ASSERT(oldKind == KIND_STRING);
     209             : 
     210           0 :     nsCOMPtr<nsISupportsString> supportsstr = do_QueryInterface(data);
     211           0 :     if (supportsstr) {
     212           0 :       nsAutoString str;
     213           0 :       supportsstr->GetData(str);
     214           0 :       variant->SetAsAString(str);
     215             :     } else {
     216           0 :       nsCOMPtr<nsISupportsCString> supportscstr = do_QueryInterface(data);
     217           0 :       if (supportscstr) {
     218           0 :         nsAutoCString str;
     219           0 :         supportscstr->GetData(str);
     220           0 :         variant->SetAsACString(str);
     221             :       }
     222             :     }
     223             :   }
     224             : 
     225           0 :   SetData(variant);
     226             : 
     227           0 :   if (oldKind != Kind()) {
     228           0 :     NS_WARNING("Clipboard data provided by the OS does not match predicted kind");
     229           0 :     mDataTransfer->TypesListMayHaveChanged();
     230             :   }
     231             : }
     232             : 
     233             : void
     234           0 : DataTransferItem::GetType(nsAString& aType)
     235             : {
     236             :   // If we don't have a File, we can just put whatever our recorded internal
     237             :   // type is.
     238           0 :   if (Kind() != KIND_FILE) {
     239           0 :     aType = mType;
     240           0 :     return;
     241             :   }
     242             : 
     243             :   // If we do have a File, then we need to look at our File object to discover
     244             :   // what its mime type is. We can use the System Principal here, as this
     245             :   // information should be avaliable even if the data is currently inaccessible
     246             :   // (for example during a dragover).
     247             :   //
     248             :   // XXX: This seems inefficient, as it seems like we should be able to get this
     249             :   // data without getting the entire File object, which may require talking to
     250             :   // the OS.
     251           0 :   ErrorResult rv;
     252           0 :   RefPtr<File> file = GetAsFile(*nsContentUtils::GetSystemPrincipal(), rv);
     253           0 :   MOZ_ASSERT(!rv.Failed(), "Failed to get file data with system principal");
     254             : 
     255             :   // If we don't actually have a file, fall back to returning the internal type.
     256           0 :   if (NS_WARN_IF(!file)) {
     257           0 :     aType = mType;
     258           0 :     return;
     259             :   }
     260             : 
     261           0 :   file->GetType(aType);
     262             : }
     263             : 
     264             : already_AddRefed<File>
     265           0 : DataTransferItem::GetAsFile(nsIPrincipal& aSubjectPrincipal,
     266             :                             ErrorResult& aRv)
     267             : {
     268             :   // This is done even if we have an mCachedFile, as it performs the necessary
     269             :   // permissions checks to ensure that we are allowed to access this type.
     270           0 :   nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
     271           0 :   if (NS_WARN_IF(!data || aRv.Failed())) {
     272           0 :     return nullptr;
     273             :   }
     274             : 
     275             :   // We have to check our kind after getting the data, because if we have
     276             :   // external data and the OS lied to us (which unfortunately does happen
     277             :   // sometimes), then we might not have the same type of data as we did coming
     278             :   // into this function.
     279           0 :   if (NS_WARN_IF(mKind != KIND_FILE)) {
     280           0 :     return nullptr;
     281             :   }
     282             : 
     283             :   // Generate the dom::File from the stored data, caching it so that the
     284             :   // same object is returned in the future.
     285           0 :   if (!mCachedFile) {
     286           0 :     nsCOMPtr<nsISupports> supports;
     287           0 :     aRv = data->GetAsISupports(getter_AddRefs(supports));
     288           0 :     MOZ_ASSERT(!aRv.Failed() && supports,
     289             :                "File objects should be stored as nsISupports variants");
     290           0 :     if (aRv.Failed() || !supports) {
     291           0 :       return nullptr;
     292             :     }
     293             : 
     294           0 :     if (nsCOMPtr<nsIDOMBlob> domBlob = do_QueryInterface(supports)) {
     295           0 :       Blob* blob = static_cast<Blob*>(domBlob.get());
     296           0 :       mCachedFile = blob->ToFile();
     297           0 :     } else if (nsCOMPtr<BlobImpl> blobImpl = do_QueryInterface(supports)) {
     298           0 :       MOZ_ASSERT(blobImpl->IsFile());
     299           0 :       mCachedFile = File::Create(mDataTransfer, blobImpl);
     300           0 :     } else if (nsCOMPtr<nsIFile> ifile = do_QueryInterface(supports)) {
     301           0 :       mCachedFile = File::CreateFromFile(mDataTransfer, ifile);
     302             :     } else {
     303           0 :       MOZ_ASSERT(false, "One of the above code paths should be taken");
     304             :       return nullptr;
     305             :     }
     306             :   }
     307             : 
     308           0 :   RefPtr<File> file = mCachedFile;
     309           0 :   return file.forget();
     310             : }
     311             : 
     312             : already_AddRefed<FileSystemEntry>
     313           0 : DataTransferItem::GetAsEntry(nsIPrincipal& aSubjectPrincipal,
     314             :                              ErrorResult& aRv)
     315             : {
     316           0 :   RefPtr<File> file = GetAsFile(aSubjectPrincipal, aRv);
     317           0 :   if (NS_WARN_IF(aRv.Failed()) || !file) {
     318           0 :     return nullptr;
     319             :   }
     320             : 
     321           0 :   nsCOMPtr<nsIGlobalObject> global;
     322             :   // This is annoying, but DataTransfer may have various things as parent.
     323             :   nsCOMPtr<EventTarget> target =
     324           0 :     do_QueryInterface(mDataTransfer->GetParentObject());
     325           0 :   if (target) {
     326           0 :     global = target->GetOwnerGlobal();
     327             :   } else {
     328             :     nsCOMPtr<nsIDOMEvent> event =
     329           0 :       do_QueryInterface(mDataTransfer->GetParentObject());
     330           0 :     if (event) {
     331           0 :       global = event->InternalDOMEvent()->GetParentObject();
     332             :     }
     333             :   }
     334             : 
     335           0 :   if (!global) {
     336           0 :     return nullptr;
     337             :   }
     338             : 
     339           0 :   RefPtr<FileSystem> fs = FileSystem::Create(global);
     340           0 :   RefPtr<FileSystemEntry> entry;
     341           0 :   BlobImpl* impl = file->Impl();
     342           0 :   MOZ_ASSERT(impl);
     343             : 
     344           0 :   if (impl->IsDirectory()) {
     345           0 :     nsAutoString fullpath;
     346           0 :     impl->GetMozFullPathInternal(fullpath, aRv);
     347           0 :     if (aRv.Failed()) {
     348           0 :       aRv.SuppressException();
     349           0 :       return nullptr;
     350             :     }
     351             : 
     352           0 :     nsCOMPtr<nsIFile> directoryFile;
     353             :     // fullPath is already in unicode, we don't have to use
     354             :     // NS_NewNativeLocalFile.
     355           0 :     nsresult rv = NS_NewLocalFile(fullpath, true,
     356           0 :                                   getter_AddRefs(directoryFile));
     357           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     358           0 :       return nullptr;
     359             :     }
     360             : 
     361           0 :     RefPtr<Directory> directory = Directory::Create(global, directoryFile);
     362           0 :     entry = new FileSystemDirectoryEntry(global, directory, nullptr, fs);
     363             :   } else {
     364           0 :     entry = new FileSystemFileEntry(global, file, nullptr, fs);
     365             :   }
     366             : 
     367           0 :   Sequence<RefPtr<FileSystemEntry>> entries;
     368           0 :   if (!entries.AppendElement(entry, fallible)) {
     369           0 :     return nullptr;
     370             :   }
     371             : 
     372           0 :   fs->CreateRoot(entries);
     373           0 :   return entry.forget();
     374             : }
     375             : 
     376             : already_AddRefed<File>
     377           0 : DataTransferItem::CreateFileFromInputStream(nsIInputStream* aStream)
     378             : {
     379           0 :   const char* key = nullptr;
     380           0 :   for (uint32_t i = 0; i < ArrayLength(kFileMimeNameMap); ++i) {
     381           0 :     if (mType.EqualsASCII(kFileMimeNameMap[i].mMimeName)) {
     382           0 :       key = kFileMimeNameMap[i].mFileName;
     383           0 :       break;
     384             :     }
     385             :   }
     386           0 :   if (!key) {
     387           0 :     MOZ_ASSERT_UNREACHABLE("Unsupported mime type");
     388             :     key = "GenericFileName";
     389             :   }
     390             : 
     391           0 :   nsXPIDLString fileName;
     392             :   nsresult rv = nsContentUtils::GetLocalizedString(nsContentUtils::eDOM_PROPERTIES,
     393           0 :                                                    key, fileName);
     394           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     395           0 :     return nullptr;
     396             :   }
     397             : 
     398             :   uint64_t available;
     399           0 :   rv = aStream->Available(&available);
     400           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     401           0 :     return nullptr;
     402             :   }
     403             : 
     404           0 :   void* data = nullptr;
     405           0 :   rv = NS_ReadInputStreamToBuffer(aStream, &data, available);
     406           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     407           0 :     return nullptr;
     408             :   }
     409             : 
     410             :   return File::CreateMemoryFile(mDataTransfer, data, available, fileName,
     411           0 :                                 mType, PR_Now());
     412             : }
     413             : 
     414             : void
     415           0 : DataTransferItem::GetAsString(FunctionStringCallback* aCallback,
     416             :                               nsIPrincipal& aSubjectPrincipal,
     417             :                               ErrorResult& aRv)
     418             : {
     419           0 :   if (!aCallback) {
     420           0 :     return;
     421             :   }
     422             : 
     423             :   // Theoretically this should be done inside of the runnable, as it might be an
     424             :   // expensive operation on some systems, however we wouldn't get access to the
     425             :   // NS_ERROR_DOM_SECURITY_ERROR messages which may be raised by this method.
     426           0 :   nsCOMPtr<nsIVariant> data = Data(&aSubjectPrincipal, aRv);
     427           0 :   if (NS_WARN_IF(!data || aRv.Failed())) {
     428           0 :     return;
     429             :   }
     430             : 
     431             :   // We have to check our kind after getting the data, because if we have
     432             :   // external data and the OS lied to us (which unfortunately does happen
     433             :   // sometimes), then we might not have the same type of data as we did coming
     434             :   // into this function.
     435           0 :   if (NS_WARN_IF(mKind != KIND_STRING)) {
     436           0 :     return;
     437             :   }
     438             : 
     439           0 :   nsAutoString stringData;
     440           0 :   nsresult rv = data->GetAsAString(stringData);
     441           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     442           0 :     return;
     443             :   }
     444             : 
     445             :   // Dispatch the callback to the main thread
     446           0 :   class GASRunnable final : public Runnable
     447             :   {
     448             :   public:
     449           0 :     GASRunnable(FunctionStringCallback* aCallback, const nsAString& aStringData)
     450           0 :       : mozilla::Runnable("GASRunnable")
     451             :       , mCallback(aCallback)
     452           0 :       , mStringData(aStringData)
     453           0 :     {}
     454             : 
     455           0 :     NS_IMETHOD Run() override
     456             :     {
     457           0 :       ErrorResult rv;
     458           0 :       mCallback->Call(mStringData, rv);
     459           0 :       NS_WARNING_ASSERTION(!rv.Failed(), "callback failed");
     460           0 :       return rv.StealNSResult();
     461             :     }
     462             :   private:
     463             :     RefPtr<FunctionStringCallback> mCallback;
     464             :     nsString mStringData;
     465             :   };
     466             : 
     467           0 :   RefPtr<GASRunnable> runnable = new GASRunnable(aCallback, stringData);
     468             : 
     469             :   // DataTransfer.mParent might be EventTarget, nsIGlobalObject, ClipboardEvent
     470             :   // nsPIDOMWindowOuter, null
     471           0 :   nsISupports* parent = mDataTransfer->GetParentObject();
     472           0 :   nsCOMPtr<nsIGlobalObject> global = do_QueryInterface(parent);
     473           0 :   if (parent && !global) {
     474           0 :     if (nsCOMPtr<dom::EventTarget> target = do_QueryInterface(parent)) {
     475           0 :       global = target->GetOwnerGlobal();
     476           0 :     } else if (nsCOMPtr<nsIDOMEvent> event = do_QueryInterface(parent)) {
     477           0 :       global = event->InternalDOMEvent()->GetParentObject();
     478             :     }
     479             :   }
     480           0 :   if (global) {
     481           0 :     rv = global->Dispatch("GASRunnable", TaskCategory::Other, runnable.forget());
     482             :   } else {
     483           0 :     rv = NS_DispatchToMainThread(runnable);
     484             :   }
     485           0 :   if (NS_FAILED(rv)) {
     486             :     NS_WARNING("Dispatch to main thread Failed in "
     487           0 :                "DataTransferItem::GetAsString!");
     488             :   }
     489             : }
     490             : 
     491             : already_AddRefed<nsIVariant>
     492           0 : DataTransferItem::DataNoSecurityCheck()
     493             : {
     494           0 :   if (!mData) {
     495           0 :     FillInExternalData();
     496             :   }
     497           0 :   nsCOMPtr<nsIVariant> data = mData;
     498           0 :   return data.forget();
     499             : }
     500             : 
     501             : already_AddRefed<nsIVariant>
     502           0 : DataTransferItem::Data(nsIPrincipal* aPrincipal, ErrorResult& aRv)
     503             : {
     504           0 :   MOZ_ASSERT(aPrincipal);
     505             : 
     506           0 :   nsCOMPtr<nsIVariant> variant = DataNoSecurityCheck();
     507             : 
     508             :   // If the inbound principal is system, we can skip the below checks, as
     509             :   // they will trivially succeed.
     510           0 :   if (nsContentUtils::IsSystemPrincipal(aPrincipal)) {
     511           0 :     return variant.forget();
     512             :   }
     513             : 
     514           0 :   MOZ_ASSERT(!ChromeOnly(), "Non-chrome code shouldn't see a ChromeOnly DataTransferItem");
     515           0 :   if (ChromeOnly()) {
     516           0 :     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     517           0 :     return nullptr;
     518             :   }
     519             : 
     520           0 :   bool checkItemPrincipal = mDataTransfer->IsCrossDomainSubFrameDrop() ||
     521           0 :     (mDataTransfer->GetEventMessage() != eDrop &&
     522           0 :      mDataTransfer->GetEventMessage() != ePaste);
     523             : 
     524             :   // Check if the caller is allowed to access the drag data. Callers with
     525             :   // chrome privileges can always read the data. During the
     526             :   // drop event, allow retrieving the data except in the case where the
     527             :   // source of the drag is in a child frame of the caller. In that case,
     528             :   // we only allow access to data of the same principal. During other events,
     529             :   // only allow access to the data with the same principal.
     530             :   //
     531             :   // We don't want to fail with an exception in this siutation, rather we want
     532             :   // to just pretend as though the stored data is "nullptr". This is consistent
     533             :   // with Chrome's behavior and is less surprising for web applications which
     534             :   // don't expect execptions to be raised when performing certain operations.
     535           0 :   if (Principal() && checkItemPrincipal &&
     536           0 :       !aPrincipal->Subsumes(Principal())) {
     537           0 :     return nullptr;
     538             :   }
     539             : 
     540           0 :   if (!variant) {
     541           0 :     return nullptr;
     542             :   }
     543             : 
     544           0 :   nsCOMPtr<nsISupports> data;
     545           0 :   nsresult rv = variant->GetAsISupports(getter_AddRefs(data));
     546           0 :   if (NS_SUCCEEDED(rv) && data) {
     547           0 :     nsCOMPtr<EventTarget> pt = do_QueryInterface(data);
     548           0 :     if (pt) {
     549           0 :       nsIScriptContext* c = pt->GetContextForEventHandlers(&rv);
     550           0 :       if (NS_WARN_IF(NS_FAILED(rv) || !c)) {
     551           0 :         return nullptr;
     552             :       }
     553             : 
     554           0 :       nsIGlobalObject* go = c->GetGlobalObject();
     555           0 :       if (NS_WARN_IF(!go)) {
     556           0 :         return nullptr;
     557             :       }
     558             : 
     559           0 :       nsCOMPtr<nsIScriptObjectPrincipal> sp = do_QueryInterface(go);
     560           0 :       MOZ_ASSERT(sp, "This cannot fail on the main thread.");
     561             : 
     562           0 :       nsIPrincipal* dataPrincipal = sp->GetPrincipal();
     563           0 :       if (NS_WARN_IF(!dataPrincipal || !aPrincipal->Equals(dataPrincipal))) {
     564           0 :         return nullptr;
     565             :       }
     566             :     }
     567             :   }
     568             : 
     569           0 :   return variant.forget();
     570             : }
     571             : 
     572             : } // namespace dom
     573             : } // namespace mozilla

Generated by: LCOV version 1.13