michael@0: /* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this file, michael@0: * You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef mozilla_dom_FileSystemTaskBase_h michael@0: #define mozilla_dom_FileSystemTaskBase_h michael@0: michael@0: #include "mozilla/ErrorResult.h" michael@0: #include "mozilla/dom/FileSystemRequestParent.h" michael@0: #include "mozilla/dom/PFileSystemRequestChild.h" michael@0: #include "mozilla/dom/ipc/Blob.h" michael@0: michael@0: class nsIDOMFile; michael@0: michael@0: namespace mozilla { michael@0: namespace dom { michael@0: michael@0: class FileSystemBase; michael@0: class FileSystemParams; michael@0: class Promise; michael@0: michael@0: /* michael@0: * The base class to implement a Task class. michael@0: * The task is used to handle the OOP (out of process) operations. michael@0: * The file system operations can only be performed in the parent process. When michael@0: * performing such a parent-process-only operation, a task will delivered the michael@0: * operation to the parent process if needed. michael@0: * michael@0: * The following diagram illustrates the how a API call from the content page michael@0: * starts a task and gets call back results. michael@0: * michael@0: * The left block is the call sequence inside the child process, while the michael@0: * right block is the call sequence inside the parent process. michael@0: * michael@0: * There are two types of API call. One is from the content page of the child michael@0: * process and we mark the steps as (1) to (8). The other is from the content michael@0: * page of the parent process and we mark the steps as (1') to (4'). michael@0: * michael@0: * Page Page michael@0: * | | michael@0: * | (1) | (1') michael@0: * ______|________________ | _____________________|_____________ michael@0: * | | | | | | | michael@0: * | | Task in | | | Task in | | michael@0: * | | Child Process | | | Parent Process | | michael@0: * | V | IPC | V | michael@0: * [new FileSystemTaskBase()] | | [new FileSystemTaskBase()] | michael@0: * | | | | | | | michael@0: * | | (2) | | | (2') | michael@0: * | V | (3) | | | michael@0: * | [GetRequestParams]------------->[new FileSystemTaskBase(...)] | michael@0: * | | | | | | michael@0: * | | | | | (4) | | michael@0: * | | | | | V | michael@0: * | | | | -----------> [Work] | michael@0: * | | IPC | | | michael@0: * | | | | (5) | (3') | michael@0: * | | | | V | michael@0: * | | | | --------[HandleResult] | michael@0: * | | | | | | | michael@0: * | | | | (6) | | michael@0: * | | (7) | V | | michael@0: * | [SetRequestResult]<-------------[GetRequestResult] | | michael@0: * | | | | | (4') | michael@0: * | | (8) | | | | | michael@0: * | V | | | V | michael@0: * |[HandlerCallback] | IPC | [HandlerCallback] | michael@0: * |_______|_______________| | |_________________________|_________| michael@0: * | | | michael@0: * V V michael@0: * Page Page michael@0: * michael@0: * 1. From child process page michael@0: * Child: michael@0: * (1) Call FileSystem API from content page with JS. Create a task and run. michael@0: * The base constructor [FileSystemTaskBase()] of the task should be called. michael@0: * (2) Forward the task to the parent process through the IPC and call michael@0: * [GetRequestParams] to prepare the parameters of the IPC. michael@0: * Parent: michael@0: * (3) The parent process receives IPC and handle it in michael@0: * FileystemRequestParent. michael@0: * Get the IPC parameters and create a task to run the IPC task. The base michael@0: * constructor [FileSystemTaskBase(aParam, aParent)] of the task should be michael@0: * called to set the task as an IPC task. michael@0: * (4) The task operation will be performed in the member function of [Work]. michael@0: * A worker thread will be created to run that function. If error occurs michael@0: * during the operation, call [SetError] to record the error and then abort. michael@0: * (5) After finishing the task operation, call [HandleResult] to send the michael@0: * result back to the child process though the IPC. michael@0: * (6) Call [GetRequestResult] request result to prepare the parameters of the michael@0: * IPC. Because the formats of the error result for different task are the michael@0: * same, FileSystemTaskBase can handle the error message without interfering. michael@0: * Each task only needs to implement its specific success result preparation michael@0: * function -[GetSuccessRequestResult]. michael@0: * Child: michael@0: * (7) The child process receives IPC and calls [SetRequestResult] to get the michael@0: * task result. Each task needs to implement its specific success result michael@0: * parsing function [SetSuccessRequestResult] to get the success result. michael@0: * (8) Call [HandlerCallback] to send the task result to the content page. michael@0: * 2. From parent process page michael@0: * We don't need to send the task parameters and result to other process. So michael@0: * there are less steps, but their functions are the same. The correspondence michael@0: * between the two types of steps is: michael@0: * (1') = (1), michael@0: * (2') = (4), michael@0: * (3') = (5), michael@0: * (4') = (8). michael@0: */ michael@0: class FileSystemTaskBase michael@0: : public nsRunnable michael@0: , public PFileSystemRequestChild michael@0: { michael@0: public: michael@0: /* michael@0: * Start the task. If the task is running the child process, it will be michael@0: * forwarded to parent process by IPC, or else, creates a worker thread to michael@0: * do the task work. michael@0: */ michael@0: void michael@0: Start(); michael@0: michael@0: /* michael@0: * The error codes are defined in xpcom/base/ErrorList.h and their michael@0: * corresponding error name and message are defined in dom/base/domerr.msg. michael@0: */ michael@0: void michael@0: SetError(const nsresult& aErrorCode); michael@0: michael@0: FileSystemBase* michael@0: GetFileSystem() const; michael@0: michael@0: /* michael@0: * Get the type of permission access required to perform this task. michael@0: */ michael@0: virtual void michael@0: GetPermissionAccessType(nsCString& aAccess) const = 0; michael@0: michael@0: NS_DECL_NSIRUNNABLE michael@0: protected: michael@0: /* michael@0: * To create a task to handle the page content request. michael@0: */ michael@0: FileSystemTaskBase(FileSystemBase* aFileSystem); michael@0: michael@0: /* michael@0: * To create a parent process task delivered from the child process through michael@0: * IPC. michael@0: */ michael@0: FileSystemTaskBase(FileSystemBase* aFileSystem, michael@0: const FileSystemParams& aParam, michael@0: FileSystemRequestParent* aParent); michael@0: michael@0: virtual michael@0: ~FileSystemTaskBase(); michael@0: michael@0: /* michael@0: * The function to perform task operation. It will be run on the worker michael@0: * thread of the parent process. michael@0: * Overrides this function to define the task operation for individual task. michael@0: */ michael@0: virtual nsresult michael@0: Work() = 0; michael@0: michael@0: /* michael@0: * After the task is completed, this function will be called to pass the task michael@0: * result to the content page. michael@0: * Override this function to handle the call back to the content page. michael@0: */ michael@0: virtual void michael@0: HandlerCallback() = 0; michael@0: michael@0: /* michael@0: * Wrap the task parameter to FileSystemParams for sending it through IPC. michael@0: * It will be called when we need to forward a task from the child process to michael@0: * the prarent process. michael@0: * @param filesystem The string representation of the file system. michael@0: */ michael@0: virtual FileSystemParams michael@0: GetRequestParams(const nsString& aFileSystem) const = 0; michael@0: michael@0: /* michael@0: * Wrap the task success result to FileSystemResponseValue for sending it michael@0: * through IPC. michael@0: * It will be called when the task is completed successfully and we need to michael@0: * send the task success result back to the child process. michael@0: */ michael@0: virtual FileSystemResponseValue michael@0: GetSuccessRequestResult() const = 0; michael@0: michael@0: /* michael@0: * Unwrap the IPC message to get the task success result. michael@0: * It will be called when the task is completed successfully and an IPC michael@0: * message is received in the child process and we want to get the task michael@0: * success result. michael@0: */ michael@0: virtual void michael@0: SetSuccessRequestResult(const FileSystemResponseValue& aValue) = 0; michael@0: michael@0: bool michael@0: HasError() const { return mErrorValue != NS_OK; } michael@0: michael@0: // Overrides PFileSystemRequestChild michael@0: virtual bool michael@0: Recv__delete__(const FileSystemResponseValue& value) MOZ_OVERRIDE; michael@0: michael@0: BlobParent* michael@0: GetBlobParent(nsIDOMFile* aFile) const; michael@0: michael@0: nsresult mErrorValue; michael@0: michael@0: nsRefPtr mFileSystem; michael@0: nsRefPtr mRequestParent; michael@0: private: michael@0: /* michael@0: * After finishing the task operation, handle the task result. michael@0: * If it is an IPC task, send back the IPC result. Or else, send the result michael@0: * to the content page. michael@0: */ michael@0: void michael@0: HandleResult(); michael@0: michael@0: /* michael@0: * Wrap the task result to FileSystemResponseValue for sending it through IPC. michael@0: * It will be called when the task is completed and we need to michael@0: * send the task result back to the child process. michael@0: */ michael@0: FileSystemResponseValue michael@0: GetRequestResult() const; michael@0: michael@0: /* michael@0: * Unwrap the IPC message to get the task result. michael@0: * It will be called when the task is completed and an IPC message is received michael@0: * in the child process and we want to get the task result. michael@0: */ michael@0: void michael@0: SetRequestResult(const FileSystemResponseValue& aValue); michael@0: }; michael@0: michael@0: } // namespace dom michael@0: } // namespace mozilla michael@0: michael@0: #endif // mozilla_dom_FileSystemTaskBase_h