LCOV - code coverage report
Current view: top level - dom/filesystem - GetFilesHelper.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 307 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 35 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 "GetFilesHelper.h"
       8             : #include "mozilla/dom/ContentChild.h"
       9             : #include "mozilla/dom/ContentParent.h"
      10             : #include "mozilla/dom/FileBlobImpl.h"
      11             : #include "mozilla/dom/IPCBlobUtils.h"
      12             : #include "mozilla/ipc/IPCStreamUtils.h"
      13             : #include "FileSystemUtils.h"
      14             : #include "nsProxyRelease.h"
      15             : 
      16             : namespace mozilla {
      17             : namespace dom {
      18             : 
      19             : namespace {
      20             : 
      21             : // This class is used in the DTOR of GetFilesHelper to release resources in the
      22             : // correct thread.
      23           0 : class ReleaseRunnable final : public Runnable
      24             : {
      25             : public:
      26             :   static void
      27           0 :   MaybeReleaseOnMainThread(nsTArray<RefPtr<Promise>>& aPromises,
      28             :                            nsTArray<RefPtr<GetFilesCallback>>& aCallbacks,
      29             :                            Sequence<RefPtr<File>>& aFiles,
      30             :                            already_AddRefed<nsIGlobalObject> aGlobal)
      31             :   {
      32           0 :     nsCOMPtr<nsIGlobalObject> global(aGlobal);
      33           0 :     if (NS_IsMainThread()) {
      34           0 :       return;
      35             :     }
      36             : 
      37             :     RefPtr<ReleaseRunnable> runnable =
      38           0 :       new ReleaseRunnable(aPromises, aCallbacks, aFiles, global.forget());
      39           0 :     FileSystemUtils::DispatchRunnable(nullptr, runnable.forget());
      40             :   }
      41             : 
      42             :   NS_IMETHOD
      43           0 :   Run() override
      44             :   {
      45           0 :     MOZ_ASSERT(NS_IsMainThread());
      46             : 
      47           0 :     mPromises.Clear();
      48           0 :     mCallbacks.Clear();
      49           0 :     mFiles.Clear();
      50           0 :     mGlobal = nullptr;
      51             : 
      52           0 :     return NS_OK;
      53             :   }
      54             : 
      55             : private:
      56           0 :   ReleaseRunnable(nsTArray<RefPtr<Promise>>& aPromises,
      57             :                   nsTArray<RefPtr<GetFilesCallback>>& aCallbacks,
      58             :                   Sequence<RefPtr<File>>& aFiles,
      59             :                   already_AddRefed<nsIGlobalObject> aGlobal)
      60           0 :     : Runnable("dom::ReleaseRunnable")
      61             :   {
      62           0 :     mPromises.SwapElements(aPromises);
      63           0 :     mCallbacks.SwapElements(aCallbacks);
      64           0 :     mFiles.SwapElements(aFiles);
      65           0 :     mGlobal = aGlobal;
      66           0 :   }
      67             : 
      68             :   nsTArray<RefPtr<Promise>> mPromises;
      69             :   nsTArray<RefPtr<GetFilesCallback>> mCallbacks;
      70             :   Sequence<RefPtr<File>> mFiles;
      71             :   nsCOMPtr<nsIGlobalObject> mGlobal;
      72             : };
      73             : 
      74             : } // anonymous
      75             : 
      76             : ///////////////////////////////////////////////////////////////////////////////
      77             : // GetFilesHelper Base class
      78             : 
      79             : already_AddRefed<GetFilesHelper>
      80           0 : GetFilesHelper::Create(nsIGlobalObject* aGlobal,
      81             :                        const nsTArray<OwningFileOrDirectory>& aFilesOrDirectory,
      82             :                        bool aRecursiveFlag, ErrorResult& aRv)
      83             : {
      84           0 :   RefPtr<GetFilesHelper> helper;
      85             : 
      86           0 :   if (XRE_IsParentProcess()) {
      87           0 :     helper = new GetFilesHelper(aGlobal, aRecursiveFlag);
      88             :   } else {
      89           0 :     helper = new GetFilesHelperChild(aGlobal, aRecursiveFlag);
      90             :   }
      91             : 
      92           0 :   nsAutoString directoryPath;
      93             : 
      94           0 :   for (uint32_t i = 0; i < aFilesOrDirectory.Length(); ++i) {
      95           0 :     const OwningFileOrDirectory& data = aFilesOrDirectory[i];
      96           0 :     if (data.IsFile()) {
      97           0 :       if (!helper->mFiles.AppendElement(data.GetAsFile(), fallible)) {
      98           0 :         aRv.Throw(NS_ERROR_OUT_OF_MEMORY);
      99           0 :         return nullptr;
     100             :       }
     101             :     } else {
     102           0 :       MOZ_ASSERT(data.IsDirectory());
     103             : 
     104             :       // We support the upload of only 1 top-level directory from our
     105             :       // directory picker. This means that we cannot have more than 1
     106             :       // Directory object in aFilesOrDirectory array.
     107           0 :       MOZ_ASSERT(directoryPath.IsEmpty());
     108             : 
     109           0 :       RefPtr<Directory> directory = data.GetAsDirectory();
     110           0 :       MOZ_ASSERT(directory);
     111             : 
     112           0 :       aRv = directory->GetFullRealPath(directoryPath);
     113           0 :       if (NS_WARN_IF(aRv.Failed())) {
     114           0 :         return nullptr;
     115             :       }
     116             :     }
     117             :   }
     118             : 
     119             :   // No directories to explore.
     120           0 :   if (directoryPath.IsEmpty()) {
     121           0 :     helper->mListingCompleted = true;
     122           0 :     return helper.forget();
     123             :   }
     124             : 
     125           0 :   MOZ_ASSERT(helper->mFiles.IsEmpty());
     126           0 :   helper->SetDirectoryPath(directoryPath);
     127             : 
     128           0 :   helper->Work(aRv);
     129           0 :   if (NS_WARN_IF(aRv.Failed())) {
     130           0 :     return nullptr;
     131             :   }
     132             : 
     133           0 :   return helper.forget();
     134             : }
     135             : 
     136           0 : GetFilesHelper::GetFilesHelper(nsIGlobalObject* aGlobal, bool aRecursiveFlag)
     137             :   : Runnable("GetFilesHelper")
     138             :   , GetFilesHelperBase(aRecursiveFlag)
     139             :   , mGlobal(aGlobal)
     140             :   , mListingCompleted(false)
     141             :   , mErrorResult(NS_OK)
     142             :   , mMutex("GetFilesHelper::mMutex")
     143           0 :   , mCanceled(false)
     144             : {
     145           0 : }
     146             : 
     147           0 : GetFilesHelper::~GetFilesHelper()
     148             : {
     149           0 :   ReleaseRunnable::MaybeReleaseOnMainThread(mPromises, mCallbacks, mFiles,
     150           0 :                                             mGlobal.forget());
     151           0 : }
     152             : 
     153             : void
     154           0 : GetFilesHelper::AddPromise(Promise* aPromise)
     155             : {
     156           0 :   MOZ_ASSERT(aPromise);
     157             : 
     158             :   // Still working.
     159           0 :   if (!mListingCompleted) {
     160           0 :     mPromises.AppendElement(aPromise);
     161           0 :     return;
     162             :   }
     163             : 
     164           0 :   MOZ_ASSERT(mPromises.IsEmpty());
     165           0 :   ResolveOrRejectPromise(aPromise);
     166             : }
     167             : 
     168             : void
     169           0 : GetFilesHelper::AddCallback(GetFilesCallback* aCallback)
     170             : {
     171           0 :   MOZ_ASSERT(aCallback);
     172             : 
     173             :   // Still working.
     174           0 :   if (!mListingCompleted) {
     175           0 :     mCallbacks.AppendElement(aCallback);
     176           0 :     return;
     177             :   }
     178             : 
     179           0 :   MOZ_ASSERT(mCallbacks.IsEmpty());
     180           0 :   RunCallback(aCallback);
     181             : }
     182             : 
     183             : void
     184           0 : GetFilesHelper::Unlink()
     185             : {
     186           0 :   mGlobal = nullptr;
     187           0 :   mFiles.Clear();
     188           0 :   mPromises.Clear();
     189           0 :   mCallbacks.Clear();
     190             : 
     191             :   {
     192           0 :     MutexAutoLock lock(mMutex);
     193           0 :     mCanceled = true;
     194             :   }
     195             : 
     196           0 :   Cancel();
     197           0 : }
     198             : 
     199             : void
     200           0 : GetFilesHelper::Traverse(nsCycleCollectionTraversalCallback &cb)
     201             : {
     202           0 :   GetFilesHelper* tmp = this;
     203           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mGlobal);
     204           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mFiles);
     205           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPromises);
     206           0 : }
     207             : 
     208             : void
     209           0 : GetFilesHelper::Work(ErrorResult& aRv)
     210             : {
     211             :   nsCOMPtr<nsIEventTarget> target =
     212           0 :     do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
     213           0 :   MOZ_ASSERT(target);
     214             : 
     215           0 :   aRv = target->Dispatch(this, NS_DISPATCH_NORMAL);
     216           0 : }
     217             : 
     218             : NS_IMETHODIMP
     219           0 : GetFilesHelper::Run()
     220             : {
     221           0 :   MOZ_ASSERT(!mDirectoryPath.IsEmpty());
     222           0 :   MOZ_ASSERT(!mListingCompleted);
     223             : 
     224             :   // First step is to retrieve the list of file paths.
     225             :   // This happens in the I/O thread.
     226           0 :   if (!NS_IsMainThread()) {
     227           0 :     RunIO();
     228             : 
     229             :     // If this operation has been canceled, we don't have to go back to
     230             :     // main-thread.
     231           0 :     if (IsCanceled()) {
     232           0 :       return NS_OK;
     233             :     }
     234             : 
     235           0 :     RefPtr<Runnable> runnable = this;
     236           0 :     return FileSystemUtils::DispatchRunnable(nullptr, runnable.forget());
     237             :   }
     238             : 
     239             :   // We are here, but we should not do anything on this thread because, in the
     240             :   // meantime, the operation has been canceled.
     241           0 :   if (IsCanceled()) {
     242           0 :     return NS_OK;
     243             :   }
     244             : 
     245           0 :   RunMainThread();
     246             : 
     247           0 :   OperationCompleted();
     248           0 :   return NS_OK;
     249             : }
     250             : 
     251             : void
     252           0 : GetFilesHelper::OperationCompleted()
     253             : {
     254             :   // We mark the operation as completed here.
     255           0 :   mListingCompleted = true;
     256             : 
     257             :   // Let's process the pending promises.
     258           0 :   nsTArray<RefPtr<Promise>> promises;
     259           0 :   promises.SwapElements(mPromises);
     260             : 
     261           0 :   for (uint32_t i = 0; i < promises.Length(); ++i) {
     262           0 :     ResolveOrRejectPromise(promises[i]);
     263             :   }
     264             : 
     265             :   // Let's process the pending callbacks.
     266           0 :   nsTArray<RefPtr<GetFilesCallback>> callbacks;
     267           0 :   callbacks.SwapElements(mCallbacks);
     268             : 
     269           0 :   for (uint32_t i = 0; i < callbacks.Length(); ++i) {
     270           0 :     RunCallback(callbacks[i]);
     271             :   }
     272           0 : }
     273             : 
     274             : void
     275           0 : GetFilesHelper::RunIO()
     276             : {
     277           0 :   MOZ_ASSERT(!NS_IsMainThread());
     278           0 :   MOZ_ASSERT(!mDirectoryPath.IsEmpty());
     279           0 :   MOZ_ASSERT(!mListingCompleted);
     280             : 
     281           0 :   nsCOMPtr<nsIFile> file;
     282           0 :   mErrorResult = NS_NewLocalFile(mDirectoryPath, true, getter_AddRefs(file));
     283           0 :   if (NS_WARN_IF(NS_FAILED(mErrorResult))) {
     284           0 :     return;
     285             :   }
     286             : 
     287           0 :   nsAutoString leafName;
     288           0 :   mErrorResult = file->GetLeafName(leafName);
     289           0 :   if (NS_WARN_IF(NS_FAILED(mErrorResult))) {
     290           0 :     return;
     291             :   }
     292             : 
     293           0 :   nsAutoString domPath;
     294           0 :   domPath.AssignLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
     295           0 :   domPath.Append(leafName);
     296             : 
     297           0 :   mErrorResult = ExploreDirectory(domPath, file);
     298             : }
     299             : 
     300             : void
     301           0 : GetFilesHelper::RunMainThread()
     302             : {
     303           0 :   MOZ_ASSERT(NS_IsMainThread());
     304           0 :   MOZ_ASSERT(!mDirectoryPath.IsEmpty());
     305           0 :   MOZ_ASSERT(!mListingCompleted);
     306             : 
     307             :   // If there is an error, do nothing.
     308           0 :   if (NS_FAILED(mErrorResult)) {
     309           0 :     return;
     310             :   }
     311             : 
     312             :   // Create the sequence of Files.
     313           0 :   for (uint32_t i = 0; i < mTargetBlobImplArray.Length(); ++i) {
     314           0 :     RefPtr<File> domFile = File::Create(mGlobal, mTargetBlobImplArray[i]);
     315           0 :     MOZ_ASSERT(domFile);
     316             : 
     317           0 :     if (!mFiles.AppendElement(domFile, fallible)) {
     318           0 :       mErrorResult = NS_ERROR_OUT_OF_MEMORY;
     319           0 :       mFiles.Clear();
     320           0 :       return;
     321             :     }
     322             :   }
     323             : }
     324             : 
     325             : nsresult
     326           0 : GetFilesHelperBase::ExploreDirectory(const nsAString& aDOMPath, nsIFile* aFile)
     327             : {
     328           0 :   MOZ_ASSERT(!NS_IsMainThread());
     329           0 :   MOZ_ASSERT(aFile);
     330             : 
     331             :   // We check if this operation has to be terminated at each recursion.
     332           0 :   if (IsCanceled()) {
     333           0 :     return NS_OK;
     334             :   }
     335             : 
     336           0 :   nsresult rv = AddExploredDirectory(aFile);
     337           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     338           0 :     return rv;
     339             :   }
     340             : 
     341           0 :   nsCOMPtr<nsISimpleEnumerator> entries;
     342           0 :   rv = aFile->GetDirectoryEntries(getter_AddRefs(entries));
     343           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     344           0 :     return rv;
     345             :   }
     346             : 
     347             :   for (;;) {
     348           0 :     bool hasMore = false;
     349           0 :     if (NS_WARN_IF(NS_FAILED(entries->HasMoreElements(&hasMore))) || !hasMore) {
     350           0 :       break;
     351             :     }
     352             : 
     353           0 :     nsCOMPtr<nsISupports> supp;
     354           0 :     if (NS_WARN_IF(NS_FAILED(entries->GetNext(getter_AddRefs(supp))))) {
     355           0 :       break;
     356             :     }
     357             : 
     358           0 :     nsCOMPtr<nsIFile> currFile = do_QueryInterface(supp);
     359           0 :     MOZ_ASSERT(currFile);
     360             : 
     361             :     bool isLink, isSpecial, isFile, isDir;
     362           0 :     if (NS_WARN_IF(NS_FAILED(currFile->IsSymlink(&isLink)) ||
     363           0 :                    NS_FAILED(currFile->IsSpecial(&isSpecial))) ||
     364             :         isSpecial) {
     365           0 :       continue;
     366             :     }
     367             : 
     368           0 :     if (NS_WARN_IF(NS_FAILED(currFile->IsFile(&isFile)) ||
     369           0 :                    NS_FAILED(currFile->IsDirectory(&isDir))) ||
     370           0 :         !(isFile || isDir)) {
     371           0 :       continue;
     372             :     }
     373             : 
     374             :     // We don't want to explore loops of links.
     375           0 :     if (isDir && isLink && !ShouldFollowSymLink(currFile)) {
     376           0 :       continue;
     377             :     }
     378             : 
     379             :     // The new domPath
     380           0 :     nsAutoString domPath;
     381           0 :     domPath.Assign(aDOMPath);
     382           0 :     if (!aDOMPath.EqualsLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL)) {
     383           0 :       domPath.AppendLiteral(FILESYSTEM_DOM_PATH_SEPARATOR_LITERAL);
     384             :     }
     385             : 
     386           0 :     nsAutoString leafName;
     387           0 :     if (NS_WARN_IF(NS_FAILED(currFile->GetLeafName(leafName)))) {
     388           0 :       continue;
     389             :     }
     390           0 :     domPath.Append(leafName);
     391             : 
     392           0 :     if (isFile) {
     393           0 :       RefPtr<BlobImpl> blobImpl = new FileBlobImpl(currFile);
     394           0 :       blobImpl->SetDOMPath(domPath);
     395             : 
     396           0 :       if (!mTargetBlobImplArray.AppendElement(blobImpl, fallible)) {
     397           0 :         return NS_ERROR_OUT_OF_MEMORY;
     398             :       }
     399             : 
     400           0 :       continue;
     401             :     }
     402             : 
     403           0 :     MOZ_ASSERT(isDir);
     404           0 :     if (!mRecursiveFlag) {
     405           0 :       continue;
     406             :     }
     407             : 
     408             :     // Recursive.
     409           0 :     rv = ExploreDirectory(domPath, currFile);
     410           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     411           0 :       return rv;
     412             :     }
     413           0 :   }
     414             : 
     415           0 :   return NS_OK;
     416             : }
     417             : 
     418             : nsresult
     419           0 : GetFilesHelperBase::AddExploredDirectory(nsIFile* aDir)
     420             : {
     421             :   nsresult rv;
     422             : 
     423             : #ifdef DEBUG
     424             :   bool isDir;
     425           0 :   rv = aDir->IsDirectory(&isDir);
     426           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     427           0 :     return rv;
     428             :   }
     429             : 
     430           0 :   MOZ_ASSERT(isDir, "Why are we here?");
     431             : #endif
     432             : 
     433             :   bool isLink;
     434           0 :   rv = aDir->IsSymlink(&isLink);
     435           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     436           0 :     return rv;
     437             :   }
     438             : 
     439           0 :   nsAutoString path;
     440           0 :   if (!isLink) {
     441           0 :     rv = aDir->GetPath(path);
     442           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     443           0 :       return rv;
     444             :     }
     445             :   } else {
     446           0 :     rv = aDir->GetTarget(path);
     447           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     448           0 :       return rv;
     449             :     }
     450             :   }
     451             : 
     452           0 :   mExploredDirectories.PutEntry(path);
     453           0 :   return NS_OK;
     454             : }
     455             : 
     456             : bool
     457           0 : GetFilesHelperBase::ShouldFollowSymLink(nsIFile* aDir)
     458             : {
     459             : #ifdef DEBUG
     460             :   bool isLink, isDir;
     461           0 :   if (NS_WARN_IF(NS_FAILED(aDir->IsSymlink(&isLink)) ||
     462             :                  NS_FAILED(aDir->IsDirectory(&isDir)))) {
     463           0 :     return false;
     464             :   }
     465             : 
     466           0 :   MOZ_ASSERT(isLink && isDir, "Why are we here?");
     467             : #endif
     468             : 
     469           0 :   nsAutoString targetPath;
     470           0 :   if (NS_WARN_IF(NS_FAILED(aDir->GetTarget(targetPath)))) {
     471           0 :     return false;
     472             :   }
     473             : 
     474           0 :   return !mExploredDirectories.Contains(targetPath);
     475             : }
     476             : 
     477             : void
     478           0 : GetFilesHelper::ResolveOrRejectPromise(Promise* aPromise)
     479             : {
     480           0 :   MOZ_ASSERT(NS_IsMainThread());
     481           0 :   MOZ_ASSERT(mListingCompleted);
     482           0 :   MOZ_ASSERT(aPromise);
     483             : 
     484             :   // Error propagation.
     485           0 :   if (NS_FAILED(mErrorResult)) {
     486           0 :     aPromise->MaybeReject(mErrorResult);
     487           0 :     return;
     488             :   }
     489             : 
     490           0 :   aPromise->MaybeResolve(mFiles);
     491             : }
     492             : 
     493             : void
     494           0 : GetFilesHelper::RunCallback(GetFilesCallback* aCallback)
     495             : {
     496           0 :   MOZ_ASSERT(NS_IsMainThread());
     497           0 :   MOZ_ASSERT(mListingCompleted);
     498           0 :   MOZ_ASSERT(aCallback);
     499             : 
     500           0 :   aCallback->Callback(mErrorResult, mFiles);
     501           0 : }
     502             : 
     503             : ///////////////////////////////////////////////////////////////////////////////
     504             : // GetFilesHelperChild class
     505             : 
     506             : void
     507           0 : GetFilesHelperChild::Work(ErrorResult& aRv)
     508             : {
     509           0 :   ContentChild* cc = ContentChild::GetSingleton();
     510           0 :   if (NS_WARN_IF(!cc)) {
     511           0 :     aRv.Throw(NS_ERROR_FAILURE);
     512           0 :     return;
     513             :   }
     514             : 
     515           0 :   aRv = nsContentUtils::GenerateUUIDInPlace(mUUID);
     516           0 :   if (NS_WARN_IF(aRv.Failed())) {
     517           0 :     return;
     518             :   }
     519             : 
     520           0 :   mPendingOperation = true;
     521           0 :   cc->CreateGetFilesRequest(mDirectoryPath, mRecursiveFlag, mUUID, this);
     522             : }
     523             : 
     524             : void
     525           0 : GetFilesHelperChild::Cancel()
     526             : {
     527           0 :   if (!mPendingOperation) {
     528           0 :     return;
     529             :   }
     530             : 
     531           0 :   ContentChild* cc = ContentChild::GetSingleton();
     532           0 :   if (NS_WARN_IF(!cc)) {
     533           0 :     return;
     534             :   }
     535             : 
     536           0 :   mPendingOperation = false;
     537           0 :   cc->DeleteGetFilesRequest(mUUID, this);
     538             : }
     539             : 
     540             : bool
     541           0 : GetFilesHelperChild::AppendBlobImpl(BlobImpl* aBlobImpl)
     542             : {
     543           0 :   MOZ_ASSERT(mPendingOperation);
     544           0 :   MOZ_ASSERT(aBlobImpl);
     545           0 :   MOZ_ASSERT(aBlobImpl->IsFile());
     546             : 
     547           0 :   RefPtr<File> file = File::Create(mGlobal, aBlobImpl);
     548           0 :   MOZ_ASSERT(file);
     549             : 
     550           0 :   return mFiles.AppendElement(file, fallible);
     551             : }
     552             : 
     553             : void
     554           0 : GetFilesHelperChild::Finished(nsresult aError)
     555             : {
     556           0 :   MOZ_ASSERT(mPendingOperation);
     557           0 :   MOZ_ASSERT(NS_SUCCEEDED(mErrorResult));
     558             : 
     559           0 :   mPendingOperation = false;
     560           0 :   mErrorResult = aError;
     561             : 
     562           0 :   OperationCompleted();
     563           0 : }
     564             : 
     565             : ///////////////////////////////////////////////////////////////////////////////
     566             : // GetFilesHelperParent class
     567             : 
     568           0 : class GetFilesHelperParentCallback final : public GetFilesCallback
     569             : {
     570             : public:
     571           0 :   explicit GetFilesHelperParentCallback(GetFilesHelperParent* aParent)
     572           0 :     : mParent(aParent)
     573             :   {
     574           0 :     MOZ_ASSERT(aParent);
     575           0 :   }
     576             : 
     577             :   void
     578           0 :   Callback(nsresult aStatus, const Sequence<RefPtr<File>>& aFiles) override
     579             :   {
     580           0 :     if (NS_FAILED(aStatus)) {
     581           0 :       mParent->mContentParent->SendGetFilesResponseAndForget(mParent->mUUID,
     582           0 :                                                              GetFilesResponseFailure(aStatus));
     583           0 :       return;
     584             :     }
     585             : 
     586           0 :     GetFilesResponseSuccess success;
     587             : 
     588           0 :     nsTArray<IPCBlob>& ipcBlobs = success.blobs();
     589           0 :     ipcBlobs.SetLength(aFiles.Length());
     590             : 
     591           0 :     for (uint32_t i = 0; i < aFiles.Length(); ++i) {
     592           0 :       nsresult rv = IPCBlobUtils::Serialize(aFiles[i]->Impl(),
     593           0 :                                             mParent->mContentParent,
     594           0 :                                             ipcBlobs[i]);
     595           0 :       if (NS_WARN_IF(NS_FAILED(rv))) {
     596           0 :         mParent->mContentParent->SendGetFilesResponseAndForget(mParent->mUUID,
     597           0 :                                                                GetFilesResponseFailure(NS_ERROR_OUT_OF_MEMORY));
     598           0 :         return;
     599             :       }
     600             :     }
     601             : 
     602           0 :     mParent->mContentParent->SendGetFilesResponseAndForget(mParent->mUUID,
     603           0 :                                                            success);
     604             :   }
     605             : 
     606             : private:
     607             :   // Raw pointer because this callback is kept alive by this parent object.
     608             :   GetFilesHelperParent* mParent;
     609             : };
     610             : 
     611           0 : GetFilesHelperParent::GetFilesHelperParent(const nsID& aUUID,
     612             :                                            ContentParent* aContentParent,
     613           0 :                                            bool aRecursiveFlag)
     614             :   : GetFilesHelper(nullptr, aRecursiveFlag)
     615             :   , mContentParent(aContentParent)
     616           0 :   , mUUID(aUUID)
     617           0 : {}
     618             : 
     619           0 : GetFilesHelperParent::~GetFilesHelperParent()
     620             : {
     621             :   NS_ReleaseOnMainThread(
     622           0 :     "GetFilesHelperParent::mContentParent", mContentParent.forget());
     623           0 : }
     624             : 
     625             : /* static */ already_AddRefed<GetFilesHelperParent>
     626           0 : GetFilesHelperParent::Create(const nsID& aUUID, const nsAString& aDirectoryPath,
     627             :                              bool aRecursiveFlag, ContentParent* aContentParent,
     628             :                              ErrorResult& aRv)
     629             : {
     630           0 :   MOZ_ASSERT(aContentParent);
     631             : 
     632             :   RefPtr<GetFilesHelperParent> helper =
     633           0 :     new GetFilesHelperParent(aUUID, aContentParent, aRecursiveFlag);
     634           0 :   helper->SetDirectoryPath(aDirectoryPath);
     635             : 
     636           0 :   helper->Work(aRv);
     637           0 :   if (NS_WARN_IF(aRv.Failed())) {
     638           0 :     return nullptr;
     639             :   }
     640             : 
     641             :   RefPtr<GetFilesHelperParentCallback> callback =
     642           0 :     new GetFilesHelperParentCallback(helper);
     643           0 :   helper->AddCallback(callback);
     644             : 
     645           0 :   return helper.forget();
     646             : }
     647             : 
     648             : } // dom namespace
     649             : } // mozilla namespace

Generated by: LCOV version 1.13