| OLD | NEW |
| (Empty) |
| 1 // Copyright (c) 2011 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_DOWNLOAD_SAVE_FILE_MANAGER_H__ | |
| 59 #define CHROME_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H__ | |
| 60 #pragma once | |
| 61 | |
| 62 #include <string> | |
| 63 | |
| 64 #include "base/basictypes.h" | |
| 65 #include "base/hash_tables.h" | |
| 66 #include "base/memory/ref_counted.h" | |
| 67 #include "chrome/browser/download/save_types.h" | |
| 68 | |
| 69 class FilePath; | |
| 70 class GURL; | |
| 71 class SaveFile; | |
| 72 class SavePackage; | |
| 73 class ResourceDispatcherHost; | |
| 74 class Task; | |
| 75 | |
| 76 namespace content { | |
| 77 class ResourceContext; | |
| 78 } | |
| 79 | |
| 80 namespace net { | |
| 81 class IOBuffer; | |
| 82 } | |
| 83 | |
| 84 class SaveFileManager | |
| 85 : public base::RefCountedThreadSafe<SaveFileManager> { | |
| 86 public: | |
| 87 explicit SaveFileManager(ResourceDispatcherHost* rdh); | |
| 88 | |
| 89 // Lifetime management. | |
| 90 void Shutdown(); | |
| 91 | |
| 92 // Called on the IO thread | |
| 93 int GetNextId(); | |
| 94 | |
| 95 // Save the specified URL. Called on the UI thread and forwarded to the | |
| 96 // ResourceDispatcherHost on the IO thread. | |
| 97 void SaveURL(const GURL& url, | |
| 98 const GURL& referrer, | |
| 99 int render_process_host_id, | |
| 100 int render_view_id, | |
| 101 SaveFileCreateInfo::SaveFileSource save_source, | |
| 102 const FilePath& file_full_path, | |
| 103 const content::ResourceContext& context, | |
| 104 SavePackage* save_package); | |
| 105 | |
| 106 // Notifications sent from the IO thread and run on the file thread: | |
| 107 void StartSave(SaveFileCreateInfo* info); | |
| 108 void UpdateSaveProgress(int save_id, net::IOBuffer* data, int size); | |
| 109 void SaveFinished(int save_id, | |
| 110 const GURL& save_url, | |
| 111 int render_process_id, | |
| 112 bool is_success); | |
| 113 | |
| 114 // Notifications sent from the UI thread and run on the file thread. | |
| 115 // Cancel a SaveFile instance which has specified save id. | |
| 116 void CancelSave(int save_id); | |
| 117 | |
| 118 // Called on the UI thread to remove a save package from SaveFileManager's | |
| 119 // tracking map. | |
| 120 void RemoveSaveFile(int save_id, const GURL& save_url, | |
| 121 SavePackage* package); | |
| 122 | |
| 123 #if !defined(OS_MACOSX) | |
| 124 // Handler for shell operations sent from the UI to the file thread. Mac OS X | |
| 125 // requires opening downloads on the UI thread, so it does not use this | |
| 126 // method. | |
| 127 void OnShowSavedFileInShell(const FilePath full_path); | |
| 128 #endif | |
| 129 | |
| 130 // Helper function for deleting specified file. | |
| 131 void DeleteDirectoryOrFile(const FilePath& full_path, bool is_dir); | |
| 132 | |
| 133 // Runs on file thread to save a file by copying from file system when | |
| 134 // original url is using file scheme. | |
| 135 void SaveLocalFile(const GURL& original_file_url, | |
| 136 int save_id, | |
| 137 int render_process_id); | |
| 138 | |
| 139 // Renames all the successfully saved files. | |
| 140 // |final_names| points to a vector which contains pairs of save ids and | |
| 141 // final names of successfully saved files. | |
| 142 void RenameAllFiles( | |
| 143 const FinalNameList& final_names, | |
| 144 const FilePath& resource_dir, | |
| 145 int render_process_id, | |
| 146 int render_view_id, | |
| 147 int save_package_id); | |
| 148 | |
| 149 // When the user cancels the saving, we need to remove all remaining saved | |
| 150 // files of this page saving job from save_file_map_. | |
| 151 void RemoveSavedFileFromFileMap(const SaveIDList & save_ids); | |
| 152 | |
| 153 private: | |
| 154 friend class base::RefCountedThreadSafe<SaveFileManager>; | |
| 155 | |
| 156 ~SaveFileManager(); | |
| 157 | |
| 158 // A cleanup helper that runs on the file thread. | |
| 159 void OnShutdown(); | |
| 160 | |
| 161 // Called only on UI thread to get the SavePackage for a tab's profile. | |
| 162 static SavePackage* GetSavePackageFromRenderIds(int render_process_id, | |
| 163 int review_view_id); | |
| 164 | |
| 165 // Register a starting request. Associate the save URL with a | |
| 166 // SavePackage for further matching. | |
| 167 void RegisterStartingRequest(const GURL& save_url, | |
| 168 SavePackage* save_package); | |
| 169 // Unregister a start request according save URL, disassociate | |
| 170 // the save URL and SavePackage. | |
| 171 SavePackage* UnregisterStartingRequest(const GURL& save_url, | |
| 172 int tab_id); | |
| 173 | |
| 174 // Look up the SavePackage according to save id. | |
| 175 SavePackage* LookupPackage(int save_id); | |
| 176 | |
| 177 // Called only on the file thread. | |
| 178 // Look up one in-progress saving item according to save id. | |
| 179 SaveFile* LookupSaveFile(int save_id); | |
| 180 | |
| 181 // Help function for sending notification of canceling specific request. | |
| 182 void SendCancelRequest(int save_id); | |
| 183 | |
| 184 // Notifications sent from the file thread and run on the UI thread. | |
| 185 | |
| 186 // Lookup the SaveManager for this TabContents' saving profile and inform it | |
| 187 // the saving job has been started. | |
| 188 void OnStartSave(const SaveFileCreateInfo* info); | |
| 189 // Update the SavePackage with the current state of a started saving job. | |
| 190 // If the SavePackage for this saving job is gone, cancel the request. | |
| 191 void OnUpdateSaveProgress(int save_id, | |
| 192 int64 bytes_so_far, | |
| 193 bool write_success); | |
| 194 // Update the SavePackage with the finish state, and remove the request | |
| 195 // tracking entries. | |
| 196 void OnSaveFinished(int save_id, int64 bytes_so_far, bool is_success); | |
| 197 // For those requests that do not have valid save id, use | |
| 198 // map:(url, SavePackage) to find the request and remove it. | |
| 199 void OnErrorFinished(const GURL& save_url, int tab_id); | |
| 200 // Notifies SavePackage that the whole page saving job is finished. | |
| 201 void OnFinishSavePageJob(int render_process_id, | |
| 202 int render_view_id, | |
| 203 int save_package_id); | |
| 204 | |
| 205 // Notifications sent from the UI thread and run on the file thread. | |
| 206 | |
| 207 // Deletes a specified file on the file thread. | |
| 208 void OnDeleteDirectoryOrFile(const FilePath& full_path, bool is_dir); | |
| 209 | |
| 210 // Notifications sent from the UI thread and run on the IO thread | |
| 211 | |
| 212 // Initiates a request for URL to be saved. | |
| 213 void OnSaveURL(const GURL& url, | |
| 214 const GURL& referrer, | |
| 215 int render_process_host_id, | |
| 216 int render_view_id, | |
| 217 const content::ResourceContext* context); | |
| 218 // Handler for a notification sent to the IO thread for generating save id. | |
| 219 void OnRequireSaveJobFromOtherSource(SaveFileCreateInfo* info); | |
| 220 // Call ResourceDispatcherHost's CancelRequest method to execute cancel | |
| 221 // action in the IO thread. | |
| 222 void ExecuteCancelSaveRequest(int render_process_id, int request_id); | |
| 223 | |
| 224 // Unique ID for the next SaveFile object. | |
| 225 int next_id_; | |
| 226 | |
| 227 // A map of all saving jobs by using save id. | |
| 228 typedef base::hash_map<int, SaveFile*> SaveFileMap; | |
| 229 SaveFileMap save_file_map_; | |
| 230 | |
| 231 ResourceDispatcherHost* resource_dispatcher_host_; | |
| 232 | |
| 233 // Tracks which SavePackage to send data to, called only on UI thread. | |
| 234 // SavePackageMap maps save IDs to their SavePackage. | |
| 235 typedef base::hash_map<int, SavePackage*> SavePackageMap; | |
| 236 SavePackageMap packages_; | |
| 237 | |
| 238 // There is a gap between after calling SaveURL() and before calling | |
| 239 // StartSave(). In this gap, each request does not have save id for tracking. | |
| 240 // But sometimes users might want to stop saving job or ResourceDispatcherHost | |
| 241 // calls SaveFinished with save id -1 for network error. We name the requests | |
| 242 // as starting requests. For tracking those starting requests, we need to | |
| 243 // have some data structure. | |
| 244 // First we use a hashmap to map the request URL to SavePackage, then we | |
| 245 // use a hashmap to map the tab id (we actually use render_process_id) to the | |
| 246 // hashmap since it is possible to save same URL in different tab at | |
| 247 // same time. | |
| 248 typedef base::hash_map<std::string, SavePackage*> StartingRequestsMap; | |
| 249 typedef base::hash_map<int, StartingRequestsMap> TabToStartingRequestsMap; | |
| 250 TabToStartingRequestsMap tab_starting_requests_; | |
| 251 | |
| 252 DISALLOW_COPY_AND_ASSIGN(SaveFileManager); | |
| 253 }; | |
| 254 | |
| 255 #endif // CHROME_BROWSER_DOWNLOAD_SAVE_FILE_MANAGER_H__ | |
| OLD | NEW |