LCOV - code coverage report
Current view: top level - dom/filesystem - FileSystemTaskBase.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 144 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 27 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 file,
       5             :  * You can obtain one at http://mozilla.org/MPL/2.0/. */
       6             : 
       7             : #include "mozilla/dom/FileSystemTaskBase.h"
       8             : 
       9             : #include "nsNetCID.h"
      10             : #include "mozilla/dom/File.h"
      11             : #include "mozilla/dom/FileSystemBase.h"
      12             : #include "mozilla/dom/FileSystemRequestParent.h"
      13             : #include "mozilla/dom/FileSystemUtils.h"
      14             : #include "mozilla/dom/Promise.h"
      15             : #include "mozilla/ipc/BackgroundChild.h"
      16             : #include "mozilla/ipc/BackgroundParent.h"
      17             : #include "mozilla/ipc/PBackgroundChild.h"
      18             : #include "mozilla/Unused.h"
      19             : #include "nsProxyRelease.h"
      20             : 
      21             : namespace mozilla {
      22             : namespace dom {
      23             : 
      24             : namespace {
      25             : 
      26             : nsresult
      27           0 : FileSystemErrorFromNsError(const nsresult& aErrorValue)
      28             : {
      29           0 :   uint16_t module = NS_ERROR_GET_MODULE(aErrorValue);
      30           0 :   if (module == NS_ERROR_MODULE_DOM_FILESYSTEM ||
      31           0 :       module == NS_ERROR_MODULE_DOM_FILE ||
      32             :       module == NS_ERROR_MODULE_DOM) {
      33           0 :     return aErrorValue;
      34             :   }
      35             : 
      36           0 :   switch (aErrorValue) {
      37             :     case NS_OK:
      38           0 :       return NS_OK;
      39             : 
      40             :     case NS_ERROR_FILE_INVALID_PATH:
      41             :     case NS_ERROR_FILE_UNRECOGNIZED_PATH:
      42           0 :       return NS_ERROR_DOM_FILESYSTEM_INVALID_PATH_ERR;
      43             : 
      44             :     case NS_ERROR_FILE_DESTINATION_NOT_DIR:
      45           0 :       return NS_ERROR_DOM_FILESYSTEM_INVALID_MODIFICATION_ERR;
      46             : 
      47             :     case NS_ERROR_FILE_ACCESS_DENIED:
      48             :     case NS_ERROR_FILE_DIR_NOT_EMPTY:
      49           0 :       return NS_ERROR_DOM_FILESYSTEM_NO_MODIFICATION_ALLOWED_ERR;
      50             : 
      51             :     case NS_ERROR_FILE_TARGET_DOES_NOT_EXIST:
      52             :     case NS_ERROR_NOT_AVAILABLE:
      53           0 :       return NS_ERROR_DOM_FILE_NOT_FOUND_ERR;
      54             : 
      55             :     case NS_ERROR_FILE_ALREADY_EXISTS:
      56           0 :       return NS_ERROR_DOM_FILESYSTEM_PATH_EXISTS_ERR;
      57             : 
      58             :     case NS_ERROR_FILE_NOT_DIRECTORY:
      59           0 :       return NS_ERROR_DOM_FILESYSTEM_TYPE_MISMATCH_ERR;
      60             : 
      61             :     case NS_ERROR_UNEXPECTED:
      62             :     default:
      63           0 :       return NS_ERROR_DOM_FILESYSTEM_UNKNOWN_ERR;
      64             :   }
      65             : }
      66             : 
      67             : nsresult
      68           0 : DispatchToIOThread(nsIRunnable* aRunnable)
      69             : {
      70           0 :   MOZ_ASSERT(aRunnable);
      71             : 
      72             :   nsCOMPtr<nsIEventTarget> target
      73           0 :     = do_GetService(NS_STREAMTRANSPORTSERVICE_CONTRACTID);
      74           0 :   MOZ_ASSERT(target);
      75             : 
      76           0 :   return target->Dispatch(aRunnable, NS_DISPATCH_NORMAL);
      77             : }
      78             : 
      79             : // This runnable is used when an error value is set before doing any real
      80             : // operation on the I/O thread. In this case we skip all and we directly
      81             : // communicate the error.
      82           0 : class ErrorRunnable final : public CancelableRunnable
      83             : {
      84             : public:
      85           0 :   explicit ErrorRunnable(FileSystemTaskChildBase* aTask)
      86           0 :     : CancelableRunnable("ErrorRunnable")
      87           0 :     , mTask(aTask)
      88             :   {
      89           0 :     MOZ_ASSERT(aTask);
      90           0 :   }
      91             : 
      92             :   NS_IMETHOD
      93           0 :   Run() override
      94             :   {
      95           0 :     MOZ_ASSERT(NS_IsMainThread());
      96           0 :     MOZ_ASSERT(mTask->HasError());
      97             : 
      98           0 :     mTask->HandlerCallback();
      99           0 :     return NS_OK;
     100             :   }
     101             : 
     102             : private:
     103             :   RefPtr<FileSystemTaskChildBase> mTask;
     104             : };
     105             : 
     106             : } // anonymous namespace
     107             : 
     108           0 : NS_IMPL_ISUPPORTS(FileSystemTaskChildBase, nsIIPCBackgroundChildCreateCallback)
     109             : 
     110             : /**
     111             :  * FileSystemTaskBase class
     112             :  */
     113             : 
     114           0 : FileSystemTaskChildBase::FileSystemTaskChildBase(nsIGlobalObject* aGlobalObject,
     115           0 :                                                  FileSystemBase* aFileSystem)
     116             :   : mErrorValue(NS_OK)
     117             :   , mFileSystem(aFileSystem)
     118           0 :   , mGlobalObject(aGlobalObject)
     119             : {
     120           0 :   MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
     121           0 :   aFileSystem->AssertIsOnOwningThread();
     122           0 :   MOZ_ASSERT(aGlobalObject);
     123           0 : }
     124             : 
     125           0 : FileSystemTaskChildBase::~FileSystemTaskChildBase()
     126             : {
     127           0 :   mFileSystem->AssertIsOnOwningThread();
     128           0 : }
     129             : 
     130             : FileSystemBase*
     131           0 : FileSystemTaskChildBase::GetFileSystem() const
     132             : {
     133           0 :   mFileSystem->AssertIsOnOwningThread();
     134           0 :   return mFileSystem.get();
     135             : }
     136             : 
     137             : void
     138           0 : FileSystemTaskChildBase::Start()
     139             : {
     140           0 :   mFileSystem->AssertIsOnOwningThread();
     141             : 
     142             :   mozilla::ipc::PBackgroundChild* actor =
     143           0 :     mozilla::ipc::BackgroundChild::GetForCurrentThread();
     144           0 :   if (actor) {
     145           0 :     ActorCreated(actor);
     146             :   } else {
     147           0 :     if (NS_WARN_IF(
     148             :         !mozilla::ipc::BackgroundChild::GetOrCreateForCurrentThread(this))) {
     149           0 :       MOZ_CRASH();
     150             :     }
     151             :   }
     152           0 : }
     153             : 
     154             : void
     155           0 : FileSystemTaskChildBase::ActorFailed()
     156             : {
     157           0 :   MOZ_CRASH("Failed to create a PBackgroundChild actor!");
     158             : }
     159             : 
     160             : void
     161           0 : FileSystemTaskChildBase::ActorCreated(mozilla::ipc::PBackgroundChild* aActor)
     162             : {
     163           0 :   if (HasError()) {
     164             :     // In this case we don't want to use IPC at all.
     165           0 :     RefPtr<ErrorRunnable> runnable = new ErrorRunnable(this);
     166           0 :     FileSystemUtils::DispatchRunnable(mGlobalObject, runnable.forget());
     167           0 :     return;
     168             :   }
     169             : 
     170           0 :   if (mFileSystem->IsShutdown()) {
     171           0 :     return;
     172             :   }
     173             : 
     174           0 :   nsAutoString serialization;
     175           0 :   mFileSystem->SerializeDOMPath(serialization);
     176             : 
     177           0 :   ErrorResult rv;
     178           0 :   FileSystemParams params = GetRequestParams(serialization, rv);
     179           0 :   if (NS_WARN_IF(rv.Failed())) {
     180           0 :     rv.SuppressException();
     181           0 :     return;
     182             :   }
     183             : 
     184             :   // Retain a reference so the task object isn't deleted without IPDL's
     185             :   // knowledge. The reference will be released by
     186             :   // mozilla::ipc::BackgroundChildImpl::DeallocPFileSystemRequestChild.
     187           0 :   NS_ADDREF_THIS();
     188             : 
     189           0 :   if (NS_IsMainThread()) {
     190           0 :     nsIEventTarget* target = mGlobalObject->EventTargetFor(TaskCategory::Other);
     191           0 :     MOZ_ASSERT(target);
     192             : 
     193           0 :     aActor->SetEventTargetForActor(this, target);
     194             :   }
     195             : 
     196           0 :   aActor->SendPFileSystemRequestConstructor(this, params);
     197             : }
     198             : 
     199             : void
     200           0 : FileSystemTaskChildBase::SetRequestResult(const FileSystemResponseValue& aValue)
     201             : {
     202           0 :   mFileSystem->AssertIsOnOwningThread();
     203             : 
     204           0 :   if (aValue.type() == FileSystemResponseValue::TFileSystemErrorResponse) {
     205           0 :     FileSystemErrorResponse r = aValue;
     206           0 :     mErrorValue = r.error();
     207             :   } else {
     208           0 :     ErrorResult rv;
     209           0 :     SetSuccessRequestResult(aValue, rv);
     210           0 :     mErrorValue = rv.StealNSResult();
     211             :   }
     212           0 : }
     213             : 
     214             : mozilla::ipc::IPCResult
     215           0 : FileSystemTaskChildBase::Recv__delete__(const FileSystemResponseValue& aValue)
     216             : {
     217           0 :   mFileSystem->AssertIsOnOwningThread();
     218             : 
     219           0 :   SetRequestResult(aValue);
     220           0 :   HandlerCallback();
     221           0 :   return IPC_OK();
     222             : }
     223             : 
     224             : void
     225           0 : FileSystemTaskChildBase::SetError(const nsresult& aErrorValue)
     226             : {
     227           0 :   mErrorValue = FileSystemErrorFromNsError(aErrorValue);
     228           0 : }
     229             : 
     230             : /**
     231             :  * FileSystemTaskParentBase class
     232             :  */
     233             : 
     234           0 : FileSystemTaskParentBase::FileSystemTaskParentBase(
     235             :   FileSystemBase* aFileSystem,
     236             :   const FileSystemParams& aParam,
     237           0 :   FileSystemRequestParent* aParent)
     238             :   : Runnable("dom::FileSystemTaskParentBase")
     239             :   , mErrorValue(NS_OK)
     240             :   , mFileSystem(aFileSystem)
     241             :   , mRequestParent(aParent)
     242           0 :   , mBackgroundEventTarget(GetCurrentThreadEventTarget())
     243             : {
     244           0 :   MOZ_ASSERT(XRE_IsParentProcess(),
     245             :              "Only call from parent process!");
     246           0 :   MOZ_ASSERT(aFileSystem, "aFileSystem should not be null.");
     247           0 :   MOZ_ASSERT(aParent);
     248           0 :   MOZ_ASSERT(mBackgroundEventTarget);
     249           0 :   AssertIsOnBackgroundThread();
     250           0 : }
     251             : 
     252           0 : FileSystemTaskParentBase::~FileSystemTaskParentBase()
     253             : {
     254             :   // This task can be released on different threads because we dispatch it (as
     255             :   // runnable) to main-thread, I/O and then back to the PBackground thread.
     256           0 :   NS_ProxyRelease(
     257             :     "FileSystemTaskParentBase::mFileSystem",
     258           0 :     mBackgroundEventTarget, mFileSystem.forget());
     259           0 :   NS_ProxyRelease(
     260             :     "FileSystemTaskParentBase::mRequestParent",
     261           0 :     mBackgroundEventTarget, mRequestParent.forget());
     262           0 : }
     263             : 
     264             : void
     265           0 : FileSystemTaskParentBase::Start()
     266             : {
     267           0 :   AssertIsOnBackgroundThread();
     268           0 :   mFileSystem->AssertIsOnOwningThread();
     269             : 
     270           0 :   DebugOnly<nsresult> rv = DispatchToIOThread(this);
     271           0 :   NS_WARNING_ASSERTION(NS_SUCCEEDED(rv), "DispatchToIOThread failed");
     272           0 : }
     273             : 
     274             : void
     275           0 : FileSystemTaskParentBase::HandleResult()
     276             : {
     277           0 :   AssertIsOnBackgroundThread();
     278           0 :   mFileSystem->AssertIsOnOwningThread();
     279             : 
     280           0 :   if (mFileSystem->IsShutdown()) {
     281           0 :     return;
     282             :   }
     283             : 
     284           0 :   MOZ_ASSERT(mRequestParent);
     285           0 :   Unused << mRequestParent->Send__delete__(mRequestParent, GetRequestResult());
     286             : }
     287             : 
     288             : FileSystemResponseValue
     289           0 : FileSystemTaskParentBase::GetRequestResult() const
     290             : {
     291           0 :   AssertIsOnBackgroundThread();
     292           0 :   mFileSystem->AssertIsOnOwningThread();
     293             : 
     294           0 :   if (HasError()) {
     295           0 :     return FileSystemErrorResponse(mErrorValue);
     296             :   }
     297             : 
     298           0 :   ErrorResult rv;
     299           0 :   FileSystemResponseValue value = GetSuccessRequestResult(rv);
     300           0 :   if (NS_WARN_IF(rv.Failed())) {
     301           0 :     return FileSystemErrorResponse(rv.StealNSResult());
     302             :   }
     303             : 
     304           0 :   return value;
     305             : }
     306             : 
     307             : void
     308           0 : FileSystemTaskParentBase::SetError(const nsresult& aErrorValue)
     309             : {
     310           0 :   mErrorValue = FileSystemErrorFromNsError(aErrorValue);
     311           0 : }
     312             : 
     313             : NS_IMETHODIMP
     314           0 : FileSystemTaskParentBase::Run()
     315             : {
     316             :   // This method can run in 2 different threads. Here why:
     317             :   // 1. We are are on the I/O thread and we call IOWork().
     318             :   // 2. After step 1, it returns back to the PBackground thread.
     319             : 
     320             :   // Run I/O thread tasks
     321           0 :   if (!IsOnBackgroundThread()) {
     322           0 :     nsresult rv = IOWork();
     323           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     324           0 :       SetError(rv);
     325             :     }
     326             : 
     327             :     // Let's go back to PBackground thread to finish the work.
     328           0 :     rv = mBackgroundEventTarget->Dispatch(this, NS_DISPATCH_NORMAL);
     329           0 :     if (NS_WARN_IF(NS_FAILED(rv))) {
     330           0 :       return rv;
     331             :     }
     332             : 
     333           0 :     return NS_OK;
     334             :   }
     335             : 
     336             :   // If we are here, it's because the I/O work has been done and we have to
     337             :   // handle the result back via IPC.
     338           0 :   AssertIsOnBackgroundThread();
     339           0 :   HandleResult();
     340           0 :   return NS_OK;
     341             : }
     342             : 
     343             : } // namespace dom
     344             : } // namespace mozilla

Generated by: LCOV version 1.13