Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/component_updater_service.h" | 5 #include "chrome/browser/component_updater/component_updater_service.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/at_exit.h" | 10 #include "base/at_exit.h" |
| (...skipping 326 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 337 running_ = false; | 337 running_ = false; |
| 338 timer_.Stop(); | 338 timer_.Stop(); |
| 339 return kOk; | 339 return kOk; |
| 340 } | 340 } |
| 341 | 341 |
| 342 // This function sets the timer which will call ProcessPendingItems() there | 342 // This function sets the timer which will call ProcessPendingItems() there |
| 343 // are two kind of waits, the short one (with step_delay = true) and the | 343 // are two kind of waits, the short one (with step_delay = true) and the |
| 344 // long one. | 344 // long one. |
| 345 void CrxUpdateService::ScheduleNextRun(bool step_delay) { | 345 void CrxUpdateService::ScheduleNextRun(bool step_delay) { |
| 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 346 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 347 DCHECK(url_fetcher_.get() == NULL); | |
| 347 CHECK(!timer_.IsRunning()); | 348 CHECK(!timer_.IsRunning()); |
| 348 // It could be the case that Stop() had been called while a url request | 349 // It could be the case that Stop() had been called while a url request |
| 349 // or unpacking was in flight, if so we arrive here but |running_| is | 350 // or unpacking was in flight, if so we arrive here but |running_| is |
| 350 // false. In that case do not loop again. | 351 // false. In that case do not loop again. |
| 351 if (!running_) | 352 if (!running_) |
| 352 return; | 353 return; |
| 353 | 354 |
| 355 int64 delay = step_delay ? config_->StepDelay() : config_->NextCheckDelay(); | |
| 356 | |
| 354 if (!step_delay) { | 357 if (!step_delay) { |
| 355 NotificationService::current()->Notify( | 358 NotificationService::current()->Notify( |
| 356 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, | 359 chrome::NOTIFICATION_COMPONENT_UPDATER_SLEEPING, |
| 357 Source<ComponentUpdateService>(this), | 360 Source<ComponentUpdateService>(this), |
| 358 NotificationService::NoDetails()); | 361 NotificationService::NoDetails()); |
| 359 // Zero is only used for unit tests. | 362 // Zero is only used for unit tests. |
| 360 if (0 == config_->NextCheckDelay()) | 363 if (0 == delay) |
| 361 return; | 364 return; |
| 362 } | 365 } |
| 363 | 366 |
| 364 int64 delay = step_delay ? config_->StepDelay() : config_->NextCheckDelay(); | |
| 365 timer_.Start(base::TimeDelta::FromSeconds(delay), | 367 timer_.Start(base::TimeDelta::FromSeconds(delay), |
| 366 this, &CrxUpdateService::ProcessPendingItems); | 368 this, &CrxUpdateService::ProcessPendingItems); |
| 367 } | 369 } |
| 368 | 370 |
| 369 // Given a extension-like component id, find the associated component. | 371 // Given a extension-like component id, find the associated component. |
| 370 CrxUpdateItem* CrxUpdateService::FindUpdateItemById(const std::string& id) { | 372 CrxUpdateItem* CrxUpdateService::FindUpdateItemById(const std::string& id) { |
| 371 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 373 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 372 CrxUpdateItem::FindById finder(id); | 374 CrxUpdateItem::FindById finder(id); |
| 373 UpdateItems::iterator it = std::find_if(work_items_.begin(), | 375 UpdateItems::iterator it = std::find_if(work_items_.begin(), |
| 374 work_items_.end(), | 376 work_items_.end(), |
| (...skipping 107 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 482 | 484 |
| 483 // Next we can go back to components we already checked, here | 485 // Next we can go back to components we already checked, here |
| 484 // we can also batch them in a single url request, as long as | 486 // we can also batch them in a single url request, as long as |
| 485 // we have not checked them recently. | 487 // we have not checked them recently. |
| 486 base::TimeDelta min_delta_time = | 488 base::TimeDelta min_delta_time = |
| 487 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); | 489 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); |
| 488 | 490 |
| 489 for (UpdateItems::const_iterator it = work_items_.begin(); | 491 for (UpdateItems::const_iterator it = work_items_.begin(); |
| 490 it != work_items_.end(); ++it) { | 492 it != work_items_.end(); ++it) { |
| 491 CrxUpdateItem* item = *it; | 493 CrxUpdateItem* item = *it; |
| 492 if ((item->status != CrxUpdateItem::kNoUpdate) || | 494 if ((item->status != CrxUpdateItem::kNoUpdate) && |
| 493 (item->status != CrxUpdateItem::kUpToDate)) | 495 (item->status != CrxUpdateItem::kUpToDate)) |
| 494 continue; | 496 continue; |
| 495 base::TimeDelta delta = base::Time::Now() - item->last_check; | 497 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 496 if (delta < min_delta_time) | 498 if (delta < min_delta_time) |
| 497 continue; | 499 continue; |
| 498 if (!AddItemToUpdateCheck(item, &query)) | 500 if (!AddItemToUpdateCheck(item, &query)) |
| 499 break; | 501 break; |
| 500 } | 502 } |
| 501 // Finally, we check components that we already updated. | 503 // Finally, we check components that we already updated. |
| 502 for (UpdateItems::const_iterator it = work_items_.begin(); | 504 for (UpdateItems::const_iterator it = work_items_.begin(); |
| (...skipping 22 matching lines...) Expand all Loading... | |
| 525 } | 527 } |
| 526 | 528 |
| 527 // Caled when we got a response from the update server. It consists of an xml | 529 // Caled when we got a response from the update server. It consists of an xml |
| 528 // document following the omaha update scheme. | 530 // document following the omaha update scheme. |
| 529 void CrxUpdateService::OnURLFetchComplete(const URLFetcher* source, | 531 void CrxUpdateService::OnURLFetchComplete(const URLFetcher* source, |
| 530 UpdateContext*) { | 532 UpdateContext*) { |
| 531 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 533 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 532 if (FetchSuccess(*source)) { | 534 if (FetchSuccess(*source)) { |
| 533 std::string xml; | 535 std::string xml; |
| 534 source->GetResponseAsString(&xml); | 536 source->GetResponseAsString(&xml); |
| 537 url_fetcher_.reset(); | |
|
asargent_no_longer_on_chrome
2011/08/09 17:56:19
Not a big deal, but it looks a little weird to res
cpu_(ooo_6.6-7.5)
2011/08/09 20:21:53
I would like to do that but then
I can't do sourc
| |
| 535 ParseManifest(xml); | 538 ParseManifest(xml); |
| 536 } else { | 539 } else { |
| 540 url_fetcher_.reset(); | |
| 537 CrxUpdateService::OnParseUpdateManifestFailed("network error"); | 541 CrxUpdateService::OnParseUpdateManifestFailed("network error"); |
| 538 } | 542 } |
| 539 url_fetcher_.reset(); | |
| 540 } | 543 } |
| 541 | 544 |
| 542 // Parsing the manifest is either done right now for tests or in a sandboxed | 545 // Parsing the manifest is either done right now for tests or in a sandboxed |
| 543 // process for the production environment. This mitigates the case where an | 546 // process for the production environment. This mitigates the case where an |
| 544 // attacker was able to feed us a malicious xml string. | 547 // attacker was able to feed us a malicious xml string. |
| 545 void CrxUpdateService::ParseManifest(const std::string& xml) { | 548 void CrxUpdateService::ParseManifest(const std::string& xml) { |
| 546 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 549 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 547 if (config_->InProcess()) { | 550 if (config_->InProcess()) { |
| 548 UpdateManifest manifest; | 551 UpdateManifest manifest; |
| 549 if (!manifest.Parse(xml)) { | 552 if (!manifest.Parse(xml)) { |
| (...skipping 20 matching lines...) Expand all Loading... | |
| 570 std::vector<UpdateManifest::Result>::const_iterator it; | 573 std::vector<UpdateManifest::Result>::const_iterator it; |
| 571 for (it = results.list.begin(); it != results.list.end(); ++it) { | 574 for (it = results.list.begin(); it != results.list.end(); ++it) { |
| 572 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); | 575 CrxUpdateItem* crx = FindUpdateItemById(it->extension_id); |
| 573 if (!crx) | 576 if (!crx) |
| 574 continue; | 577 continue; |
| 575 | 578 |
| 576 if (crx->status != CrxUpdateItem::kChecking) | 579 if (crx->status != CrxUpdateItem::kChecking) |
| 577 continue; // Not updating this component now. | 580 continue; // Not updating this component now. |
| 578 | 581 |
| 579 if (it->version.empty()) { | 582 if (it->version.empty()) { |
| 583 // No version means no update available. | |
| 580 crx->status = CrxUpdateItem::kNoUpdate; | 584 crx->status = CrxUpdateItem::kNoUpdate; |
| 581 continue; // No version means no update available. | 585 continue; |
| 582 } | 586 } |
| 583 if (!IsVersionNewer(crx->component.version, it->version)) { | 587 if (!IsVersionNewer(crx->component.version, it->version)) { |
| 588 // Our component is up to date. | |
| 584 crx->status = CrxUpdateItem::kUpToDate; | 589 crx->status = CrxUpdateItem::kUpToDate; |
| 585 continue; // Our component is up to date. | 590 continue; |
| 586 } | 591 } |
| 587 if (!it->browser_min_version.empty()) { | 592 if (!it->browser_min_version.empty()) { |
| 588 if (IsVersionNewer(chrome_version_, it->browser_min_version)) | 593 if (IsVersionNewer(chrome_version_, it->browser_min_version)) { |
| 589 continue; // Does not apply for this version. | 594 // Does not apply for this chrome version. |
| 595 crx->status = CrxUpdateItem::kNoUpdate; | |
| 596 continue; | |
| 597 } | |
| 590 } | 598 } |
| 591 // All test passed. Queue an upgrade for this component and fire the | 599 // All test passed. Queue an upgrade for this component and fire the |
| 592 // notifications. | 600 // notifications. |
| 593 crx->crx_url = it->crx_url; | 601 crx->crx_url = it->crx_url; |
| 594 crx->status = CrxUpdateItem::kCanUpdate; | 602 crx->status = CrxUpdateItem::kCanUpdate; |
| 595 ++update_pending; | 603 ++update_pending; |
| 596 | 604 |
| 597 NotificationService::current()->Notify( | 605 NotificationService::current()->Notify( |
| 598 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, | 606 chrome::NOTIFICATION_COMPONENT_UPDATE_FOUND, |
| 599 Source<std::string>(&crx->id), | 607 Source<std::string>(&crx->id), |
| 600 NotificationService::NoDetails()); | 608 NotificationService::NoDetails()); |
| 601 } | 609 } |
| 610 | |
| 611 // All the components that are not mentioned in the manifest we | |
| 612 // consider them up to date. | |
| 613 ChangeItemStatus(CrxUpdateItem::kChecking, CrxUpdateItem::kUpToDate); | |
| 614 | |
| 602 // If there are updates pending we do a short wait. | 615 // If there are updates pending we do a short wait. |
| 603 ScheduleNextRun(update_pending ? true : false); | 616 ScheduleNextRun(update_pending ? true : false); |
| 604 } | 617 } |
| 605 | 618 |
| 606 void CrxUpdateService::OnParseUpdateManifestFailed( | 619 void CrxUpdateService::OnParseUpdateManifestFailed( |
| 607 const std::string& error_message) { | 620 const std::string& error_message) { |
| 608 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 621 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 609 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, | 622 size_t count = ChangeItemStatus(CrxUpdateItem::kChecking, |
| 610 CrxUpdateItem::kNoUpdate); | 623 CrxUpdateItem::kNoUpdate); |
| 611 DCHECK_GT(count, 0ul); | 624 DCHECK_GT(count, 0ul); |
| 612 ScheduleNextRun(false); | 625 ScheduleNextRun(false); |
| 613 } | 626 } |
| 614 | 627 |
| 615 // Called when the CRX package has been downloaded to a temporary location. | 628 // Called when the CRX package has been downloaded to a temporary location. |
| 616 // Here we fire the notifications and schedule the component-specific installer | 629 // Here we fire the notifications and schedule the component-specific installer |
| 617 // to be called in the file thread. | 630 // to be called in the file thread. |
| 618 void CrxUpdateService::OnURLFetchComplete(const URLFetcher* source, | 631 void CrxUpdateService::OnURLFetchComplete(const URLFetcher* source, |
| 619 CRXContext* context) { | 632 CRXContext* context) { |
| 620 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 633 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 621 base::PlatformFileError error_code; | 634 base::PlatformFileError error_code; |
| 622 | 635 |
| 623 if (source->FileErrorOccurred(&error_code) || !FetchSuccess(*source)) { | 636 if (source->FileErrorOccurred(&error_code) || !FetchSuccess(*source)) { |
| 624 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, | 637 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, |
| 625 CrxUpdateItem::kNoUpdate); | 638 CrxUpdateItem::kNoUpdate); |
| 626 DCHECK_EQ(count, 1ul); | 639 DCHECK_EQ(count, 1ul); |
| 640 url_fetcher_.reset(); | |
| 627 ScheduleNextRun(false); | 641 ScheduleNextRun(false); |
| 628 } else { | 642 } else { |
| 629 FilePath temp_crx_path; | 643 FilePath temp_crx_path; |
| 630 CHECK(source->GetResponseAsFilePath(true, &temp_crx_path)); | 644 CHECK(source->GetResponseAsFilePath(true, &temp_crx_path)); |
| 631 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, | 645 size_t count = ChangeItemStatus(CrxUpdateItem::kDownloading, |
| 632 CrxUpdateItem::kUpdating); | 646 CrxUpdateItem::kUpdating); |
| 633 DCHECK_EQ(count, 1ul); | 647 DCHECK_EQ(count, 1ul); |
| 648 url_fetcher_.reset(); | |
| 649 | |
| 634 NotificationService::current()->Notify( | 650 NotificationService::current()->Notify( |
| 635 chrome::NOTIFICATION_COMPONENT_UPDATE_READY, | 651 chrome::NOTIFICATION_COMPONENT_UPDATE_READY, |
| 636 Source<std::string>(&context->id), | 652 Source<std::string>(&context->id), |
| 637 NotificationService::NoDetails()); | 653 NotificationService::NoDetails()); |
| 638 | 654 |
| 639 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, | 655 BrowserThread::PostDelayedTask(BrowserThread::FILE, FROM_HERE, |
| 640 NewRunnableMethod(this, &CrxUpdateService::Install, | 656 NewRunnableMethod(this, &CrxUpdateService::Install, |
| 641 context, | 657 context, |
| 642 temp_crx_path), | 658 temp_crx_path), |
| 643 config_->StepDelay()); | 659 config_->StepDelay()); |
| 644 } | 660 } |
| 645 | |
| 646 url_fetcher_.reset(); | |
| 647 } | 661 } |
| 648 | 662 |
| 649 // Install consists of digital signature verification, unpacking and then | 663 // Install consists of digital signature verification, unpacking and then |
| 650 // calling the component specific installer. All that is handled by the | 664 // calling the component specific installer. All that is handled by the |
| 651 // |unpacker|. If there is an error this function is in charge of deleting | 665 // |unpacker|. If there is an error this function is in charge of deleting |
| 652 // the files created. | 666 // the files created. |
| 653 void CrxUpdateService::Install(const CRXContext* context, | 667 void CrxUpdateService::Install(const CRXContext* context, |
| 654 const FilePath& crx_path) { | 668 const FilePath& crx_path) { |
| 655 // This function owns the |crx_path| and the |context| object. | 669 // This function owns the |crx_path| and the |context| object. |
| 656 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); | 670 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::FILE)); |
| (...skipping 23 matching lines...) Expand all Loading... | |
| 680 } | 694 } |
| 681 | 695 |
| 682 // The component update factory. Using the component updater as a singleton | 696 // The component update factory. Using the component updater as a singleton |
| 683 // is the job of the browser process. | 697 // is the job of the browser process. |
| 684 ComponentUpdateService* ComponentUpdateServiceFactory( | 698 ComponentUpdateService* ComponentUpdateServiceFactory( |
| 685 ComponentUpdateService::Configurator* config) { | 699 ComponentUpdateService::Configurator* config) { |
| 686 DCHECK(config); | 700 DCHECK(config); |
| 687 return new CrxUpdateService(config); | 701 return new CrxUpdateService(config); |
| 688 } | 702 } |
| 689 | 703 |
| OLD | NEW |