Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "components/component_updater/background_downloader_win.h" | 5 #include "components/update_client/background_downloader_win.h" |
| 6 | 6 |
| 7 #include <atlbase.h> | 7 #include <atlbase.h> |
| 8 #include <atlcom.h> | 8 #include <atlcom.h> |
| 9 | 9 |
| 10 #include <stdint.h> | 10 #include <stdint.h> |
| 11 #include <functional> | 11 #include <functional> |
| 12 #include <iomanip> | 12 #include <iomanip> |
| 13 #include <limits> | 13 #include <limits> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "base/bind.h" | 16 #include "base/bind.h" |
| 17 #include "base/bind_helpers.h" | 17 #include "base/bind_helpers.h" |
| 18 #include "base/files/file_util.h" | 18 #include "base/files/file_util.h" |
| 19 #include "base/message_loop/message_loop_proxy.h" | 19 #include "base/message_loop/message_loop_proxy.h" |
| 20 #include "base/single_thread_task_runner.h" | 20 #include "base/single_thread_task_runner.h" |
| 21 #include "base/strings/sys_string_conversions.h" | 21 #include "base/strings/sys_string_conversions.h" |
| 22 #include "base/win/scoped_co_mem.h" | 22 #include "base/win/scoped_co_mem.h" |
| 23 #include "components/component_updater/component_updater_utils.h" | 23 #include "components/update_client/utils.h" |
| 24 #include "ui/base/win/atl_module.h" | 24 #include "ui/base/win/atl_module.h" |
| 25 #include "url/gurl.h" | 25 #include "url/gurl.h" |
| 26 | 26 |
| 27 using base::win::ScopedCoMem; | 27 using base::win::ScopedCoMem; |
| 28 using base::win::ScopedComPtr; | 28 using base::win::ScopedComPtr; |
| 29 | 29 |
| 30 // The class BackgroundDownloader in this module is an adapter between | 30 // The class BackgroundDownloader in this module is an adapter between |
| 31 // the CrxDownloader interface and the BITS service interfaces. | 31 // the CrxDownloader interface and the BITS service interfaces. |
| 32 // The interface exposed on the CrxDownloader code runs on the main thread, | 32 // The interface exposed on the CrxDownloader code runs on the main thread, |
| 33 // while the BITS specific code runs on a separate thread passed in by the | 33 // while the BITS specific code runs on a separate thread passed in by the |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 86 // | 86 // |
| 87 // In addition to how BITS is managing the life time of the job, there are a | 87 // In addition to how BITS is managing the life time of the job, there are a |
| 88 // couple of special cases defined by the BackgroundDownloader. | 88 // couple of special cases defined by the BackgroundDownloader. |
| 89 // First, if the job encounters any of the 5xx HTTP responses, the job is | 89 // First, if the job encounters any of the 5xx HTTP responses, the job is |
| 90 // not retried, in order to avoid DDOS-ing the servers. | 90 // not retried, in order to avoid DDOS-ing the servers. |
| 91 // Second, there is a simple mechanism to detect stuck jobs, and allow the rest | 91 // Second, there is a simple mechanism to detect stuck jobs, and allow the rest |
| 92 // of the code to move on to trying other urls or trying other components. | 92 // of the code to move on to trying other urls or trying other components. |
| 93 // Last, after completing a job, irrespective of the outcome, the jobs older | 93 // Last, after completing a job, irrespective of the outcome, the jobs older |
| 94 // than a week are proactively cleaned up. | 94 // than a week are proactively cleaned up. |
| 95 | 95 |
| 96 namespace component_updater { | 96 namespace update_client { |
| 97 | 97 |
| 98 namespace { | 98 namespace { |
| 99 | 99 |
| 100 // All jobs created by this module have a specific description so they can | 100 // All jobs created by this module have a specific description so they can |
| 101 // be found at run-time or by using system administration tools. | 101 // be found at run-time or by using system administration tools. |
| 102 const base::char16 kJobDescription[] = L"Chrome Component Updater"; | 102 const base::char16 kJobDescription[] = L"Chrome Component Updater"; |
| 103 | 103 |
| 104 // How often the code looks for changes in the BITS job state. | 104 // How often the code looks for changes in the BITS job state. |
| 105 const int kJobPollingIntervalSec = 4; | 105 const int kJobPollingIntervalSec = 4; |
| 106 | 106 |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 134 const int kHttpStatusFirst = 100; // Continue. | 134 const int kHttpStatusFirst = 100; // Continue. |
| 135 const int kHttpStatusLast = 505; // Version not supported. | 135 const int kHttpStatusLast = 505; // Version not supported. |
| 136 bool is_valid = HIWORD(error) == 0x8019 && | 136 bool is_valid = HIWORD(error) == 0x8019 && |
| 137 LOWORD(error) >= kHttpStatusFirst && | 137 LOWORD(error) >= kHttpStatusFirst && |
| 138 LOWORD(error) <= kHttpStatusLast; | 138 LOWORD(error) <= kHttpStatusLast; |
| 139 return is_valid ? LOWORD(error) : 0; | 139 return is_valid ? LOWORD(error) : 0; |
| 140 } | 140 } |
| 141 | 141 |
| 142 // Returns the files in a BITS job. | 142 // Returns the files in a BITS job. |
| 143 HRESULT GetFilesInJob(IBackgroundCopyJob* job, | 143 HRESULT GetFilesInJob(IBackgroundCopyJob* job, |
| 144 std::vector<ScopedComPtr<IBackgroundCopyFile> >* files) { | 144 std::vector<ScopedComPtr<IBackgroundCopyFile>>* files) { |
| 145 ScopedComPtr<IEnumBackgroundCopyFiles> enum_files; | 145 ScopedComPtr<IEnumBackgroundCopyFiles> enum_files; |
| 146 HRESULT hr = job->EnumFiles(enum_files.Receive()); | 146 HRESULT hr = job->EnumFiles(enum_files.Receive()); |
| 147 if (FAILED(hr)) | 147 if (FAILED(hr)) |
| 148 return hr; | 148 return hr; |
| 149 | 149 |
| 150 ULONG num_files = 0; | 150 ULONG num_files = 0; |
| 151 hr = enum_files->GetCount(&num_files); | 151 hr = enum_files->GetCount(&num_files); |
| 152 if (FAILED(hr)) | 152 if (FAILED(hr)) |
| 153 return hr; | 153 return hr; |
| 154 | 154 |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 252 *error_code_out = FAILED(error_code) ? error_code : E_FAIL; | 252 *error_code_out = FAILED(error_code) ? error_code : E_FAIL; |
| 253 return S_OK; | 253 return S_OK; |
| 254 } | 254 } |
| 255 | 255 |
| 256 // Finds the component updater jobs matching the given predicate. | 256 // Finds the component updater jobs matching the given predicate. |
| 257 // Returns S_OK if the function has found at least one job, returns S_FALSE if | 257 // Returns S_OK if the function has found at least one job, returns S_FALSE if |
| 258 // no job was found, and it returns an error otherwise. | 258 // no job was found, and it returns an error otherwise. |
| 259 template <class Predicate> | 259 template <class Predicate> |
| 260 HRESULT FindBitsJobIf(Predicate pred, | 260 HRESULT FindBitsJobIf(Predicate pred, |
| 261 IBackgroundCopyManager* bits_manager, | 261 IBackgroundCopyManager* bits_manager, |
| 262 std::vector<ScopedComPtr<IBackgroundCopyJob> >* jobs) { | 262 std::vector<ScopedComPtr<IBackgroundCopyJob>>* jobs) { |
| 263 ScopedComPtr<IEnumBackgroundCopyJobs> enum_jobs; | 263 ScopedComPtr<IEnumBackgroundCopyJobs> enum_jobs; |
| 264 HRESULT hr = bits_manager->EnumJobs(0, enum_jobs.Receive()); | 264 HRESULT hr = bits_manager->EnumJobs(0, enum_jobs.Receive()); |
| 265 if (FAILED(hr)) | 265 if (FAILED(hr)) |
| 266 return hr; | 266 return hr; |
| 267 | 267 |
| 268 ULONG job_count = 0; | 268 ULONG job_count = 0; |
| 269 hr = enum_jobs->GetCount(&job_count); | 269 hr = enum_jobs->GetCount(&job_count); |
| 270 if (FAILED(hr)) | 270 if (FAILED(hr)) |
| 271 return hr; | 271 return hr; |
| 272 | 272 |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 310 // of any file in a job matches the argument. | 310 // of any file in a job matches the argument. |
| 311 struct JobFileUrlEqual : public std::binary_function<IBackgroundCopyJob*, | 311 struct JobFileUrlEqual : public std::binary_function<IBackgroundCopyJob*, |
| 312 const base::string16&, | 312 const base::string16&, |
| 313 bool> { | 313 bool> { |
| 314 bool operator()(IBackgroundCopyJob* job, | 314 bool operator()(IBackgroundCopyJob* job, |
| 315 const base::string16& remote_name) const; | 315 const base::string16& remote_name) const; |
| 316 }; | 316 }; |
| 317 | 317 |
| 318 bool JobFileUrlEqual::operator()(IBackgroundCopyJob* job, | 318 bool JobFileUrlEqual::operator()(IBackgroundCopyJob* job, |
| 319 const base::string16& remote_name) const { | 319 const base::string16& remote_name) const { |
| 320 std::vector<ScopedComPtr<IBackgroundCopyFile> > files; | 320 std::vector<ScopedComPtr<IBackgroundCopyFile>> files; |
| 321 HRESULT hr = GetFilesInJob(job, &files); | 321 HRESULT hr = GetFilesInJob(job, &files); |
| 322 if (FAILED(hr)) | 322 if (FAILED(hr)) |
| 323 return false; | 323 return false; |
| 324 | 324 |
| 325 for (size_t i = 0; i != files.size(); ++i) { | 325 for (size_t i = 0; i != files.size(); ++i) { |
| 326 ScopedCoMem<base::char16> name; | 326 ScopedCoMem<base::char16> name; |
| 327 if (SUCCEEDED(files[i]->GetRemoteName(&name)) && | 327 if (SUCCEEDED(files[i]->GetRemoteName(&name)) && |
| 328 remote_name.compare(name) == 0) | 328 remote_name.compare(name) == 0) |
| 329 return true; | 329 return true; |
| 330 } | 330 } |
| 331 | 331 |
| 332 return false; | 332 return false; |
| 333 } | 333 } |
| 334 | 334 |
| 335 // Creates an instance of the BITS manager. | 335 // Creates an instance of the BITS manager. |
| 336 HRESULT GetBitsManager(IBackgroundCopyManager** bits_manager) { | 336 HRESULT GetBitsManager(IBackgroundCopyManager** bits_manager) { |
| 337 ScopedComPtr<IBackgroundCopyManager> object; | 337 ScopedComPtr<IBackgroundCopyManager> object; |
| 338 HRESULT hr = object.CreateInstance(__uuidof(BackgroundCopyManager)); | 338 HRESULT hr = object.CreateInstance(__uuidof(BackgroundCopyManager)); |
| 339 if (FAILED(hr)) { | 339 if (FAILED(hr)) { |
| 340 return hr; | 340 return hr; |
| 341 } | 341 } |
| 342 *bits_manager = object.Detach(); | 342 *bits_manager = object.Detach(); |
| 343 return S_OK; | 343 return S_OK; |
| 344 } | 344 } |
| 345 | 345 |
| 346 void CleanupJobFiles(IBackgroundCopyJob* job) { | 346 void CleanupJobFiles(IBackgroundCopyJob* job) { |
| 347 std::vector<ScopedComPtr<IBackgroundCopyFile> > files; | 347 std::vector<ScopedComPtr<IBackgroundCopyFile>> files; |
| 348 if (FAILED(GetFilesInJob(job, &files))) | 348 if (FAILED(GetFilesInJob(job, &files))) |
| 349 return; | 349 return; |
| 350 for (size_t i = 0; i != files.size(); ++i) { | 350 for (size_t i = 0; i != files.size(); ++i) { |
| 351 base::string16 local_name; | 351 base::string16 local_name; |
| 352 HRESULT hr(GetJobFileProperties(files[i].get(), &local_name, NULL, NULL)); | 352 HRESULT hr(GetJobFileProperties(files[i].get(), &local_name, NULL, NULL)); |
| 353 if (SUCCEEDED(hr)) | 353 if (SUCCEEDED(hr)) |
| 354 DeleteFileAndEmptyParentDirectory(base::FilePath(local_name)); | 354 DeleteFileAndEmptyParentDirectory(base::FilePath(local_name)); |
| 355 } | 355 } |
| 356 } | 356 } |
| 357 | 357 |
| 358 // Cleans up incompleted jobs that are too old. | 358 // Cleans up incompleted jobs that are too old. |
| 359 HRESULT CleanupStaleJobs( | 359 HRESULT CleanupStaleJobs( |
| 360 base::win::ScopedComPtr<IBackgroundCopyManager> bits_manager) { | 360 base::win::ScopedComPtr<IBackgroundCopyManager> bits_manager) { |
| 361 if (!bits_manager.get()) | 361 if (!bits_manager.get()) |
| 362 return E_FAIL; | 362 return E_FAIL; |
| 363 | 363 |
| 364 static base::Time last_sweep; | 364 static base::Time last_sweep; |
| 365 | 365 |
| 366 const base::TimeDelta time_delta( | 366 const base::TimeDelta time_delta( |
| 367 base::TimeDelta::FromDays(kPurgeStaleJobsIntervalBetweenChecksDays)); | 367 base::TimeDelta::FromDays(kPurgeStaleJobsIntervalBetweenChecksDays)); |
| 368 const base::Time current_time(base::Time::Now()); | 368 const base::Time current_time(base::Time::Now()); |
| 369 if (last_sweep + time_delta > current_time) | 369 if (last_sweep + time_delta > current_time) |
| 370 return S_OK; | 370 return S_OK; |
| 371 | 371 |
| 372 last_sweep = current_time; | 372 last_sweep = current_time; |
| 373 | 373 |
| 374 std::vector<ScopedComPtr<IBackgroundCopyJob> > jobs; | 374 std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; |
| 375 HRESULT hr = FindBitsJobIf( | 375 HRESULT hr = FindBitsJobIf( |
| 376 std::bind2nd(JobCreationOlderThanDays(), kPurgeStaleJobsAfterDays), | 376 std::bind2nd(JobCreationOlderThanDays(), kPurgeStaleJobsAfterDays), |
| 377 bits_manager.get(), &jobs); | 377 bits_manager.get(), &jobs); |
| 378 if (FAILED(hr)) | 378 if (FAILED(hr)) |
| 379 return hr; | 379 return hr; |
| 380 | 380 |
| 381 for (size_t i = 0; i != jobs.size(); ++i) { | 381 for (size_t i = 0; i != jobs.size(); ++i) { |
| 382 jobs[i]->Cancel(); | 382 jobs[i]->Cancel(); |
| 383 CleanupJobFiles(jobs[i].get()); | 383 CleanupJobFiles(jobs[i].get()); |
| 384 } | 384 } |
| (...skipping 26 matching lines...) Expand all Loading... | |
| 411 // the interface pointers are valid. Releasing the ownership means leaking | 411 // the interface pointers are valid. Releasing the ownership means leaking |
| 412 // these objects and their associated resources. | 412 // these objects and their associated resources. |
| 413 timer_.release(); | 413 timer_.release(); |
| 414 bits_manager_.Detach(); | 414 bits_manager_.Detach(); |
| 415 job_.Detach(); | 415 job_.Detach(); |
| 416 } | 416 } |
| 417 | 417 |
| 418 void BackgroundDownloader::DoStartDownload(const GURL& url) { | 418 void BackgroundDownloader::DoStartDownload(const GURL& url) { |
| 419 DCHECK(thread_checker_.CalledOnValidThread()); | 419 DCHECK(thread_checker_.CalledOnValidThread()); |
| 420 | 420 |
| 421 task_runner_->PostTask( | 421 task_runner_->PostTask(FROM_HERE, |
| 422 FROM_HERE, | 422 base::Bind(&BackgroundDownloader::BeginDownload, |
| 423 base::Bind( | 423 base::Unretained(this), url)); |
| 424 &BackgroundDownloader::BeginDownload, base::Unretained(this), url)); | |
| 425 } | 424 } |
| 426 | 425 |
| 427 // Called once when this class is asked to do a download. Creates or opens | 426 // Called once when this class is asked to do a download. Creates or opens |
| 428 // an existing bits job, hooks up the notifications, and starts the timer. | 427 // an existing bits job, hooks up the notifications, and starts the timer. |
| 429 void BackgroundDownloader::BeginDownload(const GURL& url) { | 428 void BackgroundDownloader::BeginDownload(const GURL& url) { |
| 430 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 429 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 431 | 430 |
| 432 DCHECK(!timer_); | 431 DCHECK(!timer_); |
| 433 | 432 |
| 434 is_completed_ = false; | 433 is_completed_ = false; |
| 435 download_start_time_ = base::Time::Now(); | 434 download_start_time_ = base::Time::Now(); |
| 436 job_stuck_begin_time_ = download_start_time_; | 435 job_stuck_begin_time_ = download_start_time_; |
| 437 | 436 |
| 438 HRESULT hr = QueueBitsJob(url); | 437 HRESULT hr = QueueBitsJob(url); |
| 439 if (FAILED(hr)) { | 438 if (FAILED(hr)) { |
| 440 EndDownload(hr); | 439 EndDownload(hr); |
| 441 return; | 440 return; |
| 442 } | 441 } |
| 443 | 442 |
| 444 // A repeating timer retains the user task. This timer can be stopped and | 443 // A repeating timer retains the user task. This timer can be stopped and |
| 445 // reset multiple times. | 444 // reset multiple times. |
| 446 timer_.reset(new base::RepeatingTimer<BackgroundDownloader>); | 445 timer_.reset(new base::RepeatingTimer<BackgroundDownloader>); |
| 447 timer_->Start(FROM_HERE, | 446 timer_->Start(FROM_HERE, base::TimeDelta::FromSeconds(kJobPollingIntervalSec), |
| 448 base::TimeDelta::FromSeconds(kJobPollingIntervalSec), | 447 this, &BackgroundDownloader::OnDownloading); |
|
waffles
2015/01/20 21:49:07
Did git cl format do this? I liked the old format
| |
| 449 this, | |
| 450 &BackgroundDownloader::OnDownloading); | |
| 451 } | 448 } |
| 452 | 449 |
| 453 // Called any time the timer fires. | 450 // Called any time the timer fires. |
| 454 void BackgroundDownloader::OnDownloading() { | 451 void BackgroundDownloader::OnDownloading() { |
| 455 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 452 DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| 456 | 453 |
| 457 DCHECK(job_.get()); | 454 DCHECK(job_.get()); |
| 458 | 455 |
| 459 DCHECK(!is_completed_); | 456 DCHECK(!is_completed_); |
| 460 if (is_completed_) | 457 if (is_completed_) |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 551 download_metrics.download_time_ms = download_time.InMilliseconds(); | 548 download_metrics.download_time_ms = download_time.InMilliseconds(); |
| 552 | 549 |
| 553 Result result; | 550 Result result; |
| 554 result.error = error_to_report; | 551 result.error = error_to_report; |
| 555 result.response = response_; | 552 result.response = response_; |
| 556 result.downloaded_bytes = downloaded_bytes; | 553 result.downloaded_bytes = downloaded_bytes; |
| 557 result.total_bytes = total_bytes; | 554 result.total_bytes = total_bytes; |
| 558 main_task_runner_->PostTask( | 555 main_task_runner_->PostTask( |
| 559 FROM_HERE, | 556 FROM_HERE, |
| 560 base::Bind(&BackgroundDownloader::OnDownloadComplete, | 557 base::Bind(&BackgroundDownloader::OnDownloadComplete, |
| 561 base::Unretained(this), | 558 base::Unretained(this), is_handled, result, download_metrics)); |
| 562 is_handled, | |
| 563 result, | |
| 564 download_metrics)); | |
| 565 | 559 |
| 566 // Once the task is posted to the the main thread, this object may be deleted | 560 // Once the task is posted to the the main thread, this object may be deleted |
| 567 // by its owner. It is not safe to access members of this object on the | 561 // by its owner. It is not safe to access members of this object on the |
| 568 // task runner from this point on. The timer is stopped and all BITS | 562 // task runner from this point on. The timer is stopped and all BITS |
| 569 // interface pointers have been released. | 563 // interface pointers have been released. |
| 570 } | 564 } |
| 571 | 565 |
| 572 // Called when the BITS job has been transferred successfully. Completes the | 566 // Called when the BITS job has been transferred successfully. Completes the |
| 573 // BITS job by removing it from the BITS queue and making the download | 567 // BITS job by removing it from the BITS queue and making the download |
| 574 // available to the caller. | 568 // available to the caller. |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 int64_t total_bytes = -1; | 616 int64_t total_bytes = -1; |
| 623 HRESULT hr = GetJobByteCount(job_.get(), &downloaded_bytes, &total_bytes); | 617 HRESULT hr = GetJobByteCount(job_.get(), &downloaded_bytes, &total_bytes); |
| 624 if (FAILED(hr)) | 618 if (FAILED(hr)) |
| 625 return; | 619 return; |
| 626 | 620 |
| 627 Result result; | 621 Result result; |
| 628 result.downloaded_bytes = downloaded_bytes; | 622 result.downloaded_bytes = downloaded_bytes; |
| 629 result.total_bytes = total_bytes; | 623 result.total_bytes = total_bytes; |
| 630 | 624 |
| 631 main_task_runner_->PostTask( | 625 main_task_runner_->PostTask( |
| 632 FROM_HERE, | 626 FROM_HERE, base::Bind(&BackgroundDownloader::OnDownloadProgress, |
| 633 base::Bind(&BackgroundDownloader::OnDownloadProgress, | 627 base::Unretained(this), result)); |
| 634 base::Unretained(this), | |
| 635 result)); | |
| 636 } | 628 } |
| 637 | 629 |
| 638 // Called when the download was cancelled. Since the observer should have | 630 // Called when the download was cancelled. Since the observer should have |
| 639 // been disconnected by now, this notification must not be seen. | 631 // been disconnected by now, this notification must not be seen. |
| 640 void BackgroundDownloader::OnStateCancelled() { | 632 void BackgroundDownloader::OnStateCancelled() { |
| 641 EndDownload(E_UNEXPECTED); | 633 EndDownload(E_UNEXPECTED); |
| 642 } | 634 } |
| 643 | 635 |
| 644 // Called when the download was completed. Same as above. | 636 // Called when the download was completed. Same as above. |
| 645 void BackgroundDownloader::OnStateAcknowledged() { | 637 void BackgroundDownloader::OnStateAcknowledged() { |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 665 if (hr == S_OK) { | 657 if (hr == S_OK) { |
| 666 hr = InitializeNewJob(url); | 658 hr = InitializeNewJob(url); |
| 667 if (FAILED(hr)) | 659 if (FAILED(hr)) |
| 668 return hr; | 660 return hr; |
| 669 } | 661 } |
| 670 | 662 |
| 671 return job_->Resume(); | 663 return job_->Resume(); |
| 672 } | 664 } |
| 673 | 665 |
| 674 HRESULT BackgroundDownloader::CreateOrOpenJob(const GURL& url) { | 666 HRESULT BackgroundDownloader::CreateOrOpenJob(const GURL& url) { |
| 675 std::vector<ScopedComPtr<IBackgroundCopyJob> > jobs; | 667 std::vector<ScopedComPtr<IBackgroundCopyJob>> jobs; |
| 676 HRESULT hr = FindBitsJobIf( | 668 HRESULT hr = FindBitsJobIf( |
| 677 std::bind2nd(JobFileUrlEqual(), base::SysUTF8ToWide(url.spec())), | 669 std::bind2nd(JobFileUrlEqual(), base::SysUTF8ToWide(url.spec())), |
| 678 bits_manager_.get(), &jobs); | 670 bits_manager_.get(), &jobs); |
| 679 if (SUCCEEDED(hr) && !jobs.empty()) { | 671 if (SUCCEEDED(hr) && !jobs.empty()) { |
| 680 job_ = jobs.front(); | 672 job_ = jobs.front(); |
| 681 return S_FALSE; | 673 return S_FALSE; |
| 682 } | 674 } |
| 683 | 675 |
| 684 // Use kJobDescription as a temporary job display name until the proper | 676 // Use kJobDescription as a temporary job display name until the proper |
| 685 // display name is initialized later on. | 677 // display name is initialized later on. |
| 686 GUID guid = {0}; | 678 GUID guid = {0}; |
| 687 ScopedComPtr<IBackgroundCopyJob> job; | 679 ScopedComPtr<IBackgroundCopyJob> job; |
| 688 hr = bits_manager_->CreateJob( | 680 hr = bits_manager_->CreateJob(kJobDescription, BG_JOB_TYPE_DOWNLOAD, &guid, |
| 689 kJobDescription, BG_JOB_TYPE_DOWNLOAD, &guid, job.Receive()); | 681 job.Receive()); |
| 690 if (FAILED(hr)) | 682 if (FAILED(hr)) |
| 691 return hr; | 683 return hr; |
| 692 | 684 |
| 693 job_ = job; | 685 job_ = job; |
| 694 return S_OK; | 686 return S_OK; |
| 695 } | 687 } |
| 696 | 688 |
| 697 HRESULT BackgroundDownloader::InitializeNewJob(const GURL& url) { | 689 HRESULT BackgroundDownloader::InitializeNewJob(const GURL& url) { |
| 698 const base::string16 filename(base::SysUTF8ToWide(url.ExtractFileName())); | 690 const base::string16 filename(base::SysUTF8ToWide(url.ExtractFileName())); |
| 699 | 691 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 735 const base::TimeDelta job_stuck_timeout( | 727 const base::TimeDelta job_stuck_timeout( |
| 736 base::TimeDelta::FromMinutes(kJobStuckTimeoutMin)); | 728 base::TimeDelta::FromMinutes(kJobStuckTimeoutMin)); |
| 737 return job_stuck_begin_time_ + job_stuck_timeout < base::Time::Now(); | 729 return job_stuck_begin_time_ + job_stuck_timeout < base::Time::Now(); |
| 738 } | 730 } |
| 739 | 731 |
| 740 HRESULT BackgroundDownloader::CompleteJob() { | 732 HRESULT BackgroundDownloader::CompleteJob() { |
| 741 HRESULT hr = job_->Complete(); | 733 HRESULT hr = job_->Complete(); |
| 742 if (FAILED(hr) && hr != BG_S_UNABLE_TO_DELETE_FILES) | 734 if (FAILED(hr) && hr != BG_S_UNABLE_TO_DELETE_FILES) |
| 743 return hr; | 735 return hr; |
| 744 | 736 |
| 745 std::vector<ScopedComPtr<IBackgroundCopyFile> > files; | 737 std::vector<ScopedComPtr<IBackgroundCopyFile>> files; |
| 746 hr = GetFilesInJob(job_.get(), &files); | 738 hr = GetFilesInJob(job_.get(), &files); |
| 747 if (FAILED(hr)) | 739 if (FAILED(hr)) |
| 748 return hr; | 740 return hr; |
| 749 | 741 |
| 750 if (files.empty()) | 742 if (files.empty()) |
| 751 return E_UNEXPECTED; | 743 return E_UNEXPECTED; |
| 752 | 744 |
| 753 base::string16 local_name; | 745 base::string16 local_name; |
| 754 BG_FILE_PROGRESS progress = {0}; | 746 BG_FILE_PROGRESS progress = {0}; |
| 755 hr = GetJobFileProperties(files.front().get(), &local_name, NULL, &progress); | 747 hr = GetJobFileProperties(files.front().get(), &local_name, NULL, &progress); |
| 756 if (FAILED(hr)) | 748 if (FAILED(hr)) |
| 757 return hr; | 749 return hr; |
| 758 | 750 |
| 759 // Sanity check the post-conditions of a successful download, including | 751 // Sanity check the post-conditions of a successful download, including |
| 760 // the file and job invariants. The byte counts for a job and its file | 752 // the file and job invariants. The byte counts for a job and its file |
| 761 // must match as a job only contains one file. | 753 // must match as a job only contains one file. |
| 762 DCHECK(progress.Completed); | 754 DCHECK(progress.Completed); |
| 763 DCHECK_EQ(progress.BytesTotal, progress.BytesTransferred); | 755 DCHECK_EQ(progress.BytesTotal, progress.BytesTransferred); |
| 764 | 756 |
| 765 response_ = base::FilePath(local_name); | 757 response_ = base::FilePath(local_name); |
| 766 | 758 |
| 767 return S_OK; | 759 return S_OK; |
| 768 } | 760 } |
| 769 | 761 |
| 770 } // namespace component_updater | 762 } // namespace update_client |
| OLD | NEW |