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

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

Issue 2890853002: Downloads: replace BrowserThread::FILE with task scheduler. (Closed)
Patch Set: Add a missing mock expectation. Created 3 years, 6 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
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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 "content/browser/download/save_file_manager.h" 7 #include "content/browser/download/save_file_manager.h"
8 8
9 #include "base/bind.h" 9 #include "base/bind.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
11 #include "base/logging.h" 11 #include "base/logging.h"
12 #include "base/memory/ptr_util.h" 12 #include "base/memory/ptr_util.h"
13 #include "base/strings/string_util.h" 13 #include "base/strings/string_util.h"
14 #include "base/threading/thread.h" 14 #include "base/threading/thread.h"
15 #include "content/browser/child_process_security_policy_impl.h" 15 #include "content/browser/child_process_security_policy_impl.h"
16 #include "content/browser/download/download_task_runner.h"
16 #include "content/browser/download/save_file.h" 17 #include "content/browser/download/save_file.h"
17 #include "content/browser/download/save_file_resource_handler.h" 18 #include "content/browser/download/save_file_resource_handler.h"
18 #include "content/browser/download/save_package.h" 19 #include "content/browser/download/save_package.h"
19 #include "content/browser/loader/resource_dispatcher_host_impl.h" 20 #include "content/browser/loader/resource_dispatcher_host_impl.h"
20 #include "content/browser/renderer_host/render_view_host_impl.h" 21 #include "content/browser/renderer_host/render_view_host_impl.h"
21 #include "content/browser/web_contents/web_contents_impl.h" 22 #include "content/browser/web_contents/web_contents_impl.h"
22 #include "content/public/browser/browser_thread.h" 23 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/render_frame_host.h" 24 #include "content/public/browser/render_frame_host.h"
24 #include "content/public/browser/resource_context.h" 25 #include "content/public/browser/resource_context.h"
25 #include "content/public/common/previews_state.h" 26 #include "content/public/common/previews_state.h"
(...skipping 26 matching lines...) Expand all
52 } 53 }
53 54
54 // static 55 // static
55 SaveFileManager* SaveFileManager::Get() { 56 SaveFileManager* SaveFileManager::Get() {
56 return g_save_file_manager; 57 return g_save_file_manager;
57 } 58 }
58 59
59 // Called during the browser shutdown process to clean up any state (open files, 60 // Called during the browser shutdown process to clean up any state (open files,
60 // timers) that live on the saving thread (file thread). 61 // timers) that live on the saving thread (file thread).
61 void SaveFileManager::Shutdown() { 62 void SaveFileManager::Shutdown() {
62 BrowserThread::PostTask( 63 GetDownloadTaskRunner()->PostTask(
63 BrowserThread::FILE, FROM_HERE, 64 FROM_HERE, base::Bind(&SaveFileManager::OnShutdown, this));
64 base::Bind(&SaveFileManager::OnShutdown, this));
65 } 65 }
66 66
67 // Stop file thread operations. 67 // Stop file thread operations.
68 void SaveFileManager::OnShutdown() { 68 void SaveFileManager::OnShutdown() {
69 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 69 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
70 save_file_map_.clear(); 70 save_file_map_.clear();
71 } 71 }
72 72
73 SaveFile* SaveFileManager::LookupSaveFile(SaveItemId save_item_id) { 73 SaveFile* SaveFileManager::LookupSaveFile(SaveItemId save_item_id) {
74 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 74 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
75 auto it = save_file_map_.find(save_item_id); 75 auto it = save_file_map_.find(save_item_id);
76 return it == save_file_map_.end() ? nullptr : it->second.get(); 76 return it == save_file_map_.end() ? nullptr : it->second.get();
77 } 77 }
78 78
79 // Look up a SavePackage according to a save id. 79 // Look up a SavePackage according to a save id.
80 SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) { 80 SavePackage* SaveFileManager::LookupPackage(SaveItemId save_item_id) {
81 DCHECK_CURRENTLY_ON(BrowserThread::UI); 81 DCHECK_CURRENTLY_ON(BrowserThread::UI);
82 auto it = packages_.find(save_item_id); 82 auto it = packages_.find(save_item_id);
83 if (it != packages_.end()) 83 if (it != packages_.end())
84 return it->second; 84 return it->second;
(...skipping 27 matching lines...) Expand all
112 save_item_id, save_package->id(), render_process_host_id, 112 save_item_id, save_package->id(), render_process_host_id,
113 render_view_routing_id, render_frame_routing_id, context)); 113 render_view_routing_id, render_frame_routing_id, context));
114 } else { 114 } else {
115 // We manually start the save job. 115 // We manually start the save job.
116 SaveFileCreateInfo* info = new SaveFileCreateInfo( 116 SaveFileCreateInfo* info = new SaveFileCreateInfo(
117 file_full_path, url, save_item_id, save_package->id(), 117 file_full_path, url, save_item_id, save_package->id(),
118 render_process_host_id, render_frame_routing_id, save_source); 118 render_process_host_id, render_frame_routing_id, save_source);
119 119
120 // Since the data will come from render process, so we need to start 120 // Since the data will come from render process, so we need to start
121 // this kind of save job by ourself. 121 // this kind of save job by ourself.
122 BrowserThread::PostTask( 122 GetDownloadTaskRunner()->PostTask(
123 BrowserThread::FILE, FROM_HERE, 123 FROM_HERE, base::Bind(&SaveFileManager::StartSave, this, info));
124 base::Bind(&SaveFileManager::StartSave, this, info));
125 } 124 }
126 } 125 }
127 126
128 // Utility function for look up table maintenance, called on the UI thread. 127 // Utility function for look up table maintenance, called on the UI thread.
129 // A manager may have multiple save page job (SavePackage) in progress, 128 // A manager may have multiple save page job (SavePackage) in progress,
130 // so we just look up the save id and remove it from the tracking table. 129 // so we just look up the save id and remove it from the tracking table.
131 void SaveFileManager::RemoveSaveFile(SaveItemId save_item_id, 130 void SaveFileManager::RemoveSaveFile(SaveItemId save_item_id,
132 SavePackage* save_package) { 131 SavePackage* save_package) {
133 DCHECK(save_package); 132 DCHECK(save_package);
134 DCHECK_CURRENTLY_ON(BrowserThread::UI); 133 DCHECK_CURRENTLY_ON(BrowserThread::UI);
(...skipping 18 matching lines...) Expand all
153 render_frame_host)); 152 render_frame_host));
154 if (!web_contents) 153 if (!web_contents)
155 return nullptr; 154 return nullptr;
156 155
157 return web_contents->save_package(); 156 return web_contents->save_package();
158 } 157 }
159 158
160 void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path, 159 void SaveFileManager::DeleteDirectoryOrFile(const base::FilePath& full_path,
161 bool is_dir) { 160 bool is_dir) {
162 DCHECK_CURRENTLY_ON(BrowserThread::UI); 161 DCHECK_CURRENTLY_ON(BrowserThread::UI);
163 BrowserThread::PostTask( 162 GetDownloadTaskRunner()->PostTask(
164 BrowserThread::FILE, FROM_HERE, 163 FROM_HERE, base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile, this,
165 base::Bind(&SaveFileManager::OnDeleteDirectoryOrFile, 164 full_path, is_dir));
166 this, full_path, is_dir));
167 } 165 }
168 166
169 void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) { 167 void SaveFileManager::SendCancelRequest(SaveItemId save_item_id) {
170 // Cancel the request which has specific save id. 168 // Cancel the request which has specific save id.
171 DCHECK(!save_item_id.is_null()); 169 DCHECK(!save_item_id.is_null());
172 BrowserThread::PostTask( 170 GetDownloadTaskRunner()->PostTask(
173 BrowserThread::FILE, FROM_HERE, 171 FROM_HERE, base::Bind(&SaveFileManager::CancelSave, this, save_item_id));
174 base::Bind(&SaveFileManager::CancelSave, this, save_item_id));
175 } 172 }
176 173
177 // Notifications sent from the IO thread and run on the file thread: 174 // Notifications sent from the IO thread and run on the file thread:
178 175
179 // The IO thread created |info|, but the file thread (this method) uses it 176 // The IO thread created |info|, but the file thread (this method) uses it
180 // to create a SaveFile which will hold and finally destroy |info|. It will 177 // to create a SaveFile which will hold and finally destroy |info|. It will
181 // then passes |info| to the UI thread for reporting saving status. 178 // then passes |info| to the UI thread for reporting saving status.
182 void SaveFileManager::StartSave(SaveFileCreateInfo* info) { 179 void SaveFileManager::StartSave(SaveFileCreateInfo* info) {
183 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 180 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
184 DCHECK(info); 181 DCHECK(info);
185 // No need to calculate hash. 182 // No need to calculate hash.
186 std::unique_ptr<SaveFile> save_file = base::MakeUnique<SaveFile>(info, false); 183 std::unique_ptr<SaveFile> save_file = base::MakeUnique<SaveFile>(info, false);
187 184
188 // TODO(phajdan.jr): We should check the return value and handle errors here. 185 // TODO(phajdan.jr): We should check the return value and handle errors here.
189 save_file->Initialize(); 186 save_file->Initialize();
190 info->path = save_file->FullPath(); 187 info->path = save_file->FullPath();
191 188
192 DCHECK(!LookupSaveFile(info->save_item_id)); 189 DCHECK(!LookupSaveFile(info->save_item_id));
193 save_file_map_[info->save_item_id] = std::move(save_file); 190 save_file_map_[info->save_item_id] = std::move(save_file);
194 191
195 BrowserThread::PostTask( 192 BrowserThread::PostTask(
196 BrowserThread::UI, FROM_HERE, 193 BrowserThread::UI, FROM_HERE,
197 base::Bind(&SaveFileManager::OnStartSave, this, *info)); 194 base::Bind(&SaveFileManager::OnStartSave, this, *info));
198 } 195 }
199 196
200 // We do forward an update to the UI thread here, since we do not use timer to 197 // We do forward an update to the UI thread here, since we do not use timer to
201 // update the UI. If the user has canceled the saving action (in the UI 198 // update the UI. If the user has canceled the saving action (in the UI
202 // thread). We may receive a few more updates before the IO thread gets the 199 // thread). We may receive a few more updates before the IO thread gets the
203 // cancel message. We just delete the data since the SaveFile has been deleted. 200 // cancel message. We just delete the data since the SaveFile has been deleted.
204 void SaveFileManager::UpdateSaveProgress(SaveItemId save_item_id, 201 void SaveFileManager::UpdateSaveProgress(SaveItemId save_item_id,
205 net::IOBuffer* data, 202 net::IOBuffer* data,
206 int data_len) { 203 int data_len) {
207 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 204 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
208 SaveFile* save_file = LookupSaveFile(save_item_id); 205 SaveFile* save_file = LookupSaveFile(save_item_id);
209 if (save_file) { 206 if (save_file) {
210 DCHECK(save_file->InProgress()); 207 DCHECK(save_file->InProgress());
211 208
212 DownloadInterruptReason reason = 209 DownloadInterruptReason reason =
213 save_file->AppendDataToFile(data->data(), data_len); 210 save_file->AppendDataToFile(data->data(), data_len);
214 BrowserThread::PostTask( 211 BrowserThread::PostTask(
215 BrowserThread::UI, FROM_HERE, 212 BrowserThread::UI, FROM_HERE,
216 base::Bind(&SaveFileManager::OnUpdateSaveProgress, this, 213 base::Bind(&SaveFileManager::OnUpdateSaveProgress, this,
217 save_file->save_item_id(), save_file->BytesSoFar(), 214 save_file->save_item_id(), save_file->BytesSoFar(),
218 reason == DOWNLOAD_INTERRUPT_REASON_NONE)); 215 reason == DOWNLOAD_INTERRUPT_REASON_NONE));
219 } 216 }
220 } 217 }
221 218
222 // The IO thread will call this when saving is completed or it got error when 219 // The IO thread will call this when saving is completed or it got error when
223 // fetching data. We forward the message to OnSaveFinished in UI thread. 220 // fetching data. We forward the message to OnSaveFinished in UI thread.
224 void SaveFileManager::SaveFinished(SaveItemId save_item_id, 221 void SaveFileManager::SaveFinished(SaveItemId save_item_id,
225 SavePackageId save_package_id, 222 SavePackageId save_package_id,
226 bool is_success) { 223 bool is_success) {
227 DVLOG(20) << __func__ << "() save_item_id = " << save_item_id 224 DVLOG(20) << __func__ << "() save_item_id = " << save_item_id
228 << " save_package_id = " << save_package_id 225 << " save_package_id = " << save_package_id
229 << " is_success = " << is_success; 226 << " is_success = " << is_success;
230 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 227 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
231 228
232 int64_t bytes_so_far = 0; 229 int64_t bytes_so_far = 0;
233 SaveFile* save_file = LookupSaveFile(save_item_id); 230 SaveFile* save_file = LookupSaveFile(save_item_id);
234 if (save_file != nullptr) { 231 if (save_file != nullptr) {
235 DCHECK(save_file->InProgress()); 232 DCHECK(save_file->InProgress());
236 DVLOG(20) << __func__ << "() save_file = " << save_file->DebugString(); 233 DVLOG(20) << __func__ << "() save_file = " << save_file->DebugString();
237 bytes_so_far = save_file->BytesSoFar(); 234 bytes_so_far = save_file->BytesSoFar();
238 save_file->Finish(); 235 save_file->Finish();
239 save_file->Detach(); 236 save_file->Detach();
240 } else { 237 } else {
(...skipping 114 matching lines...) Expand 10 before | Expand all | Expand 10 after
355 } 352 }
356 353
357 // Notifications sent from the UI thread and run on the file thread. 354 // Notifications sent from the UI thread and run on the file thread.
358 355
359 // This method will be sent via a user action, or shutdown on the UI thread, 356 // This method will be sent via a user action, or shutdown on the UI thread,
360 // and run on the file thread. We don't post a message back for cancels, 357 // and run on the file thread. We don't post a message back for cancels,
361 // but we do forward the cancel to the IO thread. Since this message has been 358 // but we do forward the cancel to the IO thread. Since this message has been
362 // sent from the UI thread, the saving job may have already completed and 359 // sent from the UI thread, the saving job may have already completed and
363 // won't exist in our map. 360 // won't exist in our map.
364 void SaveFileManager::CancelSave(SaveItemId save_item_id) { 361 void SaveFileManager::CancelSave(SaveItemId save_item_id) {
365 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 362 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
366 auto it = save_file_map_.find(save_item_id); 363 auto it = save_file_map_.find(save_item_id);
367 if (it != save_file_map_.end()) { 364 if (it != save_file_map_.end()) {
368 std::unique_ptr<SaveFile> save_file = std::move(it->second); 365 std::unique_ptr<SaveFile> save_file = std::move(it->second);
369 366
370 if (!save_file->InProgress()) { 367 if (!save_file->InProgress()) {
371 // We've won a race with the UI thread--we finished the file before 368 // We've won a race with the UI thread--we finished the file before
372 // the UI thread cancelled it on us. Unfortunately, in this situation 369 // the UI thread cancelled it on us. Unfortunately, in this situation
373 // the cancel wins, so we need to delete the now detached file. 370 // the cancel wins, so we need to delete the now detached file.
374 base::DeleteFile(save_file->FullPath(), false); 371 base::DeleteFile(save_file->FullPath(), false);
375 } else if (save_file->save_source() == 372 } else if (save_file->save_source() ==
376 SaveFileCreateInfo::SAVE_FILE_FROM_NET) { 373 SaveFileCreateInfo::SAVE_FILE_FROM_NET) {
377 // If the data comes from the net IO thread and hasn't completed 374 // If the data comes from the net IO thread and hasn't completed
378 // yet, then forward the cancel message to IO thread & cancel the 375 // yet, then forward the cancel message to IO thread & cancel the
379 // save locally. If the data doesn't come from the IO thread, 376 // save locally. If the data doesn't come from the IO thread,
380 // we can ignore the message. 377 // we can ignore the message.
381 BrowserThread::PostTask( 378 BrowserThread::PostTask(
382 BrowserThread::IO, FROM_HERE, 379 BrowserThread::IO, FROM_HERE,
383 base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this, 380 base::Bind(&SaveFileManager::ExecuteCancelSaveRequest, this,
384 save_file->render_process_id(), save_file->request_id())); 381 save_file->render_process_id(), save_file->request_id()));
385 } 382 }
386 383
387 // Whatever the save file is complete or not, just delete it. This 384 // Whatever the save file is complete or not, just delete it. This
388 // will delete the underlying file if InProgress() is true. 385 // will delete the underlying file if InProgress() is true.
389 save_file_map_.erase(it); 386 save_file_map_.erase(it);
390 } 387 }
391 } 388 }
392 389
393 void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path, 390 void SaveFileManager::OnDeleteDirectoryOrFile(const base::FilePath& full_path,
394 bool is_dir) { 391 bool is_dir) {
395 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 392 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
396 DCHECK(!full_path.empty()); 393 DCHECK(!full_path.empty());
397 394
398 base::DeleteFile(full_path, is_dir); 395 base::DeleteFile(full_path, is_dir);
399 } 396 }
400 397
401 void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names, 398 void SaveFileManager::RenameAllFiles(const FinalNamesMap& final_names,
402 const base::FilePath& resource_dir, 399 const base::FilePath& resource_dir,
403 int render_process_id, 400 int render_process_id,
404 int render_frame_routing_id, 401 int render_frame_routing_id,
405 SavePackageId save_package_id) { 402 SavePackageId save_package_id) {
406 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 403 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
407 404
408 if (!resource_dir.empty() && !base::PathExists(resource_dir)) 405 if (!resource_dir.empty() && !base::PathExists(resource_dir))
409 base::CreateDirectory(resource_dir); 406 base::CreateDirectory(resource_dir);
410 407
411 for (const auto& i : final_names) { 408 for (const auto& i : final_names) {
412 SaveItemId save_item_id = i.first; 409 SaveItemId save_item_id = i.first;
413 const base::FilePath& final_name = i.second; 410 const base::FilePath& final_name = i.second;
414 411
415 auto it = save_file_map_.find(save_item_id); 412 auto it = save_file_map_.find(save_item_id);
416 if (it != save_file_map_.end()) { 413 if (it != save_file_map_.end()) {
(...skipping 17 matching lines...) Expand all
434 431
435 SavePackage* save_package = 432 SavePackage* save_package =
436 GetSavePackageFromRenderIds(render_process_id, render_frame_routing_id); 433 GetSavePackageFromRenderIds(render_process_id, render_frame_routing_id);
437 434
438 if (save_package && save_package->id() == save_package_id) 435 if (save_package && save_package->id() == save_package_id)
439 save_package->Finish(); 436 save_package->Finish();
440 } 437 }
441 438
442 void SaveFileManager::RemoveSavedFileFromFileMap( 439 void SaveFileManager::RemoveSavedFileFromFileMap(
443 const std::vector<SaveItemId>& save_item_ids) { 440 const std::vector<SaveItemId>& save_item_ids) {
444 DCHECK_CURRENTLY_ON(BrowserThread::FILE); 441 DCHECK(GetDownloadTaskRunner()->RunsTasksInCurrentSequence());
445 442
446 for (const SaveItemId save_item_id : save_item_ids) { 443 for (const SaveItemId save_item_id : save_item_ids) {
447 auto it = save_file_map_.find(save_item_id); 444 auto it = save_file_map_.find(save_item_id);
448 if (it != save_file_map_.end()) { 445 if (it != save_file_map_.end()) {
449 SaveFile* save_file = it->second.get(); 446 SaveFile* save_file = it->second.get();
450 DCHECK(!save_file->InProgress()); 447 DCHECK(!save_file->InProgress());
451 base::DeleteFile(save_file->FullPath(), false); 448 base::DeleteFile(save_file->FullPath(), false);
452 save_file_map_.erase(it); 449 save_file_map_.erase(it);
453 } 450 }
454 } 451 }
455 } 452 }
456 453
457 } // namespace content 454 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698