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

Side by Side Diff: chrome/browser/component_updater/background_downloader_win.cc

Issue 385013002: Componentize component_updater: Replace content::BrowserThread usage with task runners (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 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
OLDNEW
1 // Copyright 2013 The Chromium Authors. All rights reserved. 1 // Copyright 2013 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 "chrome/browser/component_updater/background_downloader_win.h" 5 #include "chrome/browser/component_updater/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 <functional> 10 #include <functional>
11 #include <iomanip> 11 #include <iomanip>
12 #include <vector> 12 #include <vector>
13 13
14 #include "base/file_util.h" 14 #include "base/file_util.h"
15 #include "base/message_loop/message_loop_proxy.h"
16 #include "base/single_thread_task_runner.h"
15 #include "base/strings/sys_string_conversions.h" 17 #include "base/strings/sys_string_conversions.h"
16 #include "base/win/scoped_co_mem.h" 18 #include "base/win/scoped_co_mem.h"
17 #include "chrome/browser/component_updater/component_updater_utils.h" 19 #include "chrome/browser/component_updater/component_updater_utils.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "ui/base/win/atl_module.h" 20 #include "ui/base/win/atl_module.h"
20 #include "url/gurl.h" 21 #include "url/gurl.h"
21 22
22 using base::win::ScopedCoMem; 23 using base::win::ScopedCoMem;
23 using base::win::ScopedComPtr; 24 using base::win::ScopedComPtr;
24 using content::BrowserThread;
25 25
26 // The class BackgroundDownloader in this module is an adapter between 26 // The class BackgroundDownloader in this module is an adapter between
27 // the CrxDownloader interface and the BITS service interfaces. 27 // the CrxDownloader interface and the BITS service interfaces.
28 // The interface exposed on the CrxDownloader code runs on the UI thread, while 28 // The interface exposed on the CrxDownloader code runs on the main thread,
29 // the BITS specific code runs in a single threaded apartment on the FILE 29 // while the BITS specific code runs on a separate thread passed in by the
30 // thread. 30 // client. For every url to download, a BITS job is created, unless there is
31 // For every url to download, a BITS job is created, unless there is already 31 // already an existing job for that url, in which case, the downloader
32 // an existing job for that url, in which case, the downloader connects to it. 32 // connects to it. Once a job is associated with the url, the code looks for
33 // Once a job is associated with the url, the code looks for changes in the 33 // changes in the BITS job state. The checks are triggered by a timer.
34 // BITS job state. The checks are triggered by a timer.
35 // The BITS job contains just one file to download. There could only be one 34 // The BITS job contains just one file to download. There could only be one
36 // download in progress at a time. If Chrome closes down before the download is 35 // download in progress at a time. If Chrome closes down before the download is
37 // complete, the BITS job remains active and finishes in the background, without 36 // complete, the BITS job remains active and finishes in the background, without
38 // any intervention. The job can be completed next time the code runs, if the 37 // any intervention. The job can be completed next time the code runs, if the
39 // file is still needed, otherwise it will be cleaned up on a periodic basis. 38 // file is still needed, otherwise it will be cleaned up on a periodic basis.
40 // 39 //
41 // To list the BITS jobs for a user, use the |bitsadmin| tool. The command line 40 // To list the BITS jobs for a user, use the |bitsadmin| tool. The command line
42 // to do that is: "bitsadmin /list /verbose". Another useful command is 41 // to do that is: "bitsadmin /list /verbose". Another useful command is
43 // "bitsadmin /info" and provide the job id returned by the previous /list 42 // "bitsadmin /info" and provide the job id returned by the previous /list
44 // command. 43 // command.
(...skipping 335 matching lines...) Expand 10 before | Expand all | Expand 10 after
380 } 379 }
381 380
382 return S_OK; 381 return S_OK;
383 } 382 }
384 383
385 } // namespace 384 } // namespace
386 385
387 BackgroundDownloader::BackgroundDownloader( 386 BackgroundDownloader::BackgroundDownloader(
388 scoped_ptr<CrxDownloader> successor, 387 scoped_ptr<CrxDownloader> successor,
389 net::URLRequestContextGetter* context_getter, 388 net::URLRequestContextGetter* context_getter,
390 scoped_refptr<base::SequencedTaskRunner> task_runner) 389 scoped_refptr<base::SingleThreadTaskRunner> task_runner)
391 : CrxDownloader(successor.Pass()), 390 : CrxDownloader(successor.Pass()),
391 main_task_runner_(base::MessageLoopProxy::current()),
392 context_getter_(context_getter), 392 context_getter_(context_getter),
393 task_runner_(task_runner), 393 bits_task_runner_(task_runner),
394 is_completed_(false) { 394 is_completed_(false) {
Sorin Jianu 2014/07/21 21:42:13 Keep the assert?
tommycli 2014/07/21 22:00:07 thread_checker_ is bound to the current thread upo
Sorin Jianu 2014/07/21 22:11:32 Of course, I was suggesting to keep it so that it
395 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
396 } 395 }
397 396
398 BackgroundDownloader::~BackgroundDownloader() { 397 BackgroundDownloader::~BackgroundDownloader() {
399 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 398 DCHECK(thread_checker_.CalledOnValidThread());
400 399
401 // The following objects have thread affinity and can't be destroyed on the 400 // The following objects have thread affinity and can't be destroyed on the
402 // UI thread. The resources managed by these objects are acquired at the 401 // main thread. The resources managed by these objects are acquired at the
403 // beginning of a download and released at the end of the download. Most of 402 // beginning of a download and released at the end of the download. Most of
404 // the time, when this destructor is called, these resources have been already 403 // the time, when this destructor is called, these resources have been already
405 // disposed by. Releasing the ownership here is a NOP. However, if the browser 404 // disposed by. Releasing the ownership here is a NOP. However, if the browser
406 // is shutting down while a download is in progress, the timer is active and 405 // is shutting down while a download is in progress, the timer is active and
407 // the interface pointers are valid. Releasing the ownership means leaking 406 // the interface pointers are valid. Releasing the ownership means leaking
408 // these objects and their associated resources. 407 // these objects and their associated resources.
409 timer_.release(); 408 timer_.release();
410 bits_manager_.Detach(); 409 bits_manager_.Detach();
411 job_.Detach(); 410 job_.Detach();
412 } 411 }
413 412
414 void BackgroundDownloader::DoStartDownload(const GURL& url) { 413 void BackgroundDownloader::DoStartDownload(const GURL& url) {
415 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 414 DCHECK(thread_checker_.CalledOnValidThread());
416 415
417 BrowserThread::PostTask( 416 bits_task_runner_->PostTask(
418 BrowserThread::FILE,
419 FROM_HERE, 417 FROM_HERE,
420 base::Bind( 418 base::Bind(
421 &BackgroundDownloader::BeginDownload, base::Unretained(this), url)); 419 &BackgroundDownloader::BeginDownload, base::Unretained(this), url));
422 } 420 }
423 421
424 // Called once when this class is asked to do a download. Creates or opens 422 // Called once when this class is asked to do a download. Creates or opens
425 // an existing bits job, hooks up the notifications, and starts the timer. 423 // an existing bits job, hooks up the notifications, and starts the timer.
426 void BackgroundDownloader::BeginDownload(const GURL& url) { 424 void BackgroundDownloader::BeginDownload(const GURL& url) {
427 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 425 DCHECK(bits_task_runner_->RunsTasksOnCurrentThread());
428 426
429 DCHECK(!timer_); 427 DCHECK(!timer_);
430 428
431 is_completed_ = false; 429 is_completed_ = false;
432 download_start_time_ = base::Time::Now(); 430 download_start_time_ = base::Time::Now();
433 job_stuck_begin_time_ = download_start_time_; 431 job_stuck_begin_time_ = download_start_time_;
434 432
435 HRESULT hr = QueueBitsJob(url); 433 HRESULT hr = QueueBitsJob(url);
436 if (FAILED(hr)) { 434 if (FAILED(hr)) {
437 EndDownload(hr); 435 EndDownload(hr);
438 return; 436 return;
439 } 437 }
440 438
441 // A repeating timer retains the user task. This timer can be stopped and 439 // A repeating timer retains the user task. This timer can be stopped and
442 // reset multiple times. 440 // reset multiple times.
443 timer_.reset(new base::RepeatingTimer<BackgroundDownloader>); 441 timer_.reset(new base::RepeatingTimer<BackgroundDownloader>);
444 timer_->Start(FROM_HERE, 442 timer_->Start(FROM_HERE,
445 base::TimeDelta::FromSeconds(kJobPollingIntervalSec), 443 base::TimeDelta::FromSeconds(kJobPollingIntervalSec),
446 this, 444 this,
447 &BackgroundDownloader::OnDownloading); 445 &BackgroundDownloader::OnDownloading);
448 } 446 }
449 447
450 // Called any time the timer fires. 448 // Called any time the timer fires.
451 void BackgroundDownloader::OnDownloading() { 449 void BackgroundDownloader::OnDownloading() {
452 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 450 DCHECK(bits_task_runner_->RunsTasksOnCurrentThread());
453 451
454 DCHECK(job_); 452 DCHECK(job_);
455 453
456 DCHECK(!is_completed_); 454 DCHECK(!is_completed_);
457 if (is_completed_) 455 if (is_completed_)
458 return; 456 return;
459 457
460 BG_JOB_STATE job_state = BG_JOB_STATE_ERROR; 458 BG_JOB_STATE job_state = BG_JOB_STATE_ERROR;
461 HRESULT hr = job_->GetState(&job_state); 459 HRESULT hr = job_->GetState(&job_state);
462 if (FAILED(hr)) { 460 if (FAILED(hr)) {
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
498 break; 496 break;
499 497
500 default: 498 default:
501 break; 499 break;
502 } 500 }
503 } 501 }
504 502
505 // Completes the BITS download, picks up the file path of the response, and 503 // Completes the BITS download, picks up the file path of the response, and
506 // notifies the CrxDownloader. The function should be called only once. 504 // notifies the CrxDownloader. The function should be called only once.
507 void BackgroundDownloader::EndDownload(HRESULT error) { 505 void BackgroundDownloader::EndDownload(HRESULT error) {
508 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 506 DCHECK(bits_task_runner_->RunsTasksOnCurrentThread());
509 507
510 DCHECK(!is_completed_); 508 DCHECK(!is_completed_);
511 is_completed_ = true; 509 is_completed_ = true;
512 510
513 timer_.reset(); 511 timer_.reset();
514 512
515 const base::Time download_end_time(base::Time::Now()); 513 const base::Time download_end_time(base::Time::Now());
516 const base::TimeDelta download_time = 514 const base::TimeDelta download_time =
517 download_end_time >= download_start_time_ 515 download_end_time >= download_start_time_
518 ? download_end_time - download_start_time_ 516 ? download_end_time - download_start_time_
(...skipping 26 matching lines...) Expand all
545 download_metrics.error = error_to_report; 543 download_metrics.error = error_to_report;
546 download_metrics.downloaded_bytes = downloaded_bytes; 544 download_metrics.downloaded_bytes = downloaded_bytes;
547 download_metrics.total_bytes = total_bytes; 545 download_metrics.total_bytes = total_bytes;
548 download_metrics.download_time_ms = download_time.InMilliseconds(); 546 download_metrics.download_time_ms = download_time.InMilliseconds();
549 547
550 Result result; 548 Result result;
551 result.error = error_to_report; 549 result.error = error_to_report;
552 result.response = response_; 550 result.response = response_;
553 result.downloaded_bytes = downloaded_bytes; 551 result.downloaded_bytes = downloaded_bytes;
554 result.total_bytes = total_bytes; 552 result.total_bytes = total_bytes;
555 BrowserThread::PostTask(BrowserThread::UI, 553 main_task_runner_->PostTask(
556 FROM_HERE, 554 FROM_HERE,
557 base::Bind(&BackgroundDownloader::OnDownloadComplete, 555 base::Bind(&BackgroundDownloader::OnDownloadComplete,
558 base::Unretained(this), 556 base::Unretained(this),
559 is_handled, 557 is_handled,
560 result, 558 result,
561 download_metrics)); 559 download_metrics));
562 560
563 // Once the task is posted to the the UI thread, this object may be deleted 561 // Once the task is posted to the the main thread, this object may be deleted
564 // by its owner. It is not safe to access members of this object on the 562 // by its owner. It is not safe to access members of this object on the
565 // FILE thread from this point on. The timer is stopped and all BITS 563 // task runner from this point on. The timer is stopped and all BITS
566 // interface pointers have been released. 564 // interface pointers have been released.
567 } 565 }
568 566
569 // Called when the BITS job has been transferred successfully. Completes the 567 // Called when the BITS job has been transferred successfully. Completes the
570 // BITS job by removing it from the BITS queue and making the download 568 // BITS job by removing it from the BITS queue and making the download
571 // available to the caller. 569 // available to the caller.
572 void BackgroundDownloader::OnStateTransferred() { 570 void BackgroundDownloader::OnStateTransferred() {
573 EndDownload(CompleteJob()); 571 EndDownload(CompleteJob());
574 } 572 }
575 573
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
618 int64 downloaded_bytes = -1; 616 int64 downloaded_bytes = -1;
619 int64 total_bytes = -1; 617 int64 total_bytes = -1;
620 HRESULT hr = GetJobByteCount(job_, &downloaded_bytes, &total_bytes); 618 HRESULT hr = GetJobByteCount(job_, &downloaded_bytes, &total_bytes);
621 if (FAILED(hr)) 619 if (FAILED(hr))
622 return; 620 return;
623 621
624 Result result; 622 Result result;
625 result.downloaded_bytes = downloaded_bytes; 623 result.downloaded_bytes = downloaded_bytes;
626 result.total_bytes = total_bytes; 624 result.total_bytes = total_bytes;
627 625
628 BrowserThread::PostTask(BrowserThread::UI, 626 main_task_runner_->PostTask(
629 FROM_HERE, 627 FROM_HERE,
630 base::Bind(&BackgroundDownloader::OnDownloadProgress, 628 base::Bind(&BackgroundDownloader::OnDownloadProgress,
631 base::Unretained(this), 629 base::Unretained(this),
632 result)); 630 result));
633 } 631 }
634 632
635 // Called when the download was cancelled. Since the observer should have 633 // Called when the download was cancelled. Since the observer should have
636 // been disconnected by now, this notification must not be seen. 634 // been disconnected by now, this notification must not be seen.
637 void BackgroundDownloader::OnStateCancelled() { 635 void BackgroundDownloader::OnStateCancelled() {
638 EndDownload(E_UNEXPECTED); 636 EndDownload(E_UNEXPECTED);
639 } 637 }
640 638
641 // Called when the download was completed. Same as above. 639 // Called when the download was completed. Same as above.
642 void BackgroundDownloader::OnStateAcknowledged() { 640 void BackgroundDownloader::OnStateAcknowledged() {
643 EndDownload(E_UNEXPECTED); 641 EndDownload(E_UNEXPECTED);
644 } 642 }
645 643
646 // Creates or opens a job for the given url and queues it up. Tries to 644 // Creates or opens a job for the given url and queues it up. Tries to
647 // install a job observer but continues on if an observer can't be set up. 645 // install a job observer but continues on if an observer can't be set up.
648 HRESULT BackgroundDownloader::QueueBitsJob(const GURL& url) { 646 HRESULT BackgroundDownloader::QueueBitsJob(const GURL& url) {
649 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); 647 DCHECK(bits_task_runner_->RunsTasksOnCurrentThread());
650 648
651 HRESULT hr = S_OK; 649 HRESULT hr = S_OK;
652 if (bits_manager_ == NULL) { 650 if (bits_manager_ == NULL) {
653 hr = GetBitsManager(bits_manager_.Receive()); 651 hr = GetBitsManager(bits_manager_.Receive());
654 if (FAILED(hr)) 652 if (FAILED(hr))
655 return hr; 653 return hr;
656 } 654 }
657 655
658 hr = CreateOrOpenJob(url); 656 hr = CreateOrOpenJob(url);
659 if (FAILED(hr)) 657 if (FAILED(hr))
(...skipping 99 matching lines...) Expand 10 before | Expand all | Expand 10 after
759 // must match as a job only contains one file. 757 // must match as a job only contains one file.
760 DCHECK(progress.Completed); 758 DCHECK(progress.Completed);
761 DCHECK_EQ(progress.BytesTotal, progress.BytesTransferred); 759 DCHECK_EQ(progress.BytesTotal, progress.BytesTransferred);
762 760
763 response_ = base::FilePath(local_name); 761 response_ = base::FilePath(local_name);
764 762
765 return S_OK; 763 return S_OK;
766 } 764 }
767 765
768 } // namespace component_updater 766 } // namespace component_updater
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698