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 downloads, on the download thread. | |
6 // | |
7 // The DownloadFileManager owns a set of DownloadFile objects, each of which | |
8 // represent one in progress download and performs the disk IO for that | |
9 // download. The DownloadFileManager itself is a singleton object owned by the | |
10 // ResourceDispatcherHost. | |
11 // | |
12 // The DownloadFileManager uses the file_thread for performing file write | |
13 // operations, in order to avoid disk activity on either the IO (network) thread | |
14 // and the UI thread. It coordinates the notifications from the network and UI. | |
15 // | |
16 // A typical download operation involves multiple threads: | |
17 // | |
18 // Updating an in progress download | |
19 // io_thread | |
20 // |----> data ---->| | |
21 // file_thread (writes to disk) | |
22 // |----> stats ---->| | |
23 // ui_thread (feedback for user and | |
24 // updates to history) | |
25 // | |
26 // Cancel operations perform the inverse order when triggered by a user action: | |
27 // ui_thread (user click) | |
28 // |----> cancel command ---->| | |
29 // file_thread (close file) | |
30 // |----> cancel command ---->| | |
31 // io_thread (stops net IO | |
32 // for download) | |
33 // | |
34 // The DownloadFileManager tracks download requests, mapping from a download | |
35 // ID (unique integer created in the IO thread) to the DownloadManager for the | |
36 // tab (profile) where the download was initiated. In the event of a tab closure | |
37 // during a download, the DownloadFileManager will continue to route data to the | |
38 // appropriate DownloadManager. In progress downloads are cancelled for a | |
39 // DownloadManager that exits (such as when closing a profile). | |
40 | |
41 #ifndef CHROME_BROWSER_DOWNLOAD_FILE_H__ | |
42 #define CHROME_BROWSER_DOWNLOAD_FILE_H__ | |
43 | |
44 #include <string> | |
45 #include <vector> | |
46 | |
47 #include "base/basictypes.h" | |
48 #include "base/hash_tables.h" | |
49 #include "base/lock.h" | |
50 #include "base/ref_counted.h" | |
51 #include "base/thread.h" | |
52 #include "base/timer.h" | |
53 #include "chrome/browser/history/download_types.h" | |
54 | |
55 class DownloadManager; | |
56 class GURL; | |
57 class MessageLoop; | |
58 class ResourceDispatcherHost; | |
59 class URLRequestContext; | |
60 | |
61 // DownloadBuffer -------------------------------------------------------------- | |
62 | |
63 // This container is created and populated on the io_thread, and passed to the | |
64 // file_thread for writing. In order to avoid flooding the file_thread with too | |
65 // many small write messages, each write is appended to the DownloadBuffer while | |
66 // waiting for the task to run on the file_thread. Access to the write buffers | |
67 // is synchronized via the lock. Each entry in 'contents' represents one data | |
68 // buffer and its size in bytes. | |
69 | |
70 struct DownloadBuffer { | |
71 Lock lock; | |
72 typedef std::pair<char *, int> Contents; | |
73 std::vector<Contents> contents; | |
74 }; | |
75 | |
76 // DownloadFile ---------------------------------------------------------------- | |
77 | |
78 // These objects live exclusively on the download thread and handle the writing | |
79 // operations for one download. These objects live only for the duration that | |
80 // the download is 'in progress': once the download has been completed or | |
81 // cancelled, the DownloadFile is destroyed. | |
82 class DownloadFile { | |
83 public: | |
84 DownloadFile(const DownloadCreateInfo* info); | |
85 ~DownloadFile(); | |
86 | |
87 bool Initialize(); | |
88 | |
89 // Write a new chunk of data to the file. Returns true on success. | |
90 bool AppendDataToFile(const char* data, int data_len); | |
91 | |
92 // Abort the download and automatically close the file. | |
93 void Cancel(); | |
94 | |
95 // Rename the download file. Returns 'true' if the rename was successful. | |
96 bool Rename(const std::wstring& full_path); | |
97 | |
98 // Accessors. | |
99 int64 bytes_so_far() const { return bytes_so_far_; } | |
100 int id() const { return id_; } | |
101 std::wstring full_path() const { return full_path_; } | |
102 int render_process_id() const { return render_process_id_; } | |
103 int render_view_id() const { return render_view_id_; } | |
104 int request_id() const { return request_id_; } | |
105 bool path_renamed() const { return path_renamed_; } | |
106 bool in_progress() const { return file_ != NULL; } | |
107 void set_in_progress(bool in_progress) { in_progress_ = in_progress; } | |
108 | |
109 private: | |
110 // Open or Close the OS file handle. The file is opened in the constructor | |
111 // based on creation information passed to it, and automatically closed in | |
112 // the destructor. | |
113 void Close(); | |
114 bool Open(const wchar_t* open_mode); | |
115 | |
116 // OS file handle for writing | |
117 FILE* file_; | |
118 | |
119 // The unique identifier for this download, assigned at creation by | |
120 // the DownloadFileManager for its internal record keeping. | |
121 int id_; | |
122 | |
123 // IDs for looking up the tab we are associated with. | |
124 int render_process_id_; | |
125 int render_view_id_; | |
126 | |
127 // Handle for informing the ResourceDispatcherHost of a UI based cancel. | |
128 int request_id_; | |
129 | |
130 // Amount of data received up to this point. We may not know in advance how | |
131 // much data to expect since some servers don't provide that information. | |
132 int64 bytes_so_far_; | |
133 | |
134 // Full path to the downloaded file. | |
135 std::wstring full_path_; | |
136 | |
137 // Whether the download is still using its initial temporary path. | |
138 bool path_renamed_; | |
139 | |
140 // Whether the download is still receiving data. | |
141 bool in_progress_; | |
142 | |
143 DISALLOW_EVIL_CONSTRUCTORS(DownloadFile); | |
144 }; | |
145 | |
146 | |
147 // DownloadFileManager --------------------------------------------------------- | |
148 | |
149 // Manages all in progress downloads. | |
150 class DownloadFileManager | |
151 : public base::RefCountedThreadSafe<DownloadFileManager> { | |
152 public: | |
153 DownloadFileManager(MessageLoop* ui_loop, ResourceDispatcherHost* rdh); | |
154 ~DownloadFileManager(); | |
155 | |
156 // Lifetime management functions, called on the UI thread. | |
157 void Initialize(); | |
158 void Shutdown(); | |
159 | |
160 // Called on the IO thread | |
161 int GetNextId(); | |
162 | |
163 // Handlers for notifications sent from the IO thread and run on the | |
164 // download thread. | |
165 void StartDownload(DownloadCreateInfo* info); | |
166 void UpdateDownload(int id, DownloadBuffer* buffer); | |
167 void CancelDownload(int id); | |
168 void DownloadFinished(int id, DownloadBuffer* buffer); | |
169 | |
170 // Handlers for notifications sent from the download thread and run on | |
171 // the UI thread. | |
172 void OnStartDownload(DownloadCreateInfo* info); | |
173 void OnDownloadFinished(int id, int64 bytes_so_far); | |
174 | |
175 // Download the URL. Called on the UI thread and forwarded to the | |
176 // ResourceDispatcherHost on the IO thread. | |
177 void DownloadUrl(const GURL& url, | |
178 const GURL& referrer, | |
179 int render_process_host_id, | |
180 int render_view_id, | |
181 URLRequestContext* request_context); | |
182 | |
183 // Run on the IO thread to initiate the download of a URL. | |
184 void OnDownloadUrl(const GURL& url, | |
185 const GURL& referrer, | |
186 int render_process_host_id, | |
187 int render_view_id, | |
188 URLRequestContext* request_context); | |
189 | |
190 // Called on the UI thread to remove a download item or manager. | |
191 void RemoveDownloadManager(DownloadManager* manager); | |
192 void RemoveDownload(int id, DownloadManager* manager); | |
193 | |
194 // Handler for shell operations sent from the UI to the download thread. | |
195 void OnShowDownloadInShell(const std::wstring full_path); | |
196 // Handler to open or execute a downloaded file. | |
197 void OnOpenDownloadInShell(const std::wstring full_path, | |
198 const std::wstring& url, HWND parent_window); | |
199 | |
200 // The download manager has provided a final name for a download. Sent from | |
201 // the UI thread and run on the download thread. | |
202 void OnFinalDownloadName(int id, const std::wstring& full_path); | |
203 | |
204 // Timer notifications. | |
205 void UpdateInProgressDownloads(); | |
206 | |
207 MessageLoop* file_loop() const { return file_loop_; } | |
208 | |
209 // Called by the download manager at initialization to ensure the default | |
210 // download directory exists. | |
211 void CreateDirectory(const std::wstring& directory); | |
212 | |
213 private: | |
214 // Timer helpers for updating the UI about the current progress of a download. | |
215 void StartUpdateTimer(); | |
216 void StopUpdateTimer(); | |
217 | |
218 // Clean up helper that runs on the download thread. | |
219 void OnShutdown(); | |
220 | |
221 // Called only on UI thread to get the DownloadManager for a tab's profile. | |
222 static DownloadManager* DownloadManagerFromRenderIds(int render_process_id, | |
223 int review_view_id); | |
224 DownloadManager* LookupManager(int download_id); | |
225 | |
226 // Called only on the download thread. | |
227 DownloadFile* LookupDownload(int id); | |
228 | |
229 // Called on the UI thread to remove a download from the UI progress table. | |
230 void RemoveDownloadFromUIProgress(int id); | |
231 | |
232 // Unique ID for each DownloadFile. | |
233 int next_id_; | |
234 | |
235 // A map of all in progress downloads. | |
236 typedef base::hash_map<int, DownloadFile*> DownloadFileMap; | |
237 DownloadFileMap downloads_; | |
238 | |
239 // Throttle updates to the UI thread. | |
240 base::RepeatingTimer<DownloadFileManager> update_timer_; | |
241 | |
242 // The MessageLoop that the DownloadManagers live on. | |
243 MessageLoop* ui_loop_; | |
244 | |
245 // The MessageLoop that the this objects primarily operates on. | |
246 MessageLoop* file_loop_; | |
247 | |
248 // Used only for DCHECKs! | |
249 MessageLoop* io_loop_; | |
250 | |
251 ResourceDispatcherHost* resource_dispatcher_host_; | |
252 | |
253 // Tracking which DownloadManager to send data to, called only on UI thread. | |
254 // DownloadManagerMap maps download IDs to their DownloadManager. | |
255 typedef base::hash_map<int, DownloadManager*> DownloadManagerMap; | |
256 DownloadManagerMap managers_; | |
257 | |
258 // RequestMap maps a DownloadManager to all in-progress download IDs. | |
259 // Called only on the UI thread. | |
260 typedef base::hash_set<int> DownloadRequests; | |
261 typedef base::hash_map<DownloadManager*, DownloadRequests> RequestMap; | |
262 RequestMap requests_; | |
263 | |
264 // Used for progress updates on the UI thread, mapping download->id() to bytes | |
265 // received so far. Written to by the file thread and read by the UI thread. | |
266 typedef base::hash_map<int, int64> ProgressMap; | |
267 ProgressMap ui_progress_; | |
268 Lock progress_lock_; | |
269 | |
270 DISALLOW_EVIL_CONSTRUCTORS(DownloadFileManager); | |
271 }; | |
272 | |
273 #endif // CHROME_BROWSER_DOWNLOAD_FILE_H__ | |
OLD | NEW |