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

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

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

Powered by Google App Engine
This is Rietveld 408576698