ActorsChild.cpp 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744
  1. /* This Source Code Form is subject to the terms of the Mozilla Public
  2. * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  3. * You can obtain one at http://mozilla.org/MPL/2.0/. */
  4. #include "ActorsChild.h"
  5. #include "BackgroundChildImpl.h"
  6. #include "FileHandleBase.h"
  7. #include "FileRequestBase.h"
  8. #include "js/Date.h"
  9. #include "mozilla/dom/EncodingUtils.h"
  10. #include "mozilla/dom/File.h"
  11. #include "mozilla/dom/ipc/BlobChild.h"
  12. #include "MutableFileBase.h"
  13. #include "nsCOMPtr.h"
  14. #include "nsContentUtils.h"
  15. #include "nsString.h"
  16. #include "xpcpublic.h"
  17. #include "mozilla/dom/BindingUtils.h"
  18. namespace mozilla {
  19. namespace dom {
  20. /*******************************************************************************
  21. * Helpers
  22. ******************************************************************************/
  23. namespace {
  24. class MOZ_STACK_CLASS AutoSetCurrentFileHandle final
  25. {
  26. typedef mozilla::ipc::BackgroundChildImpl BackgroundChildImpl;
  27. FileHandleBase* const mFileHandle;
  28. FileHandleBase* mPreviousFileHandle;
  29. FileHandleBase** mThreadLocalSlot;
  30. public:
  31. explicit AutoSetCurrentFileHandle(FileHandleBase* aFileHandle)
  32. : mFileHandle(aFileHandle)
  33. , mPreviousFileHandle(nullptr)
  34. , mThreadLocalSlot(nullptr)
  35. {
  36. if (aFileHandle) {
  37. BackgroundChildImpl::ThreadLocal* threadLocal =
  38. BackgroundChildImpl::GetThreadLocalForCurrentThread();
  39. MOZ_ASSERT(threadLocal);
  40. // Hang onto this location for resetting later.
  41. mThreadLocalSlot = &threadLocal->mCurrentFileHandle;
  42. // Save the current value.
  43. mPreviousFileHandle = *mThreadLocalSlot;
  44. // Set the new value.
  45. *mThreadLocalSlot = aFileHandle;
  46. }
  47. }
  48. ~AutoSetCurrentFileHandle()
  49. {
  50. MOZ_ASSERT_IF(mThreadLocalSlot, mFileHandle);
  51. MOZ_ASSERT_IF(mThreadLocalSlot, *mThreadLocalSlot == mFileHandle);
  52. if (mThreadLocalSlot) {
  53. // Reset old value.
  54. *mThreadLocalSlot = mPreviousFileHandle;
  55. }
  56. }
  57. FileHandleBase*
  58. FileHandle() const
  59. {
  60. return mFileHandle;
  61. }
  62. };
  63. class MOZ_STACK_CLASS ResultHelper final
  64. : public FileRequestBase::ResultCallback
  65. {
  66. FileRequestBase* mFileRequest;
  67. AutoSetCurrentFileHandle mAutoFileHandle;
  68. union
  69. {
  70. File* mFile;
  71. const nsCString* mString;
  72. const FileRequestMetadata* mMetadata;
  73. const JS::Handle<JS::Value>* mJSValHandle;
  74. } mResult;
  75. enum
  76. {
  77. ResultTypeFile,
  78. ResultTypeString,
  79. ResultTypeMetadata,
  80. ResultTypeJSValHandle,
  81. } mResultType;
  82. public:
  83. ResultHelper(FileRequestBase* aFileRequest,
  84. FileHandleBase* aFileHandle,
  85. File* aResult)
  86. : mFileRequest(aFileRequest)
  87. , mAutoFileHandle(aFileHandle)
  88. , mResultType(ResultTypeFile)
  89. {
  90. MOZ_ASSERT(aFileRequest);
  91. MOZ_ASSERT(aFileHandle);
  92. MOZ_ASSERT(aResult);
  93. mResult.mFile = aResult;
  94. }
  95. ResultHelper(FileRequestBase* aFileRequest,
  96. FileHandleBase* aFileHandle,
  97. const nsCString* aResult)
  98. : mFileRequest(aFileRequest)
  99. , mAutoFileHandle(aFileHandle)
  100. , mResultType(ResultTypeString)
  101. {
  102. MOZ_ASSERT(aFileRequest);
  103. MOZ_ASSERT(aFileHandle);
  104. MOZ_ASSERT(aResult);
  105. mResult.mString = aResult;
  106. }
  107. ResultHelper(FileRequestBase* aFileRequest,
  108. FileHandleBase* aFileHandle,
  109. const FileRequestMetadata* aResult)
  110. : mFileRequest(aFileRequest)
  111. , mAutoFileHandle(aFileHandle)
  112. , mResultType(ResultTypeMetadata)
  113. {
  114. MOZ_ASSERT(aFileRequest);
  115. MOZ_ASSERT(aFileHandle);
  116. MOZ_ASSERT(aResult);
  117. mResult.mMetadata = aResult;
  118. }
  119. ResultHelper(FileRequestBase* aFileRequest,
  120. FileHandleBase* aFileHandle,
  121. const JS::Handle<JS::Value>* aResult)
  122. : mFileRequest(aFileRequest)
  123. , mAutoFileHandle(aFileHandle)
  124. , mResultType(ResultTypeJSValHandle)
  125. {
  126. MOZ_ASSERT(aFileRequest);
  127. MOZ_ASSERT(aFileHandle);
  128. MOZ_ASSERT(aResult);
  129. mResult.mJSValHandle = aResult;
  130. }
  131. FileRequestBase*
  132. FileRequest() const
  133. {
  134. return mFileRequest;
  135. }
  136. FileHandleBase*
  137. FileHandle() const
  138. {
  139. return mAutoFileHandle.FileHandle();
  140. }
  141. virtual nsresult
  142. GetResult(JSContext* aCx, JS::MutableHandle<JS::Value> aResult) override
  143. {
  144. MOZ_ASSERT(aCx);
  145. MOZ_ASSERT(mFileRequest);
  146. switch (mResultType) {
  147. case ResultTypeFile:
  148. return GetResult(aCx, mResult.mFile, aResult);
  149. case ResultTypeString:
  150. return GetResult(aCx, mResult.mString, aResult);
  151. case ResultTypeMetadata:
  152. return GetResult(aCx, mResult.mMetadata, aResult);
  153. case ResultTypeJSValHandle:
  154. aResult.set(*mResult.mJSValHandle);
  155. return NS_OK;
  156. default:
  157. MOZ_CRASH("Unknown result type!");
  158. }
  159. MOZ_CRASH("Should never get here!");
  160. }
  161. private:
  162. nsresult
  163. GetResult(JSContext* aCx,
  164. File* aFile,
  165. JS::MutableHandle<JS::Value> aResult)
  166. {
  167. bool ok = GetOrCreateDOMReflector(aCx, aFile, aResult);
  168. if (NS_WARN_IF(!ok)) {
  169. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  170. }
  171. return NS_OK;
  172. }
  173. nsresult
  174. GetResult(JSContext* aCx,
  175. const nsCString* aString,
  176. JS::MutableHandle<JS::Value> aResult)
  177. {
  178. const nsCString& data = *aString;
  179. nsresult rv;
  180. if (!mFileRequest->HasEncoding()) {
  181. JS::Rooted<JSObject*> arrayBuffer(aCx);
  182. rv = nsContentUtils::CreateArrayBuffer(aCx, data, arrayBuffer.address());
  183. if (NS_WARN_IF(NS_FAILED(rv))) {
  184. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  185. }
  186. aResult.setObject(*arrayBuffer);
  187. return NS_OK;
  188. }
  189. nsAutoCString encoding;
  190. // The BOM sniffing is baked into the "decode" part of the Encoding
  191. // Standard, which the File API references.
  192. if (!nsContentUtils::CheckForBOM(
  193. reinterpret_cast<const unsigned char *>(data.get()),
  194. data.Length(),
  195. encoding)) {
  196. // BOM sniffing failed. Try the API argument.
  197. if (!EncodingUtils::FindEncodingForLabel(mFileRequest->GetEncoding(),
  198. encoding)) {
  199. // API argument failed. Since we are dealing with a file system file,
  200. // we don't have a meaningful type attribute for the blob available,
  201. // so proceeding to the next step, which is defaulting to UTF-8.
  202. encoding.AssignLiteral("UTF-8");
  203. }
  204. }
  205. nsString tmpString;
  206. rv = nsContentUtils::ConvertStringFromEncoding(encoding, data, tmpString);
  207. if (NS_WARN_IF(NS_FAILED(rv))) {
  208. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  209. }
  210. if (NS_WARN_IF(!xpc::StringToJsval(aCx, tmpString, aResult))) {
  211. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  212. }
  213. return NS_OK;
  214. }
  215. nsresult
  216. GetResult(JSContext* aCx,
  217. const FileRequestMetadata* aMetadata,
  218. JS::MutableHandle<JS::Value> aResult)
  219. {
  220. JS::Rooted<JSObject*> obj(aCx, JS_NewPlainObject(aCx));
  221. if (NS_WARN_IF(!obj)) {
  222. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  223. }
  224. const FileRequestSize& size = aMetadata->size();
  225. if (size.type() != FileRequestSize::Tvoid_t) {
  226. MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
  227. JS::Rooted<JS::Value> number(aCx, JS_NumberValue(size.get_uint64_t()));
  228. if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "size", number, 0))) {
  229. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  230. }
  231. }
  232. const FileRequestLastModified& lastModified = aMetadata->lastModified();
  233. if (lastModified.type() != FileRequestLastModified::Tvoid_t) {
  234. MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
  235. JS::Rooted<JSObject*> date(aCx,
  236. JS::NewDateObject(aCx, JS::TimeClip(lastModified.get_int64_t())));
  237. if (NS_WARN_IF(!date)) {
  238. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  239. }
  240. if (NS_WARN_IF(!JS_DefineProperty(aCx, obj, "lastModified", date, 0))) {
  241. return NS_ERROR_DOM_FILEHANDLE_UNKNOWN_ERR;
  242. }
  243. }
  244. aResult.setObject(*obj);
  245. return NS_OK;
  246. }
  247. };
  248. already_AddRefed<File>
  249. ConvertActorToFile(FileHandleBase* aFileHandle,
  250. const FileRequestGetFileResponse& aResponse)
  251. {
  252. auto* actor = static_cast<BlobChild*>(aResponse.fileChild());
  253. MutableFileBase* mutableFile = aFileHandle->MutableFile();
  254. MOZ_ASSERT(mutableFile);
  255. const FileRequestMetadata& metadata = aResponse.metadata();
  256. const FileRequestSize& size = metadata.size();
  257. MOZ_ASSERT(size.type() == FileRequestSize::Tuint64_t);
  258. const FileRequestLastModified& lastModified = metadata.lastModified();
  259. MOZ_ASSERT(lastModified.type() == FileRequestLastModified::Tint64_t);
  260. actor->SetMysteryBlobInfo(mutableFile->Name(),
  261. mutableFile->Type(),
  262. size.get_uint64_t(),
  263. lastModified.get_int64_t());
  264. RefPtr<BlobImpl> blobImpl = actor->GetBlobImpl();
  265. MOZ_ASSERT(blobImpl);
  266. RefPtr<File> file = mutableFile->CreateFileFor(blobImpl, aFileHandle);
  267. return file.forget();
  268. }
  269. void
  270. HandleSuccess(ResultHelper* aResultHelper)
  271. {
  272. MOZ_ASSERT(aResultHelper);
  273. RefPtr<FileRequestBase> fileRequest = aResultHelper->FileRequest();
  274. MOZ_ASSERT(fileRequest);
  275. fileRequest->AssertIsOnOwningThread();
  276. RefPtr<FileHandleBase> fileHandle = aResultHelper->FileHandle();
  277. MOZ_ASSERT(fileHandle);
  278. if (fileHandle->IsAborted()) {
  279. fileRequest->SetError(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
  280. return;
  281. }
  282. MOZ_ASSERT(fileHandle->IsOpen());
  283. fileRequest->SetResultCallback(aResultHelper);
  284. MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
  285. }
  286. void
  287. HandleError(FileRequestBase* aFileRequest,
  288. nsresult aErrorCode,
  289. FileHandleBase* aFileHandle)
  290. {
  291. MOZ_ASSERT(aFileRequest);
  292. aFileRequest->AssertIsOnOwningThread();
  293. MOZ_ASSERT(NS_FAILED(aErrorCode));
  294. MOZ_ASSERT(NS_ERROR_GET_MODULE(aErrorCode) == NS_ERROR_MODULE_DOM_FILEHANDLE);
  295. MOZ_ASSERT(aFileHandle);
  296. RefPtr<FileRequestBase> fileRequest = aFileRequest;
  297. RefPtr<FileHandleBase> fileHandle = aFileHandle;
  298. AutoSetCurrentFileHandle ascfh(aFileHandle);
  299. fileRequest->SetError(aErrorCode);
  300. MOZ_ASSERT(fileHandle->IsOpen() || fileHandle->IsAborted());
  301. }
  302. } // anonymous namespace
  303. /*******************************************************************************
  304. * BackgroundMutableFileChildBase
  305. ******************************************************************************/
  306. BackgroundMutableFileChildBase::BackgroundMutableFileChildBase(
  307. DEBUGONLY(PRThread* aOwningThread))
  308. : ThreadObject(DEBUGONLY(aOwningThread))
  309. , mMutableFile(nullptr)
  310. {
  311. AssertIsOnOwningThread();
  312. MOZ_COUNT_CTOR(BackgroundMutableFileChildBase);
  313. }
  314. BackgroundMutableFileChildBase::~BackgroundMutableFileChildBase()
  315. {
  316. AssertIsOnOwningThread();
  317. MOZ_COUNT_DTOR(BackgroundMutableFileChildBase);
  318. }
  319. void
  320. BackgroundMutableFileChildBase::EnsureDOMObject()
  321. {
  322. AssertIsOnOwningThread();
  323. if (mTemporaryStrongMutableFile) {
  324. return;
  325. }
  326. mTemporaryStrongMutableFile = CreateMutableFile();
  327. MOZ_ASSERT(mTemporaryStrongMutableFile);
  328. mTemporaryStrongMutableFile->AssertIsOnOwningThread();
  329. mMutableFile = mTemporaryStrongMutableFile;
  330. }
  331. void
  332. BackgroundMutableFileChildBase::ReleaseDOMObject()
  333. {
  334. AssertIsOnOwningThread();
  335. MOZ_ASSERT(mTemporaryStrongMutableFile);
  336. mTemporaryStrongMutableFile->AssertIsOnOwningThread();
  337. MOZ_ASSERT(mMutableFile == mTemporaryStrongMutableFile);
  338. mTemporaryStrongMutableFile = nullptr;
  339. }
  340. void
  341. BackgroundMutableFileChildBase::SendDeleteMeInternal()
  342. {
  343. AssertIsOnOwningThread();
  344. MOZ_ASSERT(!mTemporaryStrongMutableFile);
  345. if (mMutableFile) {
  346. mMutableFile->ClearBackgroundActor();
  347. mMutableFile = nullptr;
  348. MOZ_ALWAYS_TRUE(PBackgroundMutableFileChild::SendDeleteMe());
  349. }
  350. }
  351. void
  352. BackgroundMutableFileChildBase::ActorDestroy(ActorDestroyReason aWhy)
  353. {
  354. AssertIsOnOwningThread();
  355. if (mMutableFile) {
  356. mMutableFile->ClearBackgroundActor();
  357. DEBUGONLY(mMutableFile = nullptr;)
  358. }
  359. }
  360. PBackgroundFileHandleChild*
  361. BackgroundMutableFileChildBase::AllocPBackgroundFileHandleChild(
  362. const FileMode& aMode)
  363. {
  364. MOZ_CRASH("PBackgroundFileHandleChild actors should be manually "
  365. "constructed!");
  366. }
  367. bool
  368. BackgroundMutableFileChildBase::DeallocPBackgroundFileHandleChild(
  369. PBackgroundFileHandleChild* aActor)
  370. {
  371. AssertIsOnOwningThread();
  372. MOZ_ASSERT(aActor);
  373. delete static_cast<BackgroundFileHandleChild*>(aActor);
  374. return true;
  375. }
  376. /*******************************************************************************
  377. * BackgroundFileHandleChild
  378. ******************************************************************************/
  379. BackgroundFileHandleChild::BackgroundFileHandleChild(
  380. DEBUGONLY(PRThread* aOwningThread,)
  381. FileHandleBase* aFileHandle)
  382. : ThreadObject(DEBUGONLY(aOwningThread))
  383. , mTemporaryStrongFileHandle(aFileHandle)
  384. , mFileHandle(aFileHandle)
  385. {
  386. AssertIsOnOwningThread();
  387. MOZ_ASSERT(aFileHandle);
  388. aFileHandle->AssertIsOnOwningThread();
  389. MOZ_COUNT_CTOR(BackgroundFileHandleChild);
  390. }
  391. BackgroundFileHandleChild::~BackgroundFileHandleChild()
  392. {
  393. AssertIsOnOwningThread();
  394. MOZ_COUNT_DTOR(BackgroundFileHandleChild);
  395. }
  396. void
  397. BackgroundFileHandleChild::SendDeleteMeInternal()
  398. {
  399. AssertIsOnOwningThread();
  400. if (mFileHandle) {
  401. NoteActorDestroyed();
  402. MOZ_ALWAYS_TRUE(PBackgroundFileHandleChild::SendDeleteMe());
  403. }
  404. }
  405. void
  406. BackgroundFileHandleChild::NoteActorDestroyed()
  407. {
  408. AssertIsOnOwningThread();
  409. MOZ_ASSERT_IF(mTemporaryStrongFileHandle, mFileHandle);
  410. if (mFileHandle) {
  411. mFileHandle->ClearBackgroundActor();
  412. // Normally this would be DEBUG-only but NoteActorDestroyed is also called
  413. // from SendDeleteMeInternal. In that case we're going to receive an actual
  414. // ActorDestroy call later and we don't want to touch a dead object.
  415. mTemporaryStrongFileHandle = nullptr;
  416. mFileHandle = nullptr;
  417. }
  418. }
  419. void
  420. BackgroundFileHandleChild::NoteComplete()
  421. {
  422. AssertIsOnOwningThread();
  423. MOZ_ASSERT_IF(mFileHandle, mTemporaryStrongFileHandle);
  424. mTemporaryStrongFileHandle = nullptr;
  425. }
  426. void
  427. BackgroundFileHandleChild::ActorDestroy(ActorDestroyReason aWhy)
  428. {
  429. AssertIsOnOwningThread();
  430. NoteActorDestroyed();
  431. }
  432. bool
  433. BackgroundFileHandleChild::RecvComplete(const bool& aAborted)
  434. {
  435. AssertIsOnOwningThread();
  436. MOZ_ASSERT(mFileHandle);
  437. mFileHandle->HandleCompleteOrAbort(aAborted);
  438. NoteComplete();
  439. return true;
  440. }
  441. PBackgroundFileRequestChild*
  442. BackgroundFileHandleChild::AllocPBackgroundFileRequestChild(
  443. const FileRequestParams& aParams)
  444. {
  445. MOZ_CRASH("PBackgroundFileRequestChild actors should be manually "
  446. "constructed!");
  447. }
  448. bool
  449. BackgroundFileHandleChild::DeallocPBackgroundFileRequestChild(
  450. PBackgroundFileRequestChild* aActor)
  451. {
  452. MOZ_ASSERT(aActor);
  453. delete static_cast<BackgroundFileRequestChild*>(aActor);
  454. return true;
  455. }
  456. /*******************************************************************************
  457. * BackgroundFileRequestChild
  458. ******************************************************************************/
  459. BackgroundFileRequestChild::BackgroundFileRequestChild(
  460. DEBUGONLY(PRThread* aOwningThread,)
  461. FileRequestBase* aFileRequest)
  462. : ThreadObject(DEBUGONLY(aOwningThread))
  463. , mFileRequest(aFileRequest)
  464. , mFileHandle(aFileRequest->FileHandle())
  465. , mActorDestroyed(false)
  466. {
  467. AssertIsOnOwningThread();
  468. MOZ_ASSERT(aFileRequest);
  469. aFileRequest->AssertIsOnOwningThread();
  470. MOZ_ASSERT(mFileHandle);
  471. mFileHandle->AssertIsOnOwningThread();
  472. MOZ_COUNT_CTOR(BackgroundFileRequestChild);
  473. }
  474. BackgroundFileRequestChild::~BackgroundFileRequestChild()
  475. {
  476. AssertIsOnOwningThread();
  477. MOZ_ASSERT(!mFileHandle);
  478. MOZ_COUNT_DTOR(BackgroundFileRequestChild);
  479. }
  480. void
  481. BackgroundFileRequestChild::HandleResponse(nsresult aResponse)
  482. {
  483. AssertIsOnOwningThread();
  484. MOZ_ASSERT(NS_FAILED(aResponse));
  485. MOZ_ASSERT(NS_ERROR_GET_MODULE(aResponse) == NS_ERROR_MODULE_DOM_FILEHANDLE);
  486. MOZ_ASSERT(mFileHandle);
  487. HandleError(mFileRequest, aResponse, mFileHandle);
  488. }
  489. void
  490. BackgroundFileRequestChild::HandleResponse(
  491. const FileRequestGetFileResponse& aResponse)
  492. {
  493. AssertIsOnOwningThread();
  494. RefPtr<File> file = ConvertActorToFile(mFileHandle, aResponse);
  495. ResultHelper helper(mFileRequest, mFileHandle, file);
  496. HandleSuccess(&helper);
  497. }
  498. void
  499. BackgroundFileRequestChild::HandleResponse(const nsCString& aResponse)
  500. {
  501. AssertIsOnOwningThread();
  502. ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
  503. HandleSuccess(&helper);
  504. }
  505. void
  506. BackgroundFileRequestChild::HandleResponse(const FileRequestMetadata& aResponse)
  507. {
  508. AssertIsOnOwningThread();
  509. ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
  510. HandleSuccess(&helper);
  511. }
  512. void
  513. BackgroundFileRequestChild::HandleResponse(JS::Handle<JS::Value> aResponse)
  514. {
  515. AssertIsOnOwningThread();
  516. ResultHelper helper(mFileRequest, mFileHandle, &aResponse);
  517. HandleSuccess(&helper);
  518. }
  519. void
  520. BackgroundFileRequestChild::ActorDestroy(ActorDestroyReason aWhy)
  521. {
  522. AssertIsOnOwningThread();
  523. MOZ_ASSERT(!mActorDestroyed);
  524. mActorDestroyed = true;
  525. if (mFileHandle) {
  526. mFileHandle->AssertIsOnOwningThread();
  527. mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */
  528. aWhy == Deletion);
  529. DEBUGONLY(mFileHandle = nullptr;)
  530. }
  531. }
  532. bool
  533. BackgroundFileRequestChild::Recv__delete__(const FileRequestResponse& aResponse)
  534. {
  535. AssertIsOnOwningThread();
  536. MOZ_ASSERT(mFileRequest);
  537. MOZ_ASSERT(mFileHandle);
  538. if (mFileHandle->IsAborted()) {
  539. // Always handle an "error" with ABORT_ERR if the file handle was aborted,
  540. // even if the request succeeded or failed with another error.
  541. HandleResponse(NS_ERROR_DOM_FILEHANDLE_ABORT_ERR);
  542. } else {
  543. switch (aResponse.type()) {
  544. case FileRequestResponse::Tnsresult:
  545. HandleResponse(aResponse.get_nsresult());
  546. break;
  547. case FileRequestResponse::TFileRequestGetFileResponse:
  548. HandleResponse(aResponse.get_FileRequestGetFileResponse());
  549. break;
  550. case FileRequestResponse::TFileRequestReadResponse:
  551. HandleResponse(aResponse.get_FileRequestReadResponse().data());
  552. break;
  553. case FileRequestResponse::TFileRequestWriteResponse:
  554. HandleResponse(JS::UndefinedHandleValue);
  555. break;
  556. case FileRequestResponse::TFileRequestTruncateResponse:
  557. HandleResponse(JS::UndefinedHandleValue);
  558. break;
  559. case FileRequestResponse::TFileRequestFlushResponse:
  560. HandleResponse(JS::UndefinedHandleValue);
  561. break;
  562. case FileRequestResponse::TFileRequestGetMetadataResponse:
  563. HandleResponse(aResponse.get_FileRequestGetMetadataResponse()
  564. .metadata());
  565. break;
  566. default:
  567. MOZ_CRASH("Unknown response type!");
  568. }
  569. }
  570. mFileHandle->OnRequestFinished(/* aActorDestroyedNormally */ true);
  571. // Null this out so that we don't try to call OnRequestFinished() again in
  572. // ActorDestroy.
  573. mFileHandle = nullptr;
  574. return true;
  575. }
  576. bool
  577. BackgroundFileRequestChild::RecvProgress(const uint64_t& aProgress,
  578. const uint64_t& aProgressMax)
  579. {
  580. AssertIsOnOwningThread();
  581. MOZ_ASSERT(mFileRequest);
  582. mFileRequest->OnProgress(aProgress, aProgressMax);
  583. return true;
  584. }
  585. } // namespace dom
  586. } // namespace mozilla