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 |