| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | |
| 2 // Use of this source code is governed by a BSD-style license that can be | |
| 3 // found in the LICENSE file. | |
| 4 // | |
| 5 // Objects that handle file operations for saving files, on the file thread. | |
| 6 // | |
| 7 // The SaveFileManager owns a set of SaveFile objects, each of which connects | |
| 8 // with a SaveItem object which belongs to one SavePackage and runs on the file | |
| 9 // thread for saving data in order to avoid disk activity on either network IO | |
| 10 // thread or the UI thread. It coordinates the notifications from the network | |
| 11 // and UI. | |
| 12 // | |
| 13 // The SaveFileManager itself is a singleton object owned by the | |
| 14 // ResourceDispatcherHost. | |
| 15 // | |
| 16 // The data sent to SaveFileManager have 2 sources, one is from | |
| 17 // ResourceDispatcherHost, run in network IO thread, the all sub-resources | |
| 18 // and save-only-HTML pages will be got from network IO. The second is from | |
| 19 // render process, those html pages which are serialized from DOM will be | |
| 20 // composed in render process and encoded to its original encoding, then sent | |
| 21 // to UI loop in browser process, then UI loop will dispatch the data to | |
| 22 // SaveFileManager on the file thread. SaveFileManager will directly | |
| 23 // call SaveFile's method to persist data. | |
| 24 // | |
| 25 // A typical saving job operation involves multiple threads: | |
| 26 // | |
| 27 // Updating an in progress save file | |
| 28 // io_thread | |
| 29 // |----> data from net ---->| | |
| 30 // | | |
| 31 // | | |
| 32 // |----> data from ---->| | | |
| 33 // | render process | | | |
| 34 // ui_thread | | | |
| 35 // file_thread (writes to disk) | |
| 36 // |----> stats ---->| | |
| 37 // ui_thread (feedback for user) | |
| 38 // | |
| 39 // | |
| 40 // Cancel operations perform the inverse order when triggered by a user action: | |
| 41 // ui_thread (user click) | |
| 42 // |----> cancel command ---->| | |
| 43 // | | file_thread (close file) | |
| 44 // | |---------------------> cancel command ---->| | |
| 45 // | io_thread (stops net IO | |
| 46 // ui_thread (user close tab) for saving) | |
| 47 // |----> cancel command ---->| | |
| 48 // Render process(stop serializing DOM and sending | |
| 49 // data) | |
| 50 // | |
| 51 // | |
| 52 // The SaveFileManager tracks saving requests, mapping from a save ID | |
| 53 // (unique integer created in the IO thread) to the SavePackage for the | |
| 54 // tab where the saving job was initiated. In the event of a tab closure | |
| 55 // during saving, the SavePackage will notice the SaveFileManage to | |
| 56 // cancel all SaveFile job. | |
| 57 | |
| 58 #ifndef CHROME_BROWSER_SAVE_FILE_MANAGER_H__ | |
| 59 #define CHROME_BROWSER_SAVE_FILE_MANAGER_H__ | |
| 60 | |
| 61 #include <utility> | |
| 62 | |
| 63 #include "base/basictypes.h" | |
| 64 #include "base/hash_tables.h" | |
| 65 #include "base/ref_counted.h" | |
| 66 #include "base/thread.h" | |
| 67 #include "chrome/browser/save_types.h" | |
| 68 | |
| 69 class GURL; | |
| 70 class SaveFile; | |
| 71 class SavePackage; | |
| 72 class MessageLoop; | |
| 73 class ResourceDispatcherHost; | |
| 74 class Task; | |
| 75 class URLRequestContext; | |
| 76 | |
| 77 class SaveFileManager | |
| 78 : public base::RefCountedThreadSafe<SaveFileManager> { | |
| 79 public: | |
| 80 SaveFileManager(MessageLoop* ui_loop, | |
| 81 MessageLoop* io_loop, | |
| 82 ResourceDispatcherHost* rdh); | |
| 83 ~SaveFileManager(); | |
| 84 | |
| 85 // Lifetime management. | |
| 86 void Shutdown(); | |
| 87 | |
| 88 // Called on the IO thread | |
| 89 int GetNextId(); | |
| 90 | |
| 91 // Save the specified URL. Called on the UI thread and forwarded to the | |
| 92 // ResourceDispatcherHost on the IO thread. | |
| 93 void SaveURL(const std::wstring& url, | |
| 94 const std::wstring& referrer, | |
| 95 int render_process_host_id, | |
| 96 int render_view_id, | |
| 97 SaveFileCreateInfo::SaveFileSource save_source, | |
| 98 const std::wstring& file_full_path, | |
| 99 URLRequestContext* request_context, | |
| 100 SavePackage* save_package); | |
| 101 | |
| 102 // Notifications sent from the IO thread and run on the file thread: | |
| 103 void StartSave(SaveFileCreateInfo* info); | |
| 104 void UpdateSaveProgress(int save_id, char* data, int size); | |
| 105 void SaveFinished(int save_id, std::wstring save_url, | |
| 106 int render_process_id, bool is_success); | |
| 107 | |
| 108 // Notifications sent from the UI thread and run on the file thread. | |
| 109 // Cancel a SaveFile instance which has specified save id. | |
| 110 void CancelSave(int save_id); | |
| 111 | |
| 112 // Called on the UI thread to remove a save package from SaveFileManager's | |
| 113 // tracking map. | |
| 114 void RemoveSaveFile(int save_id, const std::wstring& save_url, | |
| 115 SavePackage* package); | |
| 116 | |
| 117 // Handler for shell operations sent from the UI to the file thread. | |
| 118 void OnShowSavedFileInShell(const std::wstring full_path); | |
| 119 | |
| 120 // Helper function for deleting specified file. | |
| 121 void DeleteDirectoryOrFile(const std::wstring& full_path, bool is_dir); | |
| 122 | |
| 123 // For posting notifications from the UI and IO threads. | |
| 124 MessageLoop* GetSaveLoop() const { return file_loop_; } | |
| 125 | |
| 126 // Runs on file thread to save a file by copying from file system when | |
| 127 // original url is using file scheme. | |
| 128 void SaveLocalFile(const std::wstring& original_file_url, | |
| 129 int save_id, | |
| 130 int render_process_id); | |
| 131 | |
| 132 // Renames all the successfully saved files. | |
| 133 // |final_names| points to a vector which contains pairs of save ids and | |
| 134 // final names of successfully saved files. | |
| 135 void RenameAllFiles( | |
| 136 const FinalNameList& final_names, | |
| 137 const std::wstring& resource_dir, | |
| 138 int render_process_id, | |
| 139 int render_view_id); | |
| 140 | |
| 141 // When the user cancels the saving, we need to remove all remaining saved | |
| 142 // files of this page saving job from save_file_map_. | |
| 143 void RemoveSavedFileFromFileMap(const SaveIDList & save_ids); | |
| 144 | |
| 145 private: | |
| 146 // A cleanup helper that runs on the file thread. | |
| 147 void OnShutdown(); | |
| 148 | |
| 149 // The resource does not come from the network, but we still needs to call | |
| 150 // this function for getting unique save ID by calling | |
| 151 // OnRequireSaveJobFromOtherSource in the net IO thread and start saving | |
| 152 // operation. This function is called on the UI thread. | |
| 153 void RequireSaveJobFromOtherSource(SaveFileCreateInfo* info); | |
| 154 | |
| 155 // Called only on UI thread to get the SavePackage for a tab's profile. | |
| 156 static SavePackage* GetSavePackageFromRenderIds(int render_process_id, | |
| 157 int review_view_id); | |
| 158 | |
| 159 // Register a starting request. Associate the save URL with a | |
| 160 // SavePackage for further matching. | |
| 161 void RegisterStartingRequest(const std::wstring& save_url, | |
| 162 SavePackage* save_package); | |
| 163 // Unregister a start request according save URL, disassociate | |
| 164 // the save URL and SavePackage. | |
| 165 SavePackage* UnregisterStartingRequest(const std::wstring& save_url, | |
| 166 int tab_id); | |
| 167 | |
| 168 // Look up the SavePackage according to save id. | |
| 169 SavePackage* LookupPackage(int save_id); | |
| 170 | |
| 171 // Called only on the file thread. | |
| 172 // Look up one in-progress saving item according to save id. | |
| 173 SaveFile* LookupSaveFile(int save_id); | |
| 174 | |
| 175 // Help function for sending notification of canceling specific request. | |
| 176 void SendCancelRequest(int save_id); | |
| 177 | |
| 178 // Notifications sent from the file thread and run on the UI thread. | |
| 179 | |
| 180 // Lookup the SaveManager for this WebContents' saving profile and inform it | |
| 181 // the saving job has been started. | |
| 182 void OnStartSave(const SaveFileCreateInfo* info); | |
| 183 // Update the SavePackage with the current state of a started saving job. | |
| 184 // If the SavePackage for this saving job is gone, cancel the request. | |
| 185 void OnUpdateSaveProgress(int save_id, | |
| 186 int64 bytes_so_far, | |
| 187 bool write_success); | |
| 188 // Update the SavePackage with the finish state, and remove the request | |
| 189 // tracking entries. | |
| 190 void OnSaveFinished(int save_id, int64 bytes_so_far, bool is_success); | |
| 191 // For those requests that do not have valid save id, use | |
| 192 // map:(url, SavePackage) to find the request and remove it. | |
| 193 void OnErrorFinished(std::wstring save_url, int tab_id); | |
| 194 // Handler for a notification sent to the UI thread. | |
| 195 // The user has requested a cancel in the UI thread, so send a cancel request | |
| 196 // to stop the network requests in net IO thread. | |
| 197 void OnCancelSaveRequest(int render_process_id, int request_id); | |
| 198 // Notifies SavePackage that the whole page saving job is finished. | |
| 199 void OnFinishSavePageJob(int render_process_id, int render_view_id); | |
| 200 | |
| 201 // Notifications sent from the UI thread and run on the file thread. | |
| 202 | |
| 203 // Deletes a specified file on the file thread. | |
| 204 void OnDeleteDirectoryOrFile(const std::wstring& full_path, bool is_dir); | |
| 205 | |
| 206 // Notifications sent from the UI thread and run on the IO thread | |
| 207 | |
| 208 // Initiates a request for URL to be saved. | |
| 209 void OnSaveURL(const GURL& url, | |
| 210 const GURL& referrer, | |
| 211 int render_process_host_id, | |
| 212 int render_view_id, | |
| 213 URLRequestContext* request_context); | |
| 214 // Handler for a notification sent to the IO thread for generating save id. | |
| 215 void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info); | |
| 216 // Call ResourceDispatcherHost's CancelRequest method to execute cancel | |
| 217 // action in the IO thread. | |
| 218 void ExecuteCancelSaveRequest(int render_process_id, int request_id); | |
| 219 | |
| 220 // Unique ID for the next SaveFile object. | |
| 221 int next_id_; | |
| 222 | |
| 223 // A map of all saving jobs by using save id. | |
| 224 typedef base::hash_map<int, SaveFile*> SaveFileMap; | |
| 225 SaveFileMap save_file_map_; | |
| 226 | |
| 227 // Message loop that the SavePackages live on. | |
| 228 MessageLoop* ui_loop_; | |
| 229 | |
| 230 // We cache the IO loop, we will use it to request resources from network. | |
| 231 MessageLoop* io_loop_; | |
| 232 | |
| 233 // We cache the file loop, we will use it to do real file operation. | |
| 234 // We guarantee that we won't access them incorrectly during the shutdown | |
| 235 // process | |
| 236 MessageLoop* file_loop_; | |
| 237 | |
| 238 ResourceDispatcherHost* resource_dispatcher_host_; | |
| 239 | |
| 240 // Tracks which SavePackage to send data to, called only on UI thread. | |
| 241 // SavePackageMap maps save IDs to their SavePackage. | |
| 242 typedef base::hash_map<int, SavePackage*> SavePackageMap; | |
| 243 SavePackageMap packages_; | |
| 244 | |
| 245 // There is a gap between after calling SaveURL() and before calling | |
| 246 // StartSave(). In this gap, each request does not have save id for tracking. | |
| 247 // But sometimes users might want to stop saving job or ResourceDispatcherHost | |
| 248 // calls SaveFinished with save id -1 for network error. We name the requests | |
| 249 // as starting requests. For tracking those starting requests, we need to | |
| 250 // have some data structure. | |
| 251 // First we use a hashmap to map the request URL to SavePackage, then we | |
| 252 // use a hashmap to map the tab id (we actually use render_process_id) to the | |
| 253 // hashmap since it is possible to save same URL in different tab at | |
| 254 // same time. | |
| 255 typedef base::hash_map<std::wstring, SavePackage*> StartingRequestsMap; | |
| 256 typedef base::hash_map<int, StartingRequestsMap> TabToStartingRequestsMap; | |
| 257 TabToStartingRequestsMap tab_starting_requests_; | |
| 258 | |
| 259 DISALLOW_EVIL_CONSTRUCTORS(SaveFileManager); | |
| 260 }; | |
| 261 | |
| 262 #endif // CHROME_BROWSER_SAVE_FILE_MANAGER_H__ | |
| OLD | NEW |