FileSystemTaskBase.h (11701B)
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 #ifndef mozilla_dom_FileSystemTaskBase_h 8 #define mozilla_dom_FileSystemTaskBase_h 9 10 #include "mozilla/dom/FileSystemRequestParent.h" 11 #include "mozilla/dom/PFileSystemRequestChild.h" 12 #include "nsIGlobalObject.h" 13 #include "nsThreadUtils.h" 14 15 namespace mozilla { 16 class ErrorResult; 17 18 namespace dom { 19 20 class BlobImpl; 21 class FileSystemBase; 22 class FileSystemParams; 23 24 /* 25 * The base class to implement a Task class. 26 * The file system operations can only be performed in the parent process. In 27 * order to avoid duplicated code, we used PBackground for child-parent and 28 * parent-parent communications. 29 * 30 * The following diagram illustrates the how a API call from the content page 31 * starts a task and gets call back results. 32 * 33 * The left block is the call sequence inside any process loading content, while 34 * the right block is the call sequence only inside the parent process. 35 * 36 * Page 37 * | 38 * | (1) 39 * ______|_________________________ | _________________________________ 40 * | | | | | | 41 * | | | | | | 42 * | V | IPC | PBackground thread on | 43 * | [new FileSystemTaskChildBase()] | | | the parent process | 44 * | | | | | | 45 * | | (2) | | | 46 * | V | (3) | | 47 * | [GetRequestParams]------------------->[new FileSystemTaskParentBase()] | 48 * | | | | | 49 * | | | | | (4) _____________ | 50 * | | | | | | | | 51 * | | | | | | I/O Thread | | 52 * | | | | | | | | 53 * | | | | ---------> [IOWork] | | 54 * | | IPC | | | | | 55 * | | | | | | (5) | | 56 * | | | | -------------* | | 57 * | | | | | |_____|_______| | 58 * | | | | | __________|_______ | 59 * | | | | | | | | | 60 * | | | | | | Main | | | 61 * | | | | | | Thread | | | 62 * | | | | | | V | | 63 * | | | | | | [MainThreadWork] | | 64 * | | IPC | | | (5.1) | | | 65 * | | | | | | | | | 66 * | | | | |<------------ | | 67 * | | | | | |__________________| | 68 * | | | | V | 69 * | | | | [HandleResult] | 70 * | | | | | | 71 * | | | | (6) | 72 * | | (7) | V | 73 * | [SetRequestResult]<---------------------[GetRequestResult] | 74 * | | | | | 75 * | | (8) | | | | 76 * | V | | | | 77 * |[HandlerCallback] | IPC | | 78 * |_______|_________________________| | |_________________________________| 79 * | | 80 * V 81 * Page 82 * 83 * 1. From the process that is handling the request 84 * Child/Parent (it can be in any process): 85 * (1) Call FileSystem API from content page with JS. Create a task and run. 86 * The base constructor [FileSystemTaskChildBase()] of the task should be 87 * called. 88 * (2) Forward the task to the parent process through the IPC and call 89 * [GetRequestParams] to prepare the parameters of the IPC. 90 * Parent: 91 * (3) The parent process receives IPC and handle it in 92 * FileystemRequestParent. Get the IPC parameters and create a task to run the 93 * IPC task. 94 * (4) The task operation will be performed in the member function of 95 * [IOWork]. A I/O thread will be created to run that function. If error occurs 96 * during the operation, call [SetError] to record the error and then abort. 97 * (5) After finishing the task operation, call [HandleResult] to send the 98 * result back to the child process though the IPC. 99 * (5.1) Optional, we need to run some code in the main-thread. 100 * (6) Call [GetRequestResult] request result to prepare the parameters of the 101 * IPC. Because the formats of the error result for different task are the 102 * same, FileSystemTaskChildBase can handle the error message without 103 * interfering. 104 * Each task only needs to implement its specific success result preparation 105 * function -[GetSuccessRequestResult]. 106 * Child/Parent: 107 * (7) The process receives IPC and calls [SetRequestResult] to get the 108 * task result. Each task needs to implement its specific success result 109 * parsing function [SetSuccessRequestResult] to get the success result. 110 * (8) Call [HandlerCallback] to send the task result to the content page. 111 */ 112 class FileSystemTaskChildBase : public PFileSystemRequestChild { 113 friend class PFileSystemRequestChild; 114 115 public: 116 NS_INLINE_DECL_REFCOUNTING(FileSystemTaskChildBase, final) 117 118 /* 119 * Start the task. It will dispatch all the information to the parent process, 120 * PBackground thread. This method must be called from the owning thread. 121 */ 122 void Start(); 123 124 /* 125 * The error codes are defined in xpcom/base/ErrorList.h and their 126 * corresponding error name and message are defined in dom/base/domerr.msg. 127 */ 128 void SetError(const nsresult& aErrorCode); 129 130 FileSystemBase* GetFileSystem() const; 131 132 /* 133 * After the task is completed, this function will be called to pass the task 134 * result to the content page. This method is called in the owning thread. 135 * Override this function to handle the call back to the content page. 136 */ 137 virtual void HandlerCallback() = 0; 138 139 bool HasError() const { return NS_FAILED(mErrorValue); } 140 141 protected: 142 /* 143 * To create a task to handle the page content request. 144 */ 145 FileSystemTaskChildBase(nsIGlobalObject* aGlobalObject, 146 FileSystemBase* aFileSystem); 147 148 virtual ~FileSystemTaskChildBase(); 149 150 /* 151 * Wrap the task parameter to FileSystemParams for sending it through IPC. 152 * It will be called when we need to forward a task from the child process to 153 * the parent process. This method runs in the owning thread. 154 * @param filesystem The string representation of the file system. 155 */ 156 virtual FileSystemParams GetRequestParams(const nsString& aSerializedDOMPath, 157 ErrorResult& aRv) const = 0; 158 159 /* 160 * Unwrap the IPC message to get the task success result. 161 * It will be called when the task is completed successfully and an IPC 162 * message is received in the child process and we want to get the task 163 * success result. This method runs in the owning thread. 164 */ 165 virtual void SetSuccessRequestResult(const FileSystemResponseValue& aValue, 166 ErrorResult& aRv) = 0; 167 168 // Overrides PFileSystemRequestChild 169 virtual mozilla::ipc::IPCResult Recv__delete__( 170 const FileSystemResponseValue& value) final; 171 172 nsresult mErrorValue; 173 RefPtr<FileSystemBase> mFileSystem; 174 nsCOMPtr<nsIGlobalObject> mGlobalObject; 175 176 private: 177 /* 178 * Unwrap the IPC message to get the task result. 179 * It will be called when the task is completed and an IPC message is received 180 * in the content process and we want to get the task result. This runs on the 181 * owning thread. 182 */ 183 void SetRequestResult(const FileSystemResponseValue& aValue); 184 }; 185 186 // This class is the 'alter ego' of FileSystemTaskChildBase in the PBackground 187 // world. 188 class FileSystemTaskParentBase : public Runnable { 189 public: 190 FileSystemTaskParentBase() 191 : Runnable("FileSystemTaskParentBase"), 192 mErrorValue(NS_ERROR_NOT_INITIALIZED) {} 193 194 /* 195 * Start the task. This must be called from the PBackground thread only. 196 */ 197 void Start(); 198 199 /* 200 * The error codes are defined in xpcom/base/ErrorList.h and their 201 * corresponding error name and message are defined in dom/base/domerr.msg. 202 */ 203 void SetError(const nsresult& aErrorCode); 204 205 /* 206 * The function to perform task operation. It will be run on the I/O 207 * thread of the parent process. 208 * Overrides this function to define the task operation for individual task. 209 */ 210 virtual nsresult IOWork() = 0; 211 212 // In case `MainThreadNeeded()` returns true, the following method is called. 213 virtual nsresult MainThreadWork() { 214 MOZ_CRASH("This method should be implemented"); 215 return NS_OK; 216 } 217 218 // If this returns true, after I/O work, we schedule a runnable to the 219 // main-thread before resolving the task on the PBackground one. 220 virtual bool MainThreadNeeded() const { return false; }; 221 222 /* 223 * Wrap the task success result to FileSystemResponseValue for sending it 224 * through IPC. This method runs in the PBackground thread. 225 * It will be called when the task is completed successfully and we need to 226 * send the task success result back to the child process. 227 */ 228 virtual FileSystemResponseValue GetSuccessRequestResult( 229 ErrorResult& aRv) const = 0; 230 231 /* 232 * After finishing the task operation, handle the task result. 233 * If it is an IPC task, send back the IPC result. It runs on the PBackground 234 * thread. 235 */ 236 void HandleResult(); 237 238 bool HasError() const { return NS_FAILED(mErrorValue); } 239 240 NS_IMETHOD 241 Run() override; 242 243 virtual nsresult GetTargetPath(nsAString& aPath) const = 0; 244 245 private: 246 /* 247 * Wrap the task result to FileSystemResponseValue for sending it through IPC. 248 * It will be called when the task is completed and we need to 249 * send the task result back to the content. This runs on the PBackground 250 * thread. 251 */ 252 FileSystemResponseValue GetRequestResult() const; 253 254 protected: 255 /* 256 * To create a parent process task delivered from the child process through 257 * IPC. 258 */ 259 FileSystemTaskParentBase(FileSystemBase* aFileSystem, 260 const FileSystemParams& aParam, 261 FileSystemRequestParent* aParent); 262 263 virtual ~FileSystemTaskParentBase(); 264 265 nsresult mErrorValue; 266 RefPtr<FileSystemBase> mFileSystem; 267 RefPtr<FileSystemRequestParent> mRequestParent; 268 nsCOMPtr<nsIEventTarget> mBackgroundEventTarget; 269 }; 270 271 } // namespace dom 272 } // namespace mozilla 273 274 #endif // mozilla_dom_FileSystemTaskBase_h