Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(145)

Side by Side Diff: chrome/browser/download/save_file_manager.cc

Issue 348037: Fourth patch in getting rid of caching MessageLoop pointers. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 11 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « chrome/browser/download/save_file_manager.h ('k') | chrome/browser/download/save_package.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "build/build_config.h" 5 #include "build/build_config.h"
6 6
7 #include "chrome/browser/download/save_file_manager.h" 7 #include "chrome/browser/download/save_file_manager.h"
8 8
9 #include "base/file_util.h" 9 #include "base/file_util.h"
10 #include "base/logging.h" 10 #include "base/logging.h"
11 #include "base/stl_util-inl.h" 11 #include "base/stl_util-inl.h"
12 #include "base/string_util.h" 12 #include "base/string_util.h"
13 #include "base/task.h" 13 #include "base/task.h"
14 #include "base/thread.h" 14 #include "base/thread.h"
15 #include "chrome/browser/browser_process.h" 15 #include "chrome/browser/chrome_thread.h"
16 #include "chrome/browser/download/save_file.h" 16 #include "chrome/browser/download/save_file.h"
17 #include "chrome/browser/download/save_package.h" 17 #include "chrome/browser/download/save_package.h"
18 #include "chrome/browser/net/url_request_context_getter.h" 18 #include "chrome/browser/net/url_request_context_getter.h"
19 #include "chrome/browser/renderer_host/resource_dispatcher_host.h" 19 #include "chrome/browser/renderer_host/resource_dispatcher_host.h"
20 #include "chrome/browser/tab_contents/tab_contents.h" 20 #include "chrome/browser/tab_contents/tab_contents.h"
21 #include "chrome/browser/tab_contents/tab_util.h" 21 #include "chrome/browser/tab_contents/tab_util.h"
22 #include "chrome/common/chrome_paths.h" 22 #include "chrome/common/chrome_paths.h"
23 #include "chrome/common/platform_util.h" 23 #include "chrome/common/platform_util.h"
24 #include "googleurl/src/gurl.h" 24 #include "googleurl/src/gurl.h"
25 #include "net/base/net_util.h" 25 #include "net/base/net_util.h"
26 #include "net/base/io_buffer.h" 26 #include "net/base/io_buffer.h"
27 #include "net/url_request/url_request_context.h" 27 #include "net/url_request/url_request_context.h"
28 28
29 29
30 SaveFileManager::SaveFileManager(MessageLoop* ui_loop, 30 SaveFileManager::SaveFileManager(ResourceDispatcherHost* rdh)
31 MessageLoop* io_loop,
32 ResourceDispatcherHost* rdh)
33 : next_id_(0), 31 : next_id_(0),
34 ui_loop_(ui_loop),
35 io_loop_(io_loop),
36 resource_dispatcher_host_(rdh) { 32 resource_dispatcher_host_(rdh) {
37 DCHECK(ui_loop_);
38 // Need to make sure that we are in UI thread because using g_browser_process
39 // on a non-UI thread can cause crashes during shutdown.
40 DCHECK_EQ(ui_loop_, MessageLoop::current());
41 // Cache the message loop of file thread.
42 base::Thread* thread = g_browser_process->file_thread();
43 if (thread)
44 file_loop_ = thread->message_loop();
45 else
46 // It could be NULL when it is created in unit test of
47 // ResourceDispatcherHost.
48 file_loop_ = NULL;
49 DCHECK(resource_dispatcher_host_); 33 DCHECK(resource_dispatcher_host_);
50 } 34 }
51 35
52 SaveFileManager::~SaveFileManager() { 36 SaveFileManager::~SaveFileManager() {
53 // Check for clean shutdown. 37 // Check for clean shutdown.
54 DCHECK(save_file_map_.empty()); 38 DCHECK(save_file_map_.empty());
55 } 39 }
56 40
57 // Called during the browser shutdown process to clean up any state (open files, 41 // Called during the browser shutdown process to clean up any state (open files,
58 // timers) that live on the saving thread (file thread). 42 // timers) that live on the saving thread (file thread).
59 void SaveFileManager::Shutdown() { 43 void SaveFileManager::Shutdown() {
60 MessageLoop* loop = file_loop(); 44 ChromeThread::PostTask(
61 if (loop) { 45 ChromeThread::FILE, FROM_HERE,
62 loop->PostTask(FROM_HERE, 46 NewRunnableMethod(this, &SaveFileManager::OnShutdown));
63 NewRunnableMethod(this, &SaveFileManager::OnShutdown));
64 }
65 } 47 }
66 48
67 // Stop file thread operations. 49 // Stop file thread operations.
68 void SaveFileManager::OnShutdown() { 50 void SaveFileManager::OnShutdown() {
69 DCHECK_EQ(MessageLoop::current(), file_loop()); 51 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
70 STLDeleteValues(&save_file_map_); 52 STLDeleteValues(&save_file_map_);
71 } 53 }
72 54
73 SaveFile* SaveFileManager::LookupSaveFile(int save_id) { 55 SaveFile* SaveFileManager::LookupSaveFile(int save_id) {
74 SaveFileMap::iterator it = save_file_map_.find(save_id); 56 SaveFileMap::iterator it = save_file_map_.find(save_id);
75 return it == save_file_map_.end() ? NULL : it->second; 57 return it == save_file_map_.end() ? NULL : it->second;
76 } 58 }
77 59
78 // Called on the IO thread when 60 // Called on the IO thread when
79 // a) The ResourceDispatcherHost has decided that a request is savable. 61 // a) The ResourceDispatcherHost has decided that a request is savable.
80 // b) The resource does not come from the network, but we still need a 62 // b) The resource does not come from the network, but we still need a
81 // save ID for for managing the status of the saving operation. So we 63 // save ID for for managing the status of the saving operation. So we
82 // file a request from the file thread to the IO thread to generate a 64 // file a request from the file thread to the IO thread to generate a
83 // unique save ID. 65 // unique save ID.
84 int SaveFileManager::GetNextId() { 66 int SaveFileManager::GetNextId() {
85 DCHECK_EQ(MessageLoop::current(), io_loop_); 67 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
86 return next_id_++; 68 return next_id_++;
87 } 69 }
88 70
89 void SaveFileManager::RegisterStartingRequest(const GURL& save_url, 71 void SaveFileManager::RegisterStartingRequest(const GURL& save_url,
90 SavePackage* save_package) { 72 SavePackage* save_package) {
91 // Make sure it runs in the UI thread. 73 // Make sure it runs in the UI thread.
92 DCHECK_EQ(MessageLoop::current(), ui_loop_); 74 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
93 int tab_id = save_package->tab_id(); 75 int tab_id = save_package->tab_id();
94 76
95 // Register this starting request. 77 // Register this starting request.
96 StartingRequestsMap& starting_requests = tab_starting_requests_[tab_id]; 78 StartingRequestsMap& starting_requests = tab_starting_requests_[tab_id];
97 bool never_present = starting_requests.insert( 79 bool never_present = starting_requests.insert(
98 StartingRequestsMap::value_type(save_url.spec(), save_package)).second; 80 StartingRequestsMap::value_type(save_url.spec(), save_package)).second;
99 DCHECK(never_present); 81 DCHECK(never_present);
100 } 82 }
101 83
102 SavePackage* SaveFileManager::UnregisterStartingRequest( 84 SavePackage* SaveFileManager::UnregisterStartingRequest(
103 const GURL& save_url, int tab_id) { 85 const GURL& save_url, int tab_id) {
104 // Make sure it runs in UI thread. 86 // Make sure it runs in UI thread.
105 DCHECK_EQ(MessageLoop::current(), ui_loop_); 87 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
106 88
107 TabToStartingRequestsMap::iterator it = tab_starting_requests_.find(tab_id); 89 TabToStartingRequestsMap::iterator it = tab_starting_requests_.find(tab_id);
108 if (it != tab_starting_requests_.end()) { 90 if (it != tab_starting_requests_.end()) {
109 StartingRequestsMap& requests = it->second; 91 StartingRequestsMap& requests = it->second;
110 StartingRequestsMap::iterator sit = requests.find(save_url.spec()); 92 StartingRequestsMap::iterator sit = requests.find(save_url.spec());
111 if (sit == requests.end()) 93 if (sit == requests.end())
112 return NULL; 94 return NULL;
113 95
114 // Found, erase it from starting list and return SavePackage. 96 // Found, erase it from starting list and return SavePackage.
115 SavePackage* save_package = sit->second; 97 SavePackage* save_package = sit->second;
116 requests.erase(sit); 98 requests.erase(sit);
117 // If there is no element in requests, remove it 99 // If there is no element in requests, remove it
118 if (requests.empty()) 100 if (requests.empty())
119 tab_starting_requests_.erase(it); 101 tab_starting_requests_.erase(it);
120 return save_package; 102 return save_package;
121 } 103 }
122 104
123 return NULL; 105 return NULL;
124 } 106 }
125 107
126 void SaveFileManager::RequireSaveJobFromOtherSource(SaveFileCreateInfo* info) {
127 // This function must be called on the UI thread, because the io_loop_
128 // pointer may be junk when we use it on file thread. We can only rely on the
129 // io_loop_ pointer being valid when we run code on the UI thread (or on
130 // the IO thread.
131 DCHECK_EQ(MessageLoop::current(), ui_loop_);
132 DCHECK_EQ(info->save_id, -1);
133 // Since the data will come from render process, so we need to start
134 // this kind of save job by ourself.
135 io_loop_->PostTask(FROM_HERE,
136 NewRunnableMethod(this,
137 &SaveFileManager::OnRequireSaveJobFromOtherSource,
138 info));
139 }
140
141 // Look up a SavePackage according to a save id. 108 // Look up a SavePackage according to a save id.
142 SavePackage* SaveFileManager::LookupPackage(int save_id) { 109 SavePackage* SaveFileManager::LookupPackage(int save_id) {
143 DCHECK_EQ(MessageLoop::current(), ui_loop_); 110 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
144 SavePackageMap::iterator it = packages_.find(save_id); 111 SavePackageMap::iterator it = packages_.find(save_id);
145 if (it != packages_.end()) 112 if (it != packages_.end())
146 return it->second; 113 return it->second;
147 return NULL; 114 return NULL;
148 } 115 }
149 116
150 // Call from SavePackage for starting a saving job 117 // Call from SavePackage for starting a saving job
151 void SaveFileManager::SaveURL(const GURL& url, 118 void SaveFileManager::SaveURL(const GURL& url,
152 const GURL& referrer, 119 const GURL& referrer,
153 int render_process_host_id, 120 int render_process_host_id,
154 int render_view_id, 121 int render_view_id,
155 SaveFileCreateInfo::SaveFileSource save_source, 122 SaveFileCreateInfo::SaveFileSource save_source,
156 const FilePath& file_full_path, 123 const FilePath& file_full_path,
157 URLRequestContextGetter* request_context_getter, 124 URLRequestContextGetter* request_context_getter,
158 SavePackage* save_package) { 125 SavePackage* save_package) {
159 DCHECK_EQ(MessageLoop::current(), ui_loop_); 126 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
160 if (!io_loop_) {
161 NOTREACHED(); // Net IO thread must exist.
162 return;
163 }
164 127
165 // Register a saving job. 128 // Register a saving job.
166 RegisterStartingRequest(url, save_package); 129 RegisterStartingRequest(url, save_package);
167 if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 130 if (save_source == SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
168 DCHECK(url.is_valid()); 131 DCHECK(url.is_valid());
169 132
170 io_loop_->PostTask(FROM_HERE, 133 ChromeThread::PostTask(
134 ChromeThread::IO, FROM_HERE,
171 NewRunnableMethod(this, 135 NewRunnableMethod(this,
172 &SaveFileManager::OnSaveURL, 136 &SaveFileManager::OnSaveURL,
173 url, 137 url,
174 referrer, 138 referrer,
175 render_process_host_id, 139 render_process_host_id,
176 render_view_id, 140 render_view_id,
177 request_context_getter)); 141 request_context_getter));
178 } else { 142 } else {
179 // We manually start the save job. 143 // We manually start the save job.
180 SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path, 144 SaveFileCreateInfo* info = new SaveFileCreateInfo(file_full_path,
181 url, 145 url,
182 save_source, 146 save_source,
183 -1); 147 -1);
184 info->render_process_id = render_process_host_id; 148 info->render_process_id = render_process_host_id;
185 info->render_view_id = render_view_id; 149 info->render_view_id = render_view_id;
186 RequireSaveJobFromOtherSource(info); 150
151 // Since the data will come from render process, so we need to start
152 // this kind of save job by ourself.
153 ChromeThread::PostTask(
154 ChromeThread::IO, FROM_HERE,
155 NewRunnableMethod(
156 this, &SaveFileManager::OnRequireSaveJobFromOtherSource, info));
187 } 157 }
188 } 158 }
189 159
190 // Utility function for look up table maintenance, called on the UI thread. 160 // Utility function for look up table maintenance, called on the UI thread.
191 // A manager may have multiple save page job (SavePackage) in progress, 161 // A manager may have multiple save page job (SavePackage) in progress,
192 // so we just look up the save id and remove it from the tracking table. 162 // so we just look up the save id and remove it from the tracking table.
193 // If the save id is -1, it means we just send a request to save, but the 163 // If the save id is -1, it means we just send a request to save, but the
194 // saving action has still not happened, need to call UnregisterStartingRequest 164 // saving action has still not happened, need to call UnregisterStartingRequest
195 // to remove it from the tracking map. 165 // to remove it from the tracking map.
196 void SaveFileManager::RemoveSaveFile(int save_id, const GURL& save_url, 166 void SaveFileManager::RemoveSaveFile(int save_id, const GURL& save_url,
197 SavePackage* package) { 167 SavePackage* package) {
198 DCHECK(package); 168 DCHECK(package);
199 DCHECK_EQ(MessageLoop::current(), ui_loop_); 169 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
200 // A save page job(SavePackage) can only have one manager, 170 // A save page job(SavePackage) can only have one manager,
201 // so remove it if it exists. 171 // so remove it if it exists.
202 if (save_id == -1) { 172 if (save_id == -1) {
203 SavePackage* old_package = UnregisterStartingRequest(save_url, 173 SavePackage* old_package = UnregisterStartingRequest(save_url,
204 package->tab_id()); 174 package->tab_id());
205 DCHECK_EQ(old_package, package); 175 DCHECK_EQ(old_package, package);
206 } else { 176 } else {
207 SavePackageMap::iterator it = packages_.find(save_id); 177 SavePackageMap::iterator it = packages_.find(save_id);
208 if (it != packages_.end()) 178 if (it != packages_.end())
209 packages_.erase(it); 179 packages_.erase(it);
210 } 180 }
211 } 181 }
212 182
213 // Static 183 // Static
214 // Utility function for converting request IDs to a TabContents. Must be called 184 // Utility function for converting request IDs to a TabContents. Must be called
215 // only on the UI thread. 185 // only on the UI thread.
216 SavePackage* SaveFileManager::GetSavePackageFromRenderIds( 186 SavePackage* SaveFileManager::GetSavePackageFromRenderIds(
217 int render_process_id, int render_view_id) { 187 int render_process_id, int render_view_id) {
218 TabContents* contents = tab_util::GetTabContentsByID(render_process_id, 188 TabContents* contents = tab_util::GetTabContentsByID(render_process_id,
219 render_view_id); 189 render_view_id);
220 if (contents) 190 if (contents)
221 return contents->save_package(); 191 return contents->save_package();
222 192
223 return NULL; 193 return NULL;
224 } 194 }
225 195
226 // Utility function for deleting specified file. 196 // Utility function for deleting specified file.
227 void SaveFileManager::DeleteDirectoryOrFile(const FilePath& full_path, 197 void SaveFileManager::DeleteDirectoryOrFile(const FilePath& full_path,
228 bool is_dir) { 198 bool is_dir) {
229 DCHECK_EQ(MessageLoop::current(), ui_loop_); 199 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
230 MessageLoop* loop = file_loop(); 200 ChromeThread::PostTask(
231 DCHECK(loop); 201 ChromeThread::FILE, FROM_HERE,
232 loop->PostTask(FROM_HERE, 202 NewRunnableMethod(
233 NewRunnableMethod(this, 203 this, &SaveFileManager::OnDeleteDirectoryOrFile, full_path, is_dir));
234 &SaveFileManager::OnDeleteDirectoryOrFile,
235 full_path,
236 is_dir));
237 } 204 }
238 205
239 void SaveFileManager::SendCancelRequest(int save_id) { 206 void SaveFileManager::SendCancelRequest(int save_id) {
240 // Cancel the request which has specific save id. 207 // Cancel the request which has specific save id.
241 DCHECK_GT(save_id, -1); 208 DCHECK_GT(save_id, -1);
242 MessageLoop* loop = file_loop(); 209 ChromeThread::PostTask(
243 DCHECK(loop); 210 ChromeThread::FILE, FROM_HERE,
244 loop->PostTask(FROM_HERE, 211 NewRunnableMethod(this, &SaveFileManager::CancelSave, save_id));
245 NewRunnableMethod(this,
246 &SaveFileManager::CancelSave,
247 save_id));
248 } 212 }
249 213
250 // Notifications sent from the IO thread and run on the file thread: 214 // Notifications sent from the IO thread and run on the file thread:
251 215
252 // The IO thread created |info|, but the file thread (this method) uses it 216 // The IO thread created |info|, but the file thread (this method) uses it
253 // to create a SaveFile which will hold and finally destroy |info|. It will 217 // to create a SaveFile which will hold and finally destroy |info|. It will
254 // then passes |info| to the UI thread for reporting saving status. 218 // then passes |info| to the UI thread for reporting saving status.
255 void SaveFileManager::StartSave(SaveFileCreateInfo* info) { 219 void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
256 DCHECK_EQ(MessageLoop::current(), file_loop()); 220 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
257 DCHECK(info); 221 DCHECK(info);
258 SaveFile* save_file = new SaveFile(info); 222 SaveFile* save_file = new SaveFile(info);
259 DCHECK(!LookupSaveFile(info->save_id)); 223 DCHECK(!LookupSaveFile(info->save_id));
260 save_file_map_[info->save_id] = save_file; 224 save_file_map_[info->save_id] = save_file;
261 info->path = save_file->full_path(); 225 info->path = save_file->full_path();
262 226
263 ui_loop_->PostTask(FROM_HERE, 227 ChromeThread::PostTask(
264 NewRunnableMethod(this, 228 ChromeThread::UI, FROM_HERE,
265 &SaveFileManager::OnStartSave, 229 NewRunnableMethod(this, &SaveFileManager::OnStartSave, info));
266 info));
267 } 230 }
268 231
269 // We do forward an update to the UI thread here, since we do not use timer to 232 // We do forward an update to the UI thread here, since we do not use timer to
270 // update the UI. If the user has canceled the saving action (in the UI 233 // update the UI. If the user has canceled the saving action (in the UI
271 // thread). We may receive a few more updates before the IO thread gets the 234 // thread). We may receive a few more updates before the IO thread gets the
272 // cancel message. We just delete the data since the SaveFile has been deleted. 235 // cancel message. We just delete the data since the SaveFile has been deleted.
273 void SaveFileManager::UpdateSaveProgress(int save_id, 236 void SaveFileManager::UpdateSaveProgress(int save_id,
274 net::IOBuffer* data, 237 net::IOBuffer* data,
275 int data_len) { 238 int data_len) {
276 DCHECK_EQ(MessageLoop::current(), file_loop()); 239 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
277 SaveFile* save_file = LookupSaveFile(save_id); 240 SaveFile* save_file = LookupSaveFile(save_id);
278 if (save_file) { 241 if (save_file) {
279 bool write_success = save_file->AppendDataToFile(data->data(), data_len); 242 bool write_success = save_file->AppendDataToFile(data->data(), data_len);
280 ui_loop_->PostTask(FROM_HERE, 243 ChromeThread::PostTask(
281 NewRunnableMethod(this, 244 ChromeThread::UI, FROM_HERE,
282 &SaveFileManager::OnUpdateSaveProgress, 245 NewRunnableMethod(
283 save_file->save_id(), 246 this, &SaveFileManager::OnUpdateSaveProgress, save_file->save_id(),
284 save_file->bytes_so_far(), 247 save_file->bytes_so_far(), write_success));
285 write_success));
286 } 248 }
287 data->Release(); 249 data->Release();
288 } 250 }
289 251
290 // The IO thread will call this when saving is completed or it got error when 252 // The IO thread will call this when saving is completed or it got error when
291 // fetching data. In the former case, we forward the message to OnSaveFinished 253 // fetching data. In the former case, we forward the message to OnSaveFinished
292 // in UI thread. In the latter case, the save ID will be -1, which means the 254 // in UI thread. In the latter case, the save ID will be -1, which means the
293 // saving action did not even start, so we need to call OnErrorFinished in UI 255 // saving action did not even start, so we need to call OnErrorFinished in UI
294 // thread, which will use the save URL to find corresponding request record and 256 // thread, which will use the save URL to find corresponding request record and
295 // delete it. 257 // delete it.
296 void SaveFileManager::SaveFinished(int save_id, 258 void SaveFileManager::SaveFinished(int save_id,
297 GURL save_url, 259 GURL save_url,
298 int render_process_id, 260 int render_process_id,
299 bool is_success) { 261 bool is_success) {
300 DCHECK_EQ(MessageLoop::current(), file_loop()); 262 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
301 SaveFileMap::iterator it = save_file_map_.find(save_id); 263 SaveFileMap::iterator it = save_file_map_.find(save_id);
302 if (it != save_file_map_.end()) { 264 if (it != save_file_map_.end()) {
303 SaveFile* save_file = it->second; 265 SaveFile* save_file = it->second;
304 ui_loop_->PostTask(FROM_HERE, 266 ChromeThread::PostTask(
305 NewRunnableMethod(this, 267 ChromeThread::UI, FROM_HERE,
306 &SaveFileManager::OnSaveFinished, 268 NewRunnableMethod(
307 save_id, 269 this, &SaveFileManager::OnSaveFinished, save_id,
308 save_file->bytes_so_far(), 270 save_file->bytes_so_far(), is_success));
309 is_success));
310 271
311 save_file->Finish(); 272 save_file->Finish();
312 } else if (save_id == -1) { 273 } else if (save_id == -1) {
313 // Before saving started, we got error. We still call finish process. 274 // Before saving started, we got error. We still call finish process.
314 DCHECK(!save_url.is_empty()); 275 DCHECK(!save_url.is_empty());
315 ui_loop_->PostTask(FROM_HERE, 276 ChromeThread::PostTask(
316 NewRunnableMethod(this, 277 ChromeThread::UI, FROM_HERE,
317 &SaveFileManager::OnErrorFinished, 278 NewRunnableMethod(
318 save_url, 279 this, &SaveFileManager::OnErrorFinished, save_url,
319 render_process_id)); 280 render_process_id));
320 } 281 }
321 } 282 }
322 283
323 // Notifications sent from the file thread and run on the UI thread. 284 // Notifications sent from the file thread and run on the UI thread.
324 285
325 void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) { 286 void SaveFileManager::OnStartSave(const SaveFileCreateInfo* info) {
326 DCHECK_EQ(MessageLoop::current(), ui_loop_); 287 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
327 SavePackage* save_package = 288 SavePackage* save_package =
328 GetSavePackageFromRenderIds(info->render_process_id, 289 GetSavePackageFromRenderIds(info->render_process_id,
329 info->render_view_id); 290 info->render_view_id);
330 if (!save_package) { 291 if (!save_package) {
331 // Cancel this request. 292 // Cancel this request.
332 SendCancelRequest(info->save_id); 293 SendCancelRequest(info->save_id);
333 return; 294 return;
334 } 295 }
335 296
336 // Insert started saving job to tracking list. 297 // Insert started saving job to tracking list.
(...skipping 13 matching lines...) Expand all
350 } else { 311 } else {
351 NOTREACHED(); 312 NOTREACHED();
352 } 313 }
353 314
354 // Forward this message to SavePackage. 315 // Forward this message to SavePackage.
355 save_package->StartSave(info); 316 save_package->StartSave(info);
356 } 317 }
357 318
358 void SaveFileManager::OnUpdateSaveProgress(int save_id, int64 bytes_so_far, 319 void SaveFileManager::OnUpdateSaveProgress(int save_id, int64 bytes_so_far,
359 bool write_success) { 320 bool write_success) {
360 DCHECK_EQ(MessageLoop::current(), ui_loop_); 321 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
361 SavePackage* package = LookupPackage(save_id); 322 SavePackage* package = LookupPackage(save_id);
362 if (package) 323 if (package)
363 package->UpdateSaveProgress(save_id, bytes_so_far, write_success); 324 package->UpdateSaveProgress(save_id, bytes_so_far, write_success);
364 else 325 else
365 SendCancelRequest(save_id); 326 SendCancelRequest(save_id);
366 } 327 }
367 328
368 void SaveFileManager::OnSaveFinished(int save_id, 329 void SaveFileManager::OnSaveFinished(int save_id,
369 int64 bytes_so_far, 330 int64 bytes_so_far,
370 bool is_success) { 331 bool is_success) {
371 DCHECK_EQ(MessageLoop::current(), ui_loop_); 332 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
372 SavePackage* package = LookupPackage(save_id); 333 SavePackage* package = LookupPackage(save_id);
373 if (package) 334 if (package)
374 package->SaveFinished(save_id, bytes_so_far, is_success); 335 package->SaveFinished(save_id, bytes_so_far, is_success);
375 } 336 }
376 337
377 void SaveFileManager::OnErrorFinished(GURL save_url, int tab_id) { 338 void SaveFileManager::OnErrorFinished(GURL save_url, int tab_id) {
378 DCHECK_EQ(MessageLoop::current(), ui_loop_); 339 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
379 SavePackage* save_package = UnregisterStartingRequest(save_url, tab_id); 340 SavePackage* save_package = UnregisterStartingRequest(save_url, tab_id);
380 if (save_package) 341 if (save_package)
381 save_package->SaveFailed(save_url); 342 save_package->SaveFailed(save_url);
382 } 343 }
383 344
384 void SaveFileManager::OnCancelSaveRequest(int render_process_id,
385 int request_id) {
386 DCHECK_EQ(MessageLoop::current(), ui_loop_);
387 DCHECK(io_loop_);
388 io_loop_->PostTask(FROM_HERE,
389 NewRunnableMethod(this,
390 &SaveFileManager::ExecuteCancelSaveRequest,
391 render_process_id,
392 request_id));
393 }
394
395 // Notifications sent from the UI thread and run on the IO thread. 345 // Notifications sent from the UI thread and run on the IO thread.
396 346
397 void SaveFileManager::OnSaveURL( 347 void SaveFileManager::OnSaveURL(
398 const GURL& url, 348 const GURL& url,
399 const GURL& referrer, 349 const GURL& referrer,
400 int render_process_host_id, 350 int render_process_host_id,
401 int render_view_id, 351 int render_view_id,
402 URLRequestContextGetter* request_context_getter) { 352 URLRequestContextGetter* request_context_getter) {
403 DCHECK_EQ(MessageLoop::current(), io_loop_); 353 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
404 URLRequestContext* context = request_context_getter->GetURLRequestContext(); 354 URLRequestContext* context = request_context_getter->GetURLRequestContext();
405 resource_dispatcher_host_->BeginSaveFile(url, 355 resource_dispatcher_host_->BeginSaveFile(url,
406 referrer, 356 referrer,
407 render_process_host_id, 357 render_process_host_id,
408 render_view_id, 358 render_view_id,
409 context); 359 context);
410 } 360 }
411 361
412 void SaveFileManager::OnRequireSaveJobFromOtherSource( 362 void SaveFileManager::OnRequireSaveJobFromOtherSource(
413 SaveFileCreateInfo* info) { 363 SaveFileCreateInfo* info) {
414 DCHECK_EQ(MessageLoop::current(), io_loop_); 364 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
415 DCHECK_EQ(info->save_id, -1); 365 DCHECK_EQ(info->save_id, -1);
416 // Generate a unique save id. 366 // Generate a unique save id.
417 info->save_id = GetNextId(); 367 info->save_id = GetNextId();
418 // Start real saving action. 368 // Start real saving action.
419 MessageLoop* loop = file_loop(); 369 ChromeThread::PostTask(
420 DCHECK(loop); 370 ChromeThread::FILE, FROM_HERE,
421 loop->PostTask(FROM_HERE, 371 NewRunnableMethod(this, &SaveFileManager::StartSave, info));
422 NewRunnableMethod(this,
423 &SaveFileManager::StartSave,
424 info));
425 } 372 }
426 373
427 void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id, 374 void SaveFileManager::ExecuteCancelSaveRequest(int render_process_id,
428 int request_id) { 375 int request_id) {
429 DCHECK_EQ(MessageLoop::current(), io_loop_); 376 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::IO));
430 resource_dispatcher_host_->CancelRequest(render_process_id, 377 resource_dispatcher_host_->CancelRequest(render_process_id,
431 request_id, 378 request_id,
432 false); 379 false);
433 } 380 }
434 381
435 // Notifications sent from the UI thread and run on the file thread. 382 // Notifications sent from the UI thread and run on the file thread.
436 383
437 // This method will be sent via a user action, or shutdown on the UI thread, 384 // This method will be sent via a user action, or shutdown on the UI thread,
438 // and run on the file thread. We don't post a message back for cancels, 385 // and run on the file thread. We don't post a message back for cancels,
439 // but we do forward the cancel to the IO thread. Since this message has been 386 // but we do forward the cancel to the IO thread. Since this message has been
440 // sent from the UI thread, the saving job may have already completed and 387 // sent from the UI thread, the saving job may have already completed and
441 // won't exist in our map. 388 // won't exist in our map.
442 void SaveFileManager::CancelSave(int save_id) { 389 void SaveFileManager::CancelSave(int save_id) {
443 DCHECK_EQ(MessageLoop::current(), file_loop()); 390 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
444 SaveFileMap::iterator it = save_file_map_.find(save_id); 391 SaveFileMap::iterator it = save_file_map_.find(save_id);
445 if (it != save_file_map_.end()) { 392 if (it != save_file_map_.end()) {
446 SaveFile* save_file = it->second; 393 SaveFile* save_file = it->second;
447 394
448 // If the data comes from the net IO thread, then forward the cancel 395 // If the data comes from the net IO thread, then forward the cancel
449 // message to IO thread. If the data comes from other sources, just 396 // message to IO thread. If the data comes from other sources, just
450 // ignore the cancel message. 397 // ignore the cancel message.
451 if (save_file->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 398 if (save_file->save_source() == SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
452 ui_loop_->PostTask(FROM_HERE, 399 ChromeThread::PostTask(
453 NewRunnableMethod(this, 400 ChromeThread::IO, FROM_HERE,
454 &SaveFileManager::OnCancelSaveRequest, 401 NewRunnableMethod(
455 save_file->render_process_id(), 402 this, &SaveFileManager::ExecuteCancelSaveRequest,
456 save_file->request_id())); 403 save_file->render_process_id(), save_file->request_id()));
457 404
458 // UI thread will notify the render process to stop sending data, 405 // UI thread will notify the render process to stop sending data,
459 // so in here, we need not to do anything, just close the save file. 406 // so in here, we need not to do anything, just close the save file.
460 save_file->Cancel(); 407 save_file->Cancel();
461 } else { 408 } else {
462 // If we did not find SaveFile in map, the saving job should either get 409 // If we did not find SaveFile in map, the saving job should either get
463 // data from other sources or have finished. 410 // data from other sources or have finished.
464 DCHECK(save_file->save_source() != 411 DCHECK(save_file->save_source() !=
465 SaveFileCreateInfo::SAVE_FILE_FROM_NET || 412 SaveFileCreateInfo::SAVE_FILE_FROM_NET ||
466 !save_file->in_progress()); 413 !save_file->in_progress());
467 } 414 }
468 // Whatever the save file is renamed or not, just delete it. 415 // Whatever the save file is renamed or not, just delete it.
469 save_file_map_.erase(it); 416 save_file_map_.erase(it);
470 delete save_file; 417 delete save_file;
471 } 418 }
472 } 419 }
473 420
474 // It is possible that SaveItem which has specified save_id has been canceled 421 // It is possible that SaveItem which has specified save_id has been canceled
475 // before this function runs. So if we can not find corresponding SaveFile by 422 // before this function runs. So if we can not find corresponding SaveFile by
476 // using specified save_id, just return. 423 // using specified save_id, just return.
477 void SaveFileManager::SaveLocalFile(const GURL& original_file_url, 424 void SaveFileManager::SaveLocalFile(const GURL& original_file_url,
478 int save_id, 425 int save_id,
479 int render_process_id) { 426 int render_process_id) {
480 DCHECK_EQ(MessageLoop::current(), file_loop()); 427 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
481 SaveFile* save_file = LookupSaveFile(save_id); 428 SaveFile* save_file = LookupSaveFile(save_id);
482 if (!save_file) 429 if (!save_file)
483 return; 430 return;
484 DCHECK(!save_file->path_renamed()); 431 DCHECK(!save_file->path_renamed());
485 // If it has finished, just return. 432 // If it has finished, just return.
486 if (!save_file->in_progress()) 433 if (!save_file->in_progress())
487 return; 434 return;
488 435
489 // Close the save file before the copy operation. 436 // Close the save file before the copy operation.
490 save_file->Finish(); 437 save_file->Finish();
491 438
492 DCHECK(original_file_url.SchemeIsFile()); 439 DCHECK(original_file_url.SchemeIsFile());
493 FilePath file_path; 440 FilePath file_path;
494 net::FileURLToFilePath(original_file_url, &file_path); 441 net::FileURLToFilePath(original_file_url, &file_path);
495 // If we can not get valid file path from original URL, treat it as 442 // If we can not get valid file path from original URL, treat it as
496 // disk error. 443 // disk error.
497 if (file_path.empty()) 444 if (file_path.empty())
498 SaveFinished(save_id, original_file_url, render_process_id, false); 445 SaveFinished(save_id, original_file_url, render_process_id, false);
499 446
500 // Copy the local file to the temporary file. It will be renamed to its 447 // Copy the local file to the temporary file. It will be renamed to its
501 // final name later. 448 // final name later.
502 bool success = file_util::CopyFile(file_path, save_file->full_path()); 449 bool success = file_util::CopyFile(file_path, save_file->full_path());
503 if (!success) 450 if (!success)
504 file_util::Delete(save_file->full_path(), false); 451 file_util::Delete(save_file->full_path(), false);
505 SaveFinished(save_id, original_file_url, render_process_id, success); 452 SaveFinished(save_id, original_file_url, render_process_id, success);
506 } 453 }
507 454
508 void SaveFileManager::OnDeleteDirectoryOrFile(const FilePath& full_path, 455 void SaveFileManager::OnDeleteDirectoryOrFile(const FilePath& full_path,
509 bool is_dir) { 456 bool is_dir) {
510 DCHECK_EQ(MessageLoop::current(), file_loop()); 457 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
511 DCHECK(!full_path.empty()); 458 DCHECK(!full_path.empty());
512 459
513 file_util::Delete(full_path, is_dir); 460 file_util::Delete(full_path, is_dir);
514 } 461 }
515 462
516 // Open a saved page package, show it in a Windows Explorer window. 463 // Open a saved page package, show it in a Windows Explorer window.
517 // We run on this thread to avoid blocking the UI with slow Shell operations. 464 // We run on this thread to avoid blocking the UI with slow Shell operations.
518 #if !defined(OS_MACOSX) 465 #if !defined(OS_MACOSX)
519 void SaveFileManager::OnShowSavedFileInShell(const FilePath full_path) { 466 void SaveFileManager::OnShowSavedFileInShell(const FilePath full_path) {
520 DCHECK_EQ(MessageLoop::current(), file_loop()); 467 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
521 platform_util::ShowItemInFolder(full_path); 468 platform_util::ShowItemInFolder(full_path);
522 } 469 }
523 #endif 470 #endif
524 471
525 void SaveFileManager::RenameAllFiles( 472 void SaveFileManager::RenameAllFiles(
526 const FinalNameList& final_names, 473 const FinalNameList& final_names,
527 const FilePath& resource_dir, 474 const FilePath& resource_dir,
528 int render_process_id, 475 int render_process_id,
529 int render_view_id) { 476 int render_view_id) {
530 DCHECK_EQ(MessageLoop::current(), file_loop()); 477 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
531 478
532 if (!resource_dir.empty() && !file_util::PathExists(resource_dir)) 479 if (!resource_dir.empty() && !file_util::PathExists(resource_dir))
533 file_util::CreateDirectory(resource_dir); 480 file_util::CreateDirectory(resource_dir);
534 481
535 for (FinalNameList::const_iterator i = final_names.begin(); 482 for (FinalNameList::const_iterator i = final_names.begin();
536 i != final_names.end(); ++i) { 483 i != final_names.end(); ++i) {
537 SaveFileMap::iterator it = save_file_map_.find(i->first); 484 SaveFileMap::iterator it = save_file_map_.find(i->first);
538 if (it != save_file_map_.end()) { 485 if (it != save_file_map_.end()) {
539 SaveFile* save_file = it->second; 486 SaveFile* save_file = it->second;
540 DCHECK(!save_file->in_progress()); 487 DCHECK(!save_file->in_progress());
541 save_file->Rename(i->second); 488 save_file->Rename(i->second);
542 delete save_file; 489 delete save_file;
543 save_file_map_.erase(it); 490 save_file_map_.erase(it);
544 } 491 }
545 } 492 }
546 493
547 ui_loop_->PostTask(FROM_HERE, 494 ChromeThread::PostTask(
548 NewRunnableMethod(this, 495 ChromeThread::UI, FROM_HERE,
549 &SaveFileManager::OnFinishSavePageJob, 496 NewRunnableMethod(
550 render_process_id, 497 this, &SaveFileManager::OnFinishSavePageJob, render_process_id,
551 render_view_id)); 498 render_view_id));
552 } 499 }
553 500
554 void SaveFileManager::OnFinishSavePageJob(int render_process_id, 501 void SaveFileManager::OnFinishSavePageJob(int render_process_id,
555 int render_view_id) { 502 int render_view_id) {
556 DCHECK_EQ(MessageLoop::current(), ui_loop_); 503 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::UI));
557 504
558 SavePackage* save_package = 505 SavePackage* save_package =
559 GetSavePackageFromRenderIds(render_process_id, render_view_id); 506 GetSavePackageFromRenderIds(render_process_id, render_view_id);
560 507
561 if (save_package) { 508 if (save_package) {
562 // save_package is null if save was canceled. 509 // save_package is null if save was canceled.
563 save_package->Finish(); 510 save_package->Finish();
564 } 511 }
565 } 512 }
566 513
567 void SaveFileManager::RemoveSavedFileFromFileMap( 514 void SaveFileManager::RemoveSavedFileFromFileMap(
568 const SaveIDList& save_ids) { 515 const SaveIDList& save_ids) {
569 DCHECK_EQ(MessageLoop::current(), file_loop()); 516 DCHECK(ChromeThread::CurrentlyOn(ChromeThread::FILE));
570 517
571 for (SaveIDList::const_iterator i = save_ids.begin(); 518 for (SaveIDList::const_iterator i = save_ids.begin();
572 i != save_ids.end(); ++i) { 519 i != save_ids.end(); ++i) {
573 SaveFileMap::iterator it = save_file_map_.find(*i); 520 SaveFileMap::iterator it = save_file_map_.find(*i);
574 if (it != save_file_map_.end()) { 521 if (it != save_file_map_.end()) {
575 SaveFile* save_file = it->second; 522 SaveFile* save_file = it->second;
576 DCHECK(!save_file->in_progress()); 523 DCHECK(!save_file->in_progress());
577 file_util::Delete(save_file->full_path(), false); 524 file_util::Delete(save_file->full_path(), false);
578 delete save_file; 525 delete save_file;
579 save_file_map_.erase(it); 526 save_file_map_.erase(it);
580 } 527 }
581 } 528 }
582 } 529 }
OLDNEW
« no previous file with comments | « chrome/browser/download/save_file_manager.h ('k') | chrome/browser/download/save_package.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698