Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 "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 235 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 246 class CrxUpdateService : public ComponentUpdateService { | 246 class CrxUpdateService : public ComponentUpdateService { |
| 247 public: | 247 public: |
| 248 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); | 248 explicit CrxUpdateService(ComponentUpdateService::Configurator* config); |
| 249 | 249 |
| 250 virtual ~CrxUpdateService(); | 250 virtual ~CrxUpdateService(); |
| 251 | 251 |
| 252 // Overrides for ComponentUpdateService. | 252 // Overrides for ComponentUpdateService. |
| 253 virtual Status Start() OVERRIDE; | 253 virtual Status Start() OVERRIDE; |
| 254 virtual Status Stop() OVERRIDE; | 254 virtual Status Stop() OVERRIDE; |
| 255 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; | 255 virtual Status RegisterComponent(const CrxComponent& component) OVERRIDE; |
| 256 virtual Status PingUpdateCheck(const CrxComponent& component) OVERRIDE; | |
| 256 | 257 |
| 257 // The only purpose of this class is to forward the | 258 // The only purpose of this class is to forward the |
| 258 // UtilityProcessHostClient callbacks so CrxUpdateService does | 259 // UtilityProcessHostClient callbacks so CrxUpdateService does |
| 259 // not have to derive from it because that is refcounted. | 260 // not have to derive from it because that is refcounted. |
| 260 class ManifestParserBridge : public UtilityProcessHostClient { | 261 class ManifestParserBridge : public UtilityProcessHostClient { |
| 261 public: | 262 public: |
| 262 explicit ManifestParserBridge(CrxUpdateService* service) | 263 explicit ManifestParserBridge(CrxUpdateService* service) |
| 263 : service_(service) {} | 264 : service_(service) {} |
| 264 | 265 |
| 265 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { | 266 virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE { |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 const UpdateManifest::Results& results); | 317 const UpdateManifest::Results& results); |
| 317 | 318 |
| 318 // See ManifestParserBridge. | 319 // See ManifestParserBridge. |
| 319 void OnParseUpdateManifestFailed( | 320 void OnParseUpdateManifestFailed( |
| 320 const std::string& error_message); | 321 const std::string& error_message); |
| 321 | 322 |
| 322 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); | 323 bool AddItemToUpdateCheck(CrxUpdateItem* item, std::string* query); |
| 323 | 324 |
| 324 void ProcessPendingItems(); | 325 void ProcessPendingItems(); |
| 325 | 326 |
| 327 typedef std::vector<CrxUpdateItem*> UpdateItems; | |
| 328 bool ProcessWorkItems(const UpdateItems& work_items); | |
| 329 | |
| 326 void ScheduleNextRun(bool step_delay); | 330 void ScheduleNextRun(bool step_delay); |
| 327 | 331 |
| 328 void ParseManifest(const std::string& xml); | 332 void ParseManifest(const std::string& xml); |
| 329 | 333 |
| 330 void Install(const CRXContext* context, const FilePath& crx_path); | 334 void Install(const CRXContext* context, const FilePath& crx_path); |
| 331 | 335 |
| 332 void DoneInstalling(const std::string& component_id, | 336 void DoneInstalling(const std::string& component_id, |
| 333 ComponentUnpacker::Error error); | 337 ComponentUnpacker::Error error); |
| 334 | 338 |
| 335 size_t ChangeItemStatus(CrxUpdateItem::Status from, | 339 size_t ChangeItemStatus(CrxUpdateItem::Status from, |
| 336 CrxUpdateItem::Status to); | 340 CrxUpdateItem::Status to); |
| 337 | 341 |
| 338 CrxUpdateItem* FindUpdateItemById(const std::string& id); | 342 CrxUpdateItem* FindUpdateItemById(const std::string& id); |
| 339 | 343 |
| 340 scoped_ptr<Config> config_; | 344 scoped_ptr<Config> config_; |
| 341 | 345 |
| 342 scoped_ptr<net::URLFetcher> url_fetcher_; | 346 scoped_ptr<net::URLFetcher> url_fetcher_; |
| 343 | 347 |
| 344 typedef std::vector<CrxUpdateItem*> UpdateItems; | |
| 345 UpdateItems work_items_; | 348 UpdateItems work_items_; |
| 346 | 349 |
| 347 base::OneShotTimer<CrxUpdateService> timer_; | 350 base::OneShotTimer<CrxUpdateService> timer_; |
| 348 | 351 |
| 349 Version chrome_version_; | 352 Version chrome_version_; |
| 350 | 353 |
| 351 bool running_; | 354 bool running_; |
| 352 | 355 |
| 353 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService); | 356 DISALLOW_COPY_AND_ASSIGN(CrxUpdateService); |
| 354 }; | 357 }; |
| (...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 496 std::string* query) { | 499 std::string* query) { |
| 497 if (!AddQueryString(item->id, | 500 if (!AddQueryString(item->id, |
| 498 item->component.version.GetString(), | 501 item->component.version.GetString(), |
| 499 config_->UrlSizeLimit(), query)) | 502 config_->UrlSizeLimit(), query)) |
| 500 return false; | 503 return false; |
| 501 item->status = CrxUpdateItem::kChecking; | 504 item->status = CrxUpdateItem::kChecking; |
| 502 item->last_check = base::Time::Now(); | 505 item->last_check = base::Time::Now(); |
| 503 return true; | 506 return true; |
| 504 } | 507 } |
| 505 | 508 |
| 506 // Here is where the work gets scheduled. Given that our |work_items_| list | 509 // Here is where the work gets scheduled. |
| 510 void CrxUpdateService::ProcessPendingItems() { | |
| 511 if (!ProcessWorkItems(work_items_)) { | |
| 512 // No components to update. Next check after the long sleep. | |
| 513 ScheduleNextRun(false); | |
| 514 } | |
| 515 } | |
| 516 | |
| 517 // Start the process of checking for an update, for a particular component | |
| 518 // that was previously registered. If the component does not exist return | |
| 519 // kError, otherwise kOk. | |
| 520 ComponentUpdateService::Status CrxUpdateService::PingUpdateCheck( | |
| 521 const CrxComponent& component) { | |
| 522 if (component.pk_hash.empty() || | |
| 523 !component.version.IsValid() || | |
| 524 !component.installer) | |
| 525 return kError; | |
| 526 | |
| 527 std::string id = | |
| 528 HexStringToID(StringToLowerASCII(base::HexEncode(&component.pk_hash[0], | |
| 529 component.pk_hash.size()/2))); | |
| 530 CrxUpdateItem* uit; | |
| 531 uit = FindUpdateItemById(id); | |
| 532 if (!uit) | |
| 533 return kError; | |
| 534 | |
| 535 UpdateItems one_item; | |
| 536 one_item.push_back(uit); | |
| 537 | |
| 538 // The timer is may already be running when we do this ping. | |
| 539 // If the timer is running, cancel the currently scheduled timer, | |
| 540 // but remember the remaining time delta so that we can reset the timer | |
| 541 // to something comparable if there is nothing to do. | |
| 542 base::TimeDelta remaining_delay; | |
| 543 bool remaining_delay_set = false; | |
| 544 if (timer_.IsRunning()) { | |
| 545 remaining_delay = timer_.desired_run_time() - base::TimeTicks::Now(); | |
| 546 remaining_delay_set = true; | |
| 547 timer_.Stop(); | |
| 548 } | |
|
jvoung (off chromium)
2013/01/30 02:20:21
Good point about having fetches or installs in fli
| |
| 549 | |
| 550 if (!ProcessWorkItems(one_item)) { | |
| 551 // If there is work to do, the timer is re-scheduled by a work step. | |
| 552 // However, if there is nothing to actually do, we must schedule the | |
| 553 // timer here. | |
| 554 bool use_step_delay; | |
| 555 if (remaining_delay_set) { | |
| 556 use_step_delay = | |
| 557 remaining_delay < base::TimeDelta::FromSeconds(config_->StepDelay()); | |
| 558 } else { | |
| 559 // Guess that it is not a step_delay. | |
| 560 use_step_delay = false; | |
| 561 } | |
| 562 ScheduleNextRun(use_step_delay); | |
| 563 } | |
| 564 return kOk; | |
| 565 } | |
| 566 | |
| 567 // Here is where the work gets scheduled. Given that our |work_items| list | |
| 507 // is expected to be ten or less items, we simply loop several times. | 568 // is expected to be ten or less items, we simply loop several times. |
| 508 void CrxUpdateService::ProcessPendingItems() { | 569 // Returns |true| if there is work to be done. |
| 570 bool CrxUpdateService::ProcessWorkItems(const UpdateItems& work_items) { | |
| 509 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 571 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 510 // First check for ready upgrades and do one. The first | 572 // First check for ready upgrades and do one. The first |
| 511 // step is to fetch the crx package. | 573 // step is to fetch the crx package. |
| 512 for (UpdateItems::const_iterator it = work_items_.begin(); | 574 for (UpdateItems::const_iterator it = work_items.begin(); |
| 513 it != work_items_.end(); ++it) { | 575 it != work_items.end(); ++it) { |
| 514 CrxUpdateItem* item = *it; | 576 CrxUpdateItem* item = *it; |
| 515 if (item->status != CrxUpdateItem::kCanUpdate) | 577 if (item->status != CrxUpdateItem::kCanUpdate) |
| 516 continue; | 578 continue; |
| 517 // Found component to update, start the process. | 579 // Found component to update, start the process. |
| 518 item->status = CrxUpdateItem::kDownloading; | 580 item->status = CrxUpdateItem::kDownloading; |
| 519 CRXContext* context = new CRXContext; | 581 CRXContext* context = new CRXContext; |
| 520 context->pk_hash = item->component.pk_hash; | 582 context->pk_hash = item->component.pk_hash; |
| 521 context->id = item->id; | 583 context->id = item->id; |
| 522 context->installer = item->component.installer; | 584 context->installer = item->component.installer; |
| 523 url_fetcher_.reset(net::URLFetcher::Create( | 585 url_fetcher_.reset(net::URLFetcher::Create( |
| 524 0, item->crx_url, net::URLFetcher::GET, | 586 0, item->crx_url, net::URLFetcher::GET, |
| 525 MakeContextDelegate(this, context))); | 587 MakeContextDelegate(this, context))); |
| 526 StartFetch(url_fetcher_.get(), config_->RequestContext(), true); | 588 StartFetch(url_fetcher_.get(), config_->RequestContext(), true); |
| 527 return; | 589 return true; |
| 528 } | 590 } |
| 529 | 591 |
| 530 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) { | 592 for (size_t ix = 0; ix != arraysize(kManifestSources); ++ix) { |
| 531 const CrxComponent::UrlSource manifest_source = kManifestSources[ix]; | 593 const CrxComponent::UrlSource manifest_source = kManifestSources[ix]; |
| 532 | 594 |
| 533 std::string query; | 595 std::string query; |
| 534 // If no pending upgrades, we check if there are new components we have not | 596 // If no pending upgrades, we check if there are new components we have not |
| 535 // checked against the server. We can batch some in a single url request. | 597 // checked against the server. We can batch some in a single url request. |
| 536 for (UpdateItems::const_iterator it = work_items_.begin(); | 598 for (UpdateItems::const_iterator it = work_items.begin(); |
| 537 it != work_items_.end(); ++it) { | 599 it != work_items.end(); ++it) { |
| 538 CrxUpdateItem* item = *it; | 600 CrxUpdateItem* item = *it; |
| 539 if (item->status != CrxUpdateItem::kNew) | 601 if (item->status != CrxUpdateItem::kNew) |
| 540 continue; | 602 continue; |
| 541 if (item->component.source != manifest_source) | 603 if (item->component.source != manifest_source) |
| 542 continue; | 604 continue; |
| 543 if (!AddItemToUpdateCheck(item, &query)) | 605 if (!AddItemToUpdateCheck(item, &query)) |
| 544 break; | 606 break; |
| 545 } | 607 } |
| 546 | 608 |
| 547 // Next we can go back to components we already checked, here | 609 // Next we can go back to components we already checked, here |
| 548 // we can also batch them in a single url request, as long as | 610 // we can also batch them in a single url request, as long as |
| 549 // we have not checked them recently. | 611 // we have not checked them recently. |
| 550 const base::TimeDelta min_delta_time = | 612 const base::TimeDelta min_delta_time = |
| 551 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); | 613 base::TimeDelta::FromSeconds(config_->MinimumReCheckWait()); |
| 552 | 614 |
| 553 for (UpdateItems::const_iterator it = work_items_.begin(); | 615 for (UpdateItems::const_iterator it = work_items.begin(); |
| 554 it != work_items_.end(); ++it) { | 616 it != work_items.end(); ++it) { |
| 555 CrxUpdateItem* item = *it; | 617 CrxUpdateItem* item = *it; |
| 556 if ((item->status != CrxUpdateItem::kNoUpdate) && | 618 if ((item->status != CrxUpdateItem::kNoUpdate) && |
| 557 (item->status != CrxUpdateItem::kUpToDate)) | 619 (item->status != CrxUpdateItem::kUpToDate)) |
| 558 continue; | 620 continue; |
| 559 if (item->component.source != manifest_source) | 621 if (item->component.source != manifest_source) |
| 560 continue; | 622 continue; |
| 561 base::TimeDelta delta = base::Time::Now() - item->last_check; | 623 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 562 if (delta < min_delta_time) | 624 if (delta < min_delta_time) |
| 563 continue; | 625 continue; |
| 564 if (!AddItemToUpdateCheck(item, &query)) | 626 if (!AddItemToUpdateCheck(item, &query)) |
| 565 break; | 627 break; |
| 566 } | 628 } |
| 567 | 629 |
| 568 // Finally, we check components that we already updated as long as | 630 // Finally, we check components that we already updated as long as |
| 569 // we have not checked them recently. | 631 // we have not checked them recently. |
| 570 for (UpdateItems::const_iterator it = work_items_.begin(); | 632 for (UpdateItems::const_iterator it = work_items.begin(); |
| 571 it != work_items_.end(); ++it) { | 633 it != work_items.end(); ++it) { |
| 572 CrxUpdateItem* item = *it; | 634 CrxUpdateItem* item = *it; |
| 573 if (item->status != CrxUpdateItem::kUpdated) | 635 if (item->status != CrxUpdateItem::kUpdated) |
| 574 continue; | 636 continue; |
| 575 if (item->component.source != manifest_source) | 637 if (item->component.source != manifest_source) |
| 576 continue; | 638 continue; |
| 577 base::TimeDelta delta = base::Time::Now() - item->last_check; | 639 base::TimeDelta delta = base::Time::Now() - item->last_check; |
| 578 if (delta < min_delta_time) | 640 if (delta < min_delta_time) |
| 579 continue; | 641 continue; |
| 580 if (!AddItemToUpdateCheck(item, &query)) | 642 if (!AddItemToUpdateCheck(item, &query)) |
| 581 break; | 643 break; |
| 582 } | 644 } |
| 583 | 645 |
| 584 // If no components to update we move down to the next source. | 646 // If no components to update we move down to the next source. |
| 585 if (query.empty()) | 647 if (query.empty()) |
| 586 continue; | 648 continue; |
| 587 | 649 |
| 588 // We got components to check. Start the url request and exit. | 650 // We got components to check. Start the url request and exit. |
| 589 const std::string full_query = | 651 const std::string full_query = |
| 590 MakeFinalQuery(config_->UpdateUrl(manifest_source).spec(), | 652 MakeFinalQuery(config_->UpdateUrl(manifest_source).spec(), |
| 591 query, | 653 query, |
| 592 config_->ExtraRequestParams()); | 654 config_->ExtraRequestParams()); |
| 593 | 655 |
| 594 url_fetcher_.reset(net::URLFetcher::Create( | 656 url_fetcher_.reset(net::URLFetcher::Create( |
| 595 0, GURL(full_query), net::URLFetcher::GET, | 657 0, GURL(full_query), net::URLFetcher::GET, |
| 596 MakeContextDelegate(this, new UpdateContext()))); | 658 MakeContextDelegate(this, new UpdateContext()))); |
| 597 StartFetch(url_fetcher_.get(), config_->RequestContext(), false); | 659 StartFetch(url_fetcher_.get(), config_->RequestContext(), false); |
| 598 return; | 660 return true; |
| 599 } | 661 } |
| 600 | 662 |
| 601 // No components to update. Next check after the long sleep. | 663 return false; |
| 602 ScheduleNextRun(false); | |
| 603 } | 664 } |
| 604 | 665 |
| 605 // Caled when we got a response from the update server. It consists of an xml | 666 // Called when we got a response from the update server. It consists of an xml |
| 606 // document following the omaha update scheme. | 667 // document following the omaha update scheme. |
| 607 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, | 668 void CrxUpdateService::OnURLFetchComplete(const net::URLFetcher* source, |
| 608 UpdateContext* context) { | 669 UpdateContext* context) { |
| 609 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 670 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
| 610 if (FetchSuccess(*source)) { | 671 if (FetchSuccess(*source)) { |
| 611 std::string xml; | 672 std::string xml; |
| 612 source->GetResponseAsString(&xml); | 673 source->GetResponseAsString(&xml); |
| 613 url_fetcher_.reset(); | 674 url_fetcher_.reset(); |
| 614 ParseManifest(xml); | 675 ParseManifest(xml); |
| 615 } else { | 676 } else { |
| (...skipping 183 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 799 ScheduleNextRun(false); | 860 ScheduleNextRun(false); |
| 800 } | 861 } |
| 801 | 862 |
| 802 // The component update factory. Using the component updater as a singleton | 863 // The component update factory. Using the component updater as a singleton |
| 803 // is the job of the browser process. | 864 // is the job of the browser process. |
| 804 ComponentUpdateService* ComponentUpdateServiceFactory( | 865 ComponentUpdateService* ComponentUpdateServiceFactory( |
| 805 ComponentUpdateService::Configurator* config) { | 866 ComponentUpdateService::Configurator* config) { |
| 806 DCHECK(config); | 867 DCHECK(config); |
| 807 return new CrxUpdateService(config); | 868 return new CrxUpdateService(config); |
| 808 } | 869 } |
| OLD | NEW |