LCOV - code coverage report
Current view: top level - dom/indexedDB - IDBFileHandle.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 350 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 40 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 "IDBFileHandle.h"
       8             : 
       9             : #include "ActorsChild.h"
      10             : #include "BackgroundChildImpl.h"
      11             : #include "IDBEvents.h"
      12             : #include "IDBMutableFile.h"
      13             : #include "mozilla/Assertions.h"
      14             : #include "mozilla/dom/File.h"
      15             : #include "mozilla/dom/IDBFileHandleBinding.h"
      16             : #include "mozilla/dom/IPCBlobUtils.h"
      17             : #include "mozilla/dom/PBackgroundFileHandle.h"
      18             : #include "mozilla/EventDispatcher.h"
      19             : #include "mozilla/ipc/BackgroundChild.h"
      20             : #include "nsContentUtils.h"
      21             : #include "nsQueryObject.h"
      22             : #include "nsServiceManagerUtils.h"
      23             : #include "nsWidgetsCID.h"
      24             : 
      25             : namespace mozilla {
      26             : namespace dom {
      27             : 
      28             : using namespace mozilla::dom::indexedDB;
      29             : using namespace mozilla::ipc;
      30             : 
      31             : namespace {
      32             : 
      33             : already_AddRefed<IDBFileRequest>
      34           0 : GenerateFileRequest(IDBFileHandle* aFileHandle)
      35             : {
      36           0 :   MOZ_ASSERT(aFileHandle);
      37           0 :   aFileHandle->AssertIsOnOwningThread();
      38             : 
      39             :   RefPtr<IDBFileRequest> fileRequest =
      40           0 :     IDBFileRequest::Create(aFileHandle, /* aWrapAsDOMRequest */ false);
      41           0 :   MOZ_ASSERT(fileRequest);
      42             : 
      43           0 :   return fileRequest.forget();
      44             : }
      45             : 
      46             : } // namespace
      47             : 
      48           0 : IDBFileHandle::IDBFileHandle(IDBMutableFile* aMutableFile,
      49           0 :                              FileMode aMode)
      50             :   : mMutableFile(aMutableFile)
      51             :   , mBackgroundActor(nullptr)
      52             :   , mLocation(0)
      53             :   , mPendingRequestCount(0)
      54             :   , mReadyState(INITIAL)
      55             :   , mMode(aMode)
      56             :   , mAborted(false)
      57             :   , mCreating(false)
      58             : #ifdef DEBUG
      59             :   , mSentFinishOrAbort(false)
      60           0 :   , mFiredCompleteOrAbort(false)
      61             : #endif
      62             : {
      63           0 :   MOZ_ASSERT(aMutableFile);
      64           0 :   aMutableFile->AssertIsOnOwningThread();
      65           0 : }
      66             : 
      67           0 : IDBFileHandle::~IDBFileHandle()
      68             : {
      69           0 :   AssertIsOnOwningThread();
      70           0 :   MOZ_ASSERT(!mPendingRequestCount);
      71           0 :   MOZ_ASSERT(!mCreating);
      72           0 :   MOZ_ASSERT(mSentFinishOrAbort);
      73           0 :   MOZ_ASSERT_IF(mBackgroundActor, mFiredCompleteOrAbort);
      74             : 
      75           0 :   mMutableFile->UnregisterFileHandle(this);
      76             : 
      77           0 :   if (mBackgroundActor) {
      78           0 :     mBackgroundActor->SendDeleteMeInternal();
      79             : 
      80           0 :     MOZ_ASSERT(!mBackgroundActor, "SendDeleteMeInternal should have cleared!");
      81             :   }
      82           0 : }
      83             : 
      84             : // static
      85             : already_AddRefed<IDBFileHandle>
      86           0 : IDBFileHandle::Create(IDBMutableFile* aMutableFile,
      87             :                       FileMode aMode)
      88             : {
      89           0 :   MOZ_ASSERT(aMutableFile);
      90           0 :   aMutableFile->AssertIsOnOwningThread();
      91           0 :   MOZ_ASSERT(aMode == FileMode::Readonly || aMode == FileMode::Readwrite);
      92             : 
      93             :   RefPtr<IDBFileHandle> fileHandle =
      94           0 :     new IDBFileHandle(aMutableFile, aMode);
      95             : 
      96           0 :   fileHandle->BindToOwner(aMutableFile);
      97             : 
      98             :   // XXX Fix!
      99           0 :   MOZ_ASSERT(NS_IsMainThread(), "This won't work on non-main threads!");
     100             : 
     101           0 :   nsCOMPtr<nsIRunnable> runnable = do_QueryObject(fileHandle);
     102           0 :   nsContentUtils::RunInMetastableState(runnable.forget());
     103             : 
     104           0 :   fileHandle->mCreating = true;
     105             : 
     106           0 :   aMutableFile->RegisterFileHandle(fileHandle);
     107             : 
     108           0 :   return fileHandle.forget();
     109             : }
     110             : 
     111             : // static
     112             : IDBFileHandle*
     113           0 : IDBFileHandle::GetCurrent()
     114             : {
     115           0 :   MOZ_ASSERT(BackgroundChild::GetForCurrentThread());
     116             : 
     117             :   BackgroundChildImpl::ThreadLocal* threadLocal =
     118           0 :     BackgroundChildImpl::GetThreadLocalForCurrentThread();
     119           0 :   MOZ_ASSERT(threadLocal);
     120             : 
     121           0 :   return threadLocal->mCurrentFileHandle;
     122             : }
     123             : 
     124             : #ifdef DEBUG
     125             : 
     126             : void
     127           0 : IDBFileHandle::AssertIsOnOwningThread() const
     128             : {
     129           0 :   MOZ_ASSERT(mMutableFile);
     130           0 :   mMutableFile->AssertIsOnOwningThread();
     131           0 : }
     132             : 
     133             : #endif // DEBUG
     134             : 
     135             : void
     136           0 : IDBFileHandle::SetBackgroundActor(BackgroundFileHandleChild* aActor)
     137             : {
     138           0 :   AssertIsOnOwningThread();
     139           0 :   MOZ_ASSERT(aActor);
     140           0 :   MOZ_ASSERT(!mBackgroundActor);
     141             : 
     142           0 :   mBackgroundActor = aActor;
     143           0 : }
     144             : 
     145             : void
     146           0 : IDBFileHandle::StartRequest(IDBFileRequest* aFileRequest,
     147             :                             const FileRequestParams& aParams)
     148             : {
     149           0 :   AssertIsOnOwningThread();
     150           0 :   MOZ_ASSERT(aFileRequest);
     151           0 :   MOZ_ASSERT(aParams.type() != FileRequestParams::T__None);
     152             : 
     153             :   BackgroundFileRequestChild* actor =
     154           0 :     new BackgroundFileRequestChild(aFileRequest);
     155             : 
     156           0 :   mBackgroundActor->SendPBackgroundFileRequestConstructor(actor, aParams);
     157             : 
     158             :   // Balanced in BackgroundFileRequestChild::Recv__delete__().
     159           0 :   OnNewRequest();
     160           0 : }
     161             : 
     162             : void
     163           0 : IDBFileHandle::OnNewRequest()
     164             : {
     165           0 :   AssertIsOnOwningThread();
     166             : 
     167           0 :   if (!mPendingRequestCount) {
     168           0 :     MOZ_ASSERT(mReadyState == INITIAL);
     169           0 :     mReadyState = LOADING;
     170             :   }
     171             : 
     172           0 :   ++mPendingRequestCount;
     173           0 : }
     174             : 
     175             : void
     176           0 : IDBFileHandle::OnRequestFinished(bool aActorDestroyedNormally)
     177             : {
     178           0 :   AssertIsOnOwningThread();
     179           0 :   MOZ_ASSERT(mPendingRequestCount);
     180             : 
     181           0 :   --mPendingRequestCount;
     182             : 
     183           0 :   if (!mPendingRequestCount && !mMutableFile->IsInvalidated()) {
     184           0 :     mReadyState = FINISHING;
     185             : 
     186           0 :     if (aActorDestroyedNormally) {
     187           0 :       if (!mAborted) {
     188           0 :         SendFinish();
     189             :       } else {
     190           0 :         SendAbort();
     191             :       }
     192             :     } else {
     193             :       // Don't try to send any more messages to the parent if the request actor
     194             :       // was killed.
     195             : #ifdef DEBUG
     196           0 :       MOZ_ASSERT(!mSentFinishOrAbort);
     197           0 :       mSentFinishOrAbort = true;
     198             : #endif
     199             :     }
     200             :   }
     201           0 : }
     202             : 
     203             : void
     204           0 : IDBFileHandle::FireCompleteOrAbortEvents(bool aAborted)
     205             : {
     206           0 :   AssertIsOnOwningThread();
     207           0 :   MOZ_ASSERT(!mFiredCompleteOrAbort);
     208             : 
     209           0 :   mReadyState = DONE;
     210             : 
     211             : #ifdef DEBUG
     212           0 :   mFiredCompleteOrAbort = true;
     213             : #endif
     214             : 
     215           0 :   nsCOMPtr<nsIDOMEvent> event;
     216           0 :   if (aAborted) {
     217           0 :     event = CreateGenericEvent(this, nsDependentString(kAbortEventType),
     218           0 :                                eDoesBubble, eNotCancelable);
     219             :   } else {
     220           0 :     event = CreateGenericEvent(this, nsDependentString(kCompleteEventType),
     221           0 :                                eDoesNotBubble, eNotCancelable);
     222             :   }
     223           0 :   if (NS_WARN_IF(!event)) {
     224           0 :     return;
     225             :   }
     226             : 
     227             :   bool dummy;
     228           0 :   if (NS_FAILED(DispatchEvent(event, &dummy))) {
     229           0 :     NS_WARNING("DispatchEvent failed!");
     230             :   }
     231             : }
     232             : 
     233             : bool
     234           0 : IDBFileHandle::IsOpen() const
     235             : {
     236           0 :   AssertIsOnOwningThread();
     237             : 
     238             :   // If we haven't started anything then we're open.
     239           0 :   if (mReadyState == INITIAL) {
     240           0 :     return true;
     241             :   }
     242             : 
     243             :   // If we've already started then we need to check to see if we still have the
     244             :   // mCreating flag set. If we do (i.e. we haven't returned to the event loop
     245             :   // from the time we were created) then we are open. Otherwise check the
     246             :   // currently running file handles to see if it's the same. We only allow other
     247             :   // requests to be made if this file handle is currently running.
     248           0 :   if (mReadyState == LOADING && (mCreating || GetCurrent() == this)) {
     249           0 :     return true;
     250             :   }
     251             : 
     252           0 :   return false;
     253             : }
     254             : 
     255             : void
     256           0 : IDBFileHandle::Abort()
     257             : {
     258           0 :   AssertIsOnOwningThread();
     259             : 
     260           0 :   if (IsFinishingOrDone()) {
     261             :     // Already started (and maybe finished) the finish or abort so there is
     262             :     // nothing to do here.
     263           0 :     return;
     264             :   }
     265             : 
     266           0 :   const bool isInvalidated = mMutableFile->IsInvalidated();
     267           0 :   bool needToSendAbort = mReadyState == INITIAL && !isInvalidated;
     268             : 
     269             : #ifdef DEBUG
     270           0 :   if (isInvalidated) {
     271           0 :     mSentFinishOrAbort = true;
     272             :   }
     273             : #endif
     274             : 
     275           0 :   mAborted = true;
     276           0 :   mReadyState = DONE;
     277             : 
     278             :   // Fire the abort event if there are no outstanding requests. Otherwise the
     279             :   // abort event will be fired when all outstanding requests finish.
     280           0 :   if (needToSendAbort) {
     281           0 :     SendAbort();
     282             :   }
     283             : }
     284             : 
     285             : already_AddRefed<IDBFileRequest>
     286           0 : IDBFileHandle::GetMetadata(const IDBFileMetadataParameters& aParameters,
     287             :                            ErrorResult& aRv)
     288             : {
     289           0 :   AssertIsOnOwningThread();
     290             : 
     291             :   // Common state checking
     292           0 :   if (!CheckState(aRv)) {
     293           0 :     return nullptr;
     294             :   }
     295             : 
     296             :   // Argument checking for get metadata.
     297           0 :   if (!aParameters.mSize && !aParameters.mLastModified) {
     298           0 :     aRv.ThrowTypeError<MSG_METADATA_NOT_CONFIGURED>();
     299           0 :     return nullptr;
     300             :   }
     301             : 
     302             :  // Do nothing if the window is closed
     303           0 :   if (!CheckWindow()) {
     304           0 :     return nullptr;
     305             :   }
     306             : 
     307           0 :   FileRequestGetMetadataParams params;
     308           0 :   params.size() = aParameters.mSize;
     309           0 :   params.lastModified() = aParameters.mLastModified;
     310             : 
     311           0 :   RefPtr<IDBFileRequest> fileRequest = GenerateFileRequest(this);
     312             : 
     313           0 :   StartRequest(fileRequest, params);
     314             : 
     315           0 :   return fileRequest.forget();
     316             : }
     317             : 
     318             : already_AddRefed<IDBFileRequest>
     319           0 : IDBFileHandle::Truncate(const Optional<uint64_t>& aSize, ErrorResult& aRv)
     320             : {
     321           0 :   AssertIsOnOwningThread();
     322             : 
     323             :   // State checking for write
     324           0 :   if (!CheckStateForWrite(aRv)) {
     325           0 :     return nullptr;
     326             :   }
     327             : 
     328             :   // Getting location and additional state checking for truncate
     329             :   uint64_t location;
     330           0 :   if (aSize.WasPassed()) {
     331             :     // Just in case someone calls us from C++
     332           0 :     MOZ_ASSERT(aSize.Value() != UINT64_MAX, "Passed wrong size!");
     333           0 :     location = aSize.Value();
     334             :   } else {
     335           0 :     if (mLocation == UINT64_MAX) {
     336           0 :       aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR);
     337           0 :       return nullptr;
     338             :     }
     339           0 :     location = mLocation;
     340             :   }
     341             : 
     342             :   // Do nothing if the window is closed
     343           0 :   if (!CheckWindow()) {
     344           0 :     return nullptr;
     345             :   }
     346             : 
     347           0 :   FileRequestTruncateParams params;
     348           0 :   params.offset() = location;
     349             : 
     350           0 :   RefPtr<IDBFileRequest> fileRequest = GenerateFileRequest(this);
     351             : 
     352           0 :   StartRequest(fileRequest, params);
     353             : 
     354           0 :   if (aSize.WasPassed()) {
     355           0 :     mLocation = aSize.Value();
     356             :   }
     357             : 
     358           0 :   return fileRequest.forget();
     359             : }
     360             : 
     361             : already_AddRefed<IDBFileRequest>
     362           0 : IDBFileHandle::Flush(ErrorResult& aRv)
     363             : {
     364           0 :   AssertIsOnOwningThread();
     365             : 
     366             :   // State checking for write
     367           0 :   if (!CheckStateForWrite(aRv)) {
     368           0 :     return nullptr;
     369             :   }
     370             : 
     371             :   // Do nothing if the window is closed
     372           0 :   if (!CheckWindow()) {
     373           0 :     return nullptr;
     374             :   }
     375             : 
     376           0 :   FileRequestFlushParams params;
     377             : 
     378           0 :   RefPtr<IDBFileRequest> fileRequest = GenerateFileRequest(this);
     379             : 
     380           0 :   StartRequest(fileRequest, params);
     381             : 
     382           0 :   return fileRequest.forget();
     383             : }
     384             : 
     385             : void
     386           0 : IDBFileHandle::Abort(ErrorResult& aRv)
     387             : {
     388           0 :   AssertIsOnOwningThread();
     389             : 
     390             :   // This method is special enough for not using generic state checking methods.
     391             : 
     392           0 :   if (IsFinishingOrDone()) {
     393           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR);
     394           0 :     return;
     395             :   }
     396             : 
     397           0 :   Abort();
     398             : }
     399             : 
     400             : bool
     401           0 : IDBFileHandle::CheckState(ErrorResult& aRv)
     402             : {
     403           0 :   if (!IsOpen()) {
     404           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_INACTIVE_ERR);
     405           0 :     return false;
     406             :   }
     407             : 
     408           0 :   return true;
     409             : }
     410             : 
     411             : bool
     412           0 : IDBFileHandle::CheckStateAndArgumentsForRead(uint64_t aSize, ErrorResult& aRv)
     413             : {
     414             :   // Common state checking
     415           0 :   if (!CheckState(aRv)) {
     416           0 :     return false;
     417             :   }
     418             : 
     419             :   // Additional state checking for read
     420           0 :   if (mLocation == UINT64_MAX) {
     421           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR);
     422           0 :     return false;
     423             :   }
     424             : 
     425             :   // Argument checking for read
     426           0 :   if (!aSize) {
     427           0 :     aRv.ThrowTypeError<MSG_INVALID_READ_SIZE>();
     428           0 :     return false;
     429             :   }
     430             : 
     431           0 :   return true;
     432             : }
     433             : 
     434             : bool
     435           0 : IDBFileHandle::CheckStateForWrite(ErrorResult& aRv)
     436             : {
     437             :   // Common state checking
     438           0 :   if (!CheckState(aRv)) {
     439           0 :     return false;
     440             :   }
     441             : 
     442             :   // Additional state checking for write
     443           0 :   if (mMode != FileMode::Readwrite) {
     444           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_READ_ONLY_ERR);
     445           0 :     return false;
     446             :   }
     447             : 
     448           0 :   return true;
     449             : }
     450             : 
     451             : bool
     452           0 : IDBFileHandle::CheckStateForWriteOrAppend(bool aAppend, ErrorResult& aRv)
     453             : {
     454             :   // State checking for write
     455           0 :   if (!CheckStateForWrite(aRv)) {
     456           0 :     return false;
     457             :   }
     458             : 
     459             :   // Additional state checking for write
     460           0 :   if (!aAppend && mLocation == UINT64_MAX) {
     461           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_NOT_ALLOWED_ERR);
     462           0 :     return false;
     463             :   }
     464             : 
     465           0 :   return true;
     466             : }
     467             : 
     468             : bool
     469           0 : IDBFileHandle::CheckWindow()
     470             : {
     471           0 :   AssertIsOnOwningThread();
     472             : 
     473           0 :   return GetOwner();
     474             : }
     475             : 
     476             : already_AddRefed<IDBFileRequest>
     477           0 : IDBFileHandle::Read(uint64_t aSize, bool aHasEncoding,
     478             :                     const nsAString& aEncoding, ErrorResult& aRv)
     479             : {
     480           0 :   AssertIsOnOwningThread();
     481             : 
     482             :   // State and argument checking for read
     483           0 :   if (!CheckStateAndArgumentsForRead(aSize, aRv)) {
     484           0 :     return nullptr;
     485             :   }
     486             : 
     487             :   // Do nothing if the window is closed
     488           0 :   if (!CheckWindow()) {
     489           0 :     return nullptr;
     490             :   }
     491             : 
     492           0 :   FileRequestReadParams params;
     493           0 :   params.offset() = mLocation;
     494           0 :   params.size() = aSize;
     495             : 
     496           0 :   RefPtr<IDBFileRequest> fileRequest = GenerateFileRequest(this);
     497           0 :   if (aHasEncoding) {
     498           0 :     fileRequest->SetEncoding(aEncoding);
     499             :   }
     500             : 
     501           0 :   StartRequest(fileRequest, params);
     502             : 
     503           0 :   mLocation += aSize;
     504             : 
     505           0 :   return fileRequest.forget();
     506             : }
     507             : 
     508             : already_AddRefed<IDBFileRequest>
     509           0 : IDBFileHandle::WriteOrAppend(
     510             :                        const StringOrArrayBufferOrArrayBufferViewOrBlob& aValue,
     511             :                        bool aAppend,
     512             :                        ErrorResult& aRv)
     513             : {
     514           0 :   AssertIsOnOwningThread();
     515             : 
     516           0 :   if (aValue.IsString()) {
     517           0 :     return WriteOrAppend(aValue.GetAsString(), aAppend, aRv);
     518             :   }
     519             : 
     520           0 :   if (aValue.IsArrayBuffer()) {
     521           0 :     return WriteOrAppend(aValue.GetAsArrayBuffer(), aAppend, aRv);
     522             :   }
     523             : 
     524           0 :   if (aValue.IsArrayBufferView()) {
     525           0 :     return WriteOrAppend(aValue.GetAsArrayBufferView(), aAppend, aRv);
     526             :   }
     527             : 
     528           0 :   MOZ_ASSERT(aValue.IsBlob());
     529           0 :   return WriteOrAppend(aValue.GetAsBlob(), aAppend, aRv);
     530             : }
     531             : 
     532             : already_AddRefed<IDBFileRequest>
     533           0 : IDBFileHandle::WriteOrAppend(const nsAString& aValue,
     534             :                              bool aAppend,
     535             :                              ErrorResult& aRv)
     536             : {
     537           0 :   AssertIsOnOwningThread();
     538             : 
     539             :   // State checking for write or append
     540           0 :   if (!CheckStateForWriteOrAppend(aAppend, aRv)) {
     541           0 :     return nullptr;
     542             :   }
     543             : 
     544           0 :   NS_ConvertUTF16toUTF8 cstr(aValue);
     545             : 
     546           0 :   uint64_t dataLength = cstr.Length();;
     547           0 :   if (!dataLength) {
     548           0 :     return nullptr;
     549             :   }
     550             : 
     551           0 :   FileRequestStringData stringData(cstr);
     552             : 
     553             :   // Do nothing if the window is closed
     554           0 :   if (!CheckWindow()) {
     555           0 :     return nullptr;
     556             :   }
     557             : 
     558           0 :   return WriteInternal(stringData, dataLength, aAppend, aRv);
     559             : }
     560             : 
     561             : already_AddRefed<IDBFileRequest>
     562           0 : IDBFileHandle::WriteOrAppend(const ArrayBuffer& aValue,
     563             :                              bool aAppend,
     564             :                              ErrorResult& aRv)
     565             : {
     566           0 :   AssertIsOnOwningThread();
     567             : 
     568             :   // State checking for write or append
     569           0 :   if (!CheckStateForWriteOrAppend(aAppend, aRv)) {
     570           0 :     return nullptr;
     571             :   }
     572             : 
     573           0 :   aValue.ComputeLengthAndData();
     574             : 
     575           0 :   uint64_t dataLength = aValue.Length();;
     576           0 :   if (!dataLength) {
     577           0 :     return nullptr;
     578             :   }
     579             : 
     580           0 :   const char* data = reinterpret_cast<const char*>(aValue.Data());
     581             : 
     582           0 :   FileRequestStringData stringData;
     583           0 :   if (NS_WARN_IF(!stringData.string().Assign(data, aValue.Length(),
     584             :                                              fallible_t()))) {
     585           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     586           0 :     return nullptr;
     587             :   }
     588             : 
     589             :   // Do nothing if the window is closed
     590           0 :   if (!CheckWindow()) {
     591           0 :     return nullptr;
     592             :   }
     593             : 
     594           0 :   return WriteInternal(stringData, dataLength, aAppend, aRv);
     595             : }
     596             : 
     597             : already_AddRefed<IDBFileRequest>
     598           0 : IDBFileHandle::WriteOrAppend(const ArrayBufferView& aValue,
     599             :                              bool aAppend,
     600             :                              ErrorResult& aRv)
     601             : {
     602           0 :   AssertIsOnOwningThread();
     603             : 
     604             :   // State checking for write or append
     605           0 :   if (!CheckStateForWriteOrAppend(aAppend, aRv)) {
     606           0 :     return nullptr;
     607             :   }
     608             : 
     609           0 :   aValue.ComputeLengthAndData();
     610             : 
     611           0 :   uint64_t dataLength = aValue.Length();;
     612           0 :   if (!dataLength) {
     613           0 :     return nullptr;
     614             :   }
     615             : 
     616           0 :   const char* data = reinterpret_cast<const char*>(aValue.Data());
     617             : 
     618           0 :   FileRequestStringData stringData;
     619           0 :   if (NS_WARN_IF(!stringData.string().Assign(data, aValue.Length(),
     620             :                                              fallible_t()))) {
     621           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     622           0 :     return nullptr;
     623             :   }
     624             : 
     625             :   // Do nothing if the window is closed
     626           0 :   if (!CheckWindow()) {
     627           0 :     return nullptr;
     628             :   }
     629             : 
     630           0 :   return WriteInternal(stringData, dataLength, aAppend, aRv);
     631             : }
     632             : 
     633             : already_AddRefed<IDBFileRequest>
     634           0 : IDBFileHandle::WriteOrAppend(Blob& aValue,
     635             :                              bool aAppend,
     636             :                              ErrorResult& aRv)
     637             : {
     638           0 :   AssertIsOnOwningThread();
     639             : 
     640             :   // State checking for write or append
     641           0 :   if (!CheckStateForWriteOrAppend(aAppend, aRv)) {
     642           0 :     return nullptr;
     643             :   }
     644             : 
     645           0 :   ErrorResult error;
     646           0 :   uint64_t dataLength = aValue.GetSize(error);
     647           0 :   if (NS_WARN_IF(error.Failed())) {
     648           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     649           0 :     return nullptr;
     650             :   }
     651             : 
     652           0 :   if (!dataLength) {
     653           0 :     return nullptr;
     654             :   }
     655             : 
     656           0 :   PBackgroundChild* backgroundActor = BackgroundChild::GetForCurrentThread();
     657           0 :   MOZ_ASSERT(backgroundActor);
     658             : 
     659           0 :   IPCBlob ipcBlob;
     660             :   nsresult rv =
     661           0 :     IPCBlobUtils::Serialize(aValue.Impl(), backgroundActor, ipcBlob);
     662           0 :   if (NS_WARN_IF(NS_FAILED(rv))) {
     663           0 :     aRv.Throw(NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR);
     664           0 :     return nullptr;
     665             :   }
     666             : 
     667           0 :   FileRequestBlobData blobData;
     668           0 :   blobData.blob() = ipcBlob;
     669             : 
     670             :   // Do nothing if the window is closed
     671           0 :   if (!CheckWindow()) {
     672           0 :     return nullptr;
     673             :   }
     674             : 
     675           0 :   return WriteInternal(blobData, dataLength, aAppend, aRv);
     676             : }
     677             : 
     678             : already_AddRefed<IDBFileRequest>
     679           0 : IDBFileHandle::WriteInternal(const FileRequestData& aData,
     680             :                              uint64_t aDataLength,
     681             :                              bool aAppend,
     682             :                              ErrorResult& aRv)
     683             : {
     684           0 :   AssertIsOnOwningThread();
     685             : 
     686           0 :   DebugOnly<ErrorResult> error;
     687           0 :   MOZ_ASSERT(CheckStateForWrite(error));
     688           0 :   MOZ_ASSERT_IF(!aAppend, mLocation != UINT64_MAX);
     689           0 :   MOZ_ASSERT(aDataLength);
     690           0 :   MOZ_ASSERT(CheckWindow());
     691             : 
     692           0 :   FileRequestWriteParams params;
     693           0 :   params.offset() = aAppend ? UINT64_MAX : mLocation;
     694           0 :   params.data() = aData;
     695           0 :   params.dataLength() = aDataLength;
     696             : 
     697           0 :   RefPtr<IDBFileRequest> fileRequest = GenerateFileRequest(this);
     698           0 :   MOZ_ASSERT(fileRequest);
     699             : 
     700           0 :   StartRequest(fileRequest, params);
     701             : 
     702           0 :   if (aAppend) {
     703           0 :     mLocation = UINT64_MAX;
     704             :   }
     705             :   else {
     706           0 :     mLocation += aDataLength;
     707             :   }
     708             : 
     709           0 :   return fileRequest.forget();
     710             : }
     711             : 
     712             : void
     713           0 : IDBFileHandle::SendFinish()
     714             : {
     715           0 :   AssertIsOnOwningThread();
     716           0 :   MOZ_ASSERT(!mAborted);
     717           0 :   MOZ_ASSERT(IsFinishingOrDone());
     718           0 :   MOZ_ASSERT(!mSentFinishOrAbort);
     719           0 :   MOZ_ASSERT(!mPendingRequestCount);
     720             : 
     721           0 :   MOZ_ASSERT(mBackgroundActor);
     722           0 :   mBackgroundActor->SendFinish();
     723             : 
     724             : #ifdef DEBUG
     725           0 :   mSentFinishOrAbort = true;
     726             : #endif
     727           0 : }
     728             : 
     729             : void
     730           0 : IDBFileHandle::SendAbort()
     731             : {
     732           0 :   AssertIsOnOwningThread();
     733           0 :   MOZ_ASSERT(mAborted);
     734           0 :   MOZ_ASSERT(IsFinishingOrDone());
     735           0 :   MOZ_ASSERT(!mSentFinishOrAbort);
     736             : 
     737           0 :   MOZ_ASSERT(mBackgroundActor);
     738           0 :   mBackgroundActor->SendAbort();
     739             : 
     740             : #ifdef DEBUG
     741           0 :   mSentFinishOrAbort = true;
     742             : #endif
     743           0 : }
     744             : 
     745           0 : NS_IMPL_ADDREF_INHERITED(IDBFileHandle, DOMEventTargetHelper)
     746           0 : NS_IMPL_RELEASE_INHERITED(IDBFileHandle, DOMEventTargetHelper)
     747             : 
     748           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(IDBFileHandle)
     749           0 :   NS_INTERFACE_MAP_ENTRY(nsIRunnable)
     750           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
     751           0 : NS_INTERFACE_MAP_END_INHERITING(DOMEventTargetHelper)
     752             : 
     753             : NS_IMPL_CYCLE_COLLECTION_CLASS(IDBFileHandle)
     754             : 
     755           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(IDBFileHandle,
     756             :                                                   DOMEventTargetHelper)
     757           0 :   NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mMutableFile)
     758           0 : NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
     759             : 
     760           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(IDBFileHandle,
     761             :                                                 DOMEventTargetHelper)
     762             :   // Don't unlink mMutableFile!
     763           0 : NS_IMPL_CYCLE_COLLECTION_UNLINK_END
     764             : 
     765             : NS_IMETHODIMP
     766           0 : IDBFileHandle::Run()
     767             : {
     768           0 :   AssertIsOnOwningThread();
     769             : 
     770             :   // We're back at the event loop, no longer newborn.
     771           0 :   mCreating = false;
     772             : 
     773             :   // Maybe finish if there were no requests generated.
     774           0 :   if (mReadyState == INITIAL) {
     775           0 :     mReadyState = DONE;
     776             : 
     777           0 :     SendFinish();
     778             :   }
     779             : 
     780           0 :   return NS_OK;
     781             : }
     782             : 
     783             : nsresult
     784           0 : IDBFileHandle::GetEventTargetParent(EventChainPreVisitor& aVisitor)
     785             : {
     786           0 :   AssertIsOnOwningThread();
     787             : 
     788           0 :   aVisitor.mCanHandle = true;
     789           0 :   aVisitor.mParentTarget = mMutableFile;
     790           0 :   return NS_OK;
     791             : }
     792             : 
     793             : // virtual
     794             : JSObject*
     795           0 : IDBFileHandle::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     796             : {
     797           0 :   AssertIsOnOwningThread();
     798             : 
     799           0 :   return IDBFileHandleBinding::Wrap(aCx, this, aGivenProto);
     800             : }
     801             : 
     802             : } // namespace dom
     803             : } // namespace mozilla

Generated by: LCOV version 1.13