diff options
Diffstat (limited to '')
-rw-r--r-- | dom/filesystem/FileSystemTaskBase.h | 254 |
1 files changed, 254 insertions, 0 deletions
diff --git a/dom/filesystem/FileSystemTaskBase.h b/dom/filesystem/FileSystemTaskBase.h new file mode 100644 index 0000000000..3d440403cc --- /dev/null +++ b/dom/filesystem/FileSystemTaskBase.h @@ -0,0 +1,254 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#ifndef mozilla_dom_FileSystemTaskBase_h +#define mozilla_dom_FileSystemTaskBase_h + +#include "mozilla/dom/FileSystemRequestParent.h" +#include "mozilla/dom/PFileSystemRequestChild.h" +#include "nsIGlobalObject.h" +#include "nsThreadUtils.h" + +namespace mozilla { +class ErrorResult; + +namespace dom { + +class BlobImpl; +class FileSystemBase; +class FileSystemParams; + +/* + * The base class to implement a Task class. + * The file system operations can only be performed in the parent process. In + * order to avoid duplicated code, we used PBackground for child-parent and + * parent-parent communications. + * + * The following diagram illustrates the how a API call from the content page + * starts a task and gets call back results. + * + * The left block is the call sequence inside any process loading content, while + * the right block is the call sequence only inside the parent process. + * + * Page + * | + * | (1) + * ______|_________________________ | _________________________________ + * | | | | | | + * | | | | | | + * | V | IPC | PBackground thread on | + * | [new FileSystemTaskChildBase()] | | | the parent process | + * | | | | | | + * | | (2) | | | + * | V | (3) | | + * | [GetRequestParams]------------------->[new FileSystemTaskParentBase()] | + * | | | | | + * | | | | | (4) _____________ | + * | | | | | | | | + * | | | | | | I/O Thread | | + * | | | | | | | | + * | | | | ---------> [IOWork] | | + * | | IPC | | | | | + * | | | | | | (5) | | + * | | | | -------------- | | + * | | | | | |_____________| | + * | | | | | | + * | | | | V | + * | | | | [HandleResult] | + * | | | | | | + * | | | | (6) | + * | | (7) | V | + * | [SetRequestResult]<---------------------[GetRequestResult] | + * | | | | | + * | | (8) | | | | + * | V | | | | + * |[HandlerCallback] | IPC | | + * |_______|_________________________| | |_________________________________| + * | | + * V + * Page + * + * 1. From the process that is handling the request + * Child/Parent (it can be in any process): + * (1) Call FileSystem API from content page with JS. Create a task and run. + * The base constructor [FileSystemTaskChildBase()] of the task should be + * called. + * (2) Forward the task to the parent process through the IPC and call + * [GetRequestParams] to prepare the parameters of the IPC. + * Parent: + * (3) The parent process receives IPC and handle it in + * FileystemRequestParent. Get the IPC parameters and create a task to run the + * IPC task. + * (4) The task operation will be performed in the member function of + * [IOWork]. A I/O thread will be created to run that function. If error occurs + * during the operation, call [SetError] to record the error and then abort. + * (5) After finishing the task operation, call [HandleResult] to send the + * result back to the child process though the IPC. + * (6) Call [GetRequestResult] request result to prepare the parameters of the + * IPC. Because the formats of the error result for different task are the + * same, FileSystemTaskChildBase can handle the error message without + * interfering. + * Each task only needs to implement its specific success result preparation + * function -[GetSuccessRequestResult]. + * Child/Parent: + * (7) The process receives IPC and calls [SetRequestResult] to get the + * task result. Each task needs to implement its specific success result + * parsing function [SetSuccessRequestResult] to get the success result. + * (8) Call [HandlerCallback] to send the task result to the content page. + */ +class FileSystemTaskChildBase : public PFileSystemRequestChild { + friend class PFileSystemRequestChild; + + public: + NS_INLINE_DECL_REFCOUNTING(FileSystemTaskChildBase, final) + + /* + * Start the task. It will dispatch all the information to the parent process, + * PBackground thread. This method must be called from the owning thread. + */ + void Start(); + + /* + * The error codes are defined in xpcom/base/ErrorList.h and their + * corresponding error name and message are defined in dom/base/domerr.msg. + */ + void SetError(const nsresult& aErrorCode); + + FileSystemBase* GetFileSystem() const; + + /* + * After the task is completed, this function will be called to pass the task + * result to the content page. This method is called in the owning thread. + * Override this function to handle the call back to the content page. + */ + virtual void HandlerCallback() = 0; + + bool HasError() const { return NS_FAILED(mErrorValue); } + + protected: + /* + * To create a task to handle the page content request. + */ + FileSystemTaskChildBase(nsIGlobalObject* aGlobalObject, + FileSystemBase* aFileSystem); + + virtual ~FileSystemTaskChildBase(); + + /* + * Wrap the task parameter to FileSystemParams for sending it through IPC. + * It will be called when we need to forward a task from the child process to + * the parent process. This method runs in the owning thread. + * @param filesystem The string representation of the file system. + */ + virtual FileSystemParams GetRequestParams(const nsString& aSerializedDOMPath, + ErrorResult& aRv) const = 0; + + /* + * Unwrap the IPC message to get the task success result. + * It will be called when the task is completed successfully and an IPC + * message is received in the child process and we want to get the task + * success result. This method runs in the owning thread. + */ + virtual void SetSuccessRequestResult(const FileSystemResponseValue& aValue, + ErrorResult& aRv) = 0; + + // Overrides PFileSystemRequestChild + virtual mozilla::ipc::IPCResult Recv__delete__( + const FileSystemResponseValue& value) final; + + nsresult mErrorValue; + RefPtr<FileSystemBase> mFileSystem; + nsCOMPtr<nsIGlobalObject> mGlobalObject; + + private: + /* + * Unwrap the IPC message to get the task result. + * It will be called when the task is completed and an IPC message is received + * in the content process and we want to get the task result. This runs on the + * owning thread. + */ + void SetRequestResult(const FileSystemResponseValue& aValue); +}; + +// This class is the 'alter ego' of FileSystemTaskChildBase in the PBackground +// world. +class FileSystemTaskParentBase : public Runnable { + public: + FileSystemTaskParentBase() + : Runnable("FileSystemTaskParentBase"), + mErrorValue(NS_ERROR_NOT_INITIALIZED) {} + + /* + * Start the task. This must be called from the PBackground thread only. + */ + void Start(); + + /* + * The error codes are defined in xpcom/base/ErrorList.h and their + * corresponding error name and message are defined in dom/base/domerr.msg. + */ + void SetError(const nsresult& aErrorCode); + + /* + * The function to perform task operation. It will be run on the I/O + * thread of the parent process. + * Overrides this function to define the task operation for individual task. + */ + virtual nsresult IOWork() = 0; + + /* + * Wrap the task success result to FileSystemResponseValue for sending it + * through IPC. This method runs in the PBackground thread. + * It will be called when the task is completed successfully and we need to + * send the task success result back to the child process. + */ + virtual FileSystemResponseValue GetSuccessRequestResult( + ErrorResult& aRv) const = 0; + + /* + * After finishing the task operation, handle the task result. + * If it is an IPC task, send back the IPC result. It runs on the PBackground + * thread. + */ + void HandleResult(); + + bool HasError() const { return NS_FAILED(mErrorValue); } + + NS_IMETHOD + Run() override; + + virtual nsresult GetTargetPath(nsAString& aPath) const = 0; + + private: + /* + * Wrap the task result to FileSystemResponseValue for sending it through IPC. + * It will be called when the task is completed and we need to + * send the task result back to the content. This runs on the PBackground + * thread. + */ + FileSystemResponseValue GetRequestResult() const; + + protected: + /* + * To create a parent process task delivered from the child process through + * IPC. + */ + FileSystemTaskParentBase(FileSystemBase* aFileSystem, + const FileSystemParams& aParam, + FileSystemRequestParent* aParent); + + virtual ~FileSystemTaskParentBase(); + + nsresult mErrorValue; + RefPtr<FileSystemBase> mFileSystem; + RefPtr<FileSystemRequestParent> mRequestParent; + nsCOMPtr<nsIEventTarget> mBackgroundEventTarget; +}; + +} // namespace dom +} // namespace mozilla + +#endif // mozilla_dom_FileSystemTaskBase_h |