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

Side by Side Diff: chrome/browser/extensions/extension_updater.cc

Issue 1232003: Added support for pending extensions to ExtensionsService and (Closed)
Patch Set: synced to head Created 10 years, 9 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
OLDNEW
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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/extensions/extension_updater.h" 5 #include "chrome/browser/extensions/extension_updater.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 #include <set> 8 #include <set>
9 9
10 #include "base/logging.h" 10 #include "base/logging.h"
(...skipping 360 matching lines...) Expand 10 before | Expand all | Expand 10 after
371 int response_code, 371 int response_code,
372 const std::string& data) { 372 const std::string& data) {
373 // We want to try parsing the manifest, and if it indicates updates are 373 // We want to try parsing the manifest, and if it indicates updates are
374 // available, we want to fire off requests to fetch those updates. 374 // available, we want to fire off requests to fetch those updates.
375 if (status.status() == URLRequestStatus::SUCCESS && response_code == 200) { 375 if (status.status() == URLRequestStatus::SUCCESS && response_code == 200) {
376 scoped_refptr<SafeManifestParser> safe_parser = 376 scoped_refptr<SafeManifestParser> safe_parser =
377 new SafeManifestParser(data, current_manifest_fetch_.release(), this); 377 new SafeManifestParser(data, current_manifest_fetch_.release(), this);
378 safe_parser->Start(); 378 safe_parser->Start();
379 } else { 379 } else {
380 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546). 380 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546).
381 LOG(INFO) << "Failed to fetch manifst '" << url.possibly_invalid_spec() << 381 LOG(INFO) << "Failed to fetch manifest '" << url.possibly_invalid_spec() <<
382 "' response code:" << response_code; 382 "' response code:" << response_code;
383 } 383 }
384 manifest_fetcher_.reset(); 384 manifest_fetcher_.reset();
385 current_manifest_fetch_.reset(); 385 current_manifest_fetch_.reset();
386 386
387 // If we have any pending manifest requests, fire off the next one. 387 // If we have any pending manifest requests, fire off the next one.
388 if (!manifests_pending_.empty()) { 388 if (!manifests_pending_.empty()) {
389 ManifestFetchData* manifest_fetch = manifests_pending_.front(); 389 ManifestFetchData* manifest_fetch = manifests_pending_.front();
390 manifests_pending_.pop_front(); 390 manifests_pending_.pop_front();
391 StartUpdateCheck(manifest_fetch); 391 StartUpdateCheck(manifest_fetch);
(...skipping 141 matching lines...) Expand 10 before | Expand all | Expand 10 after
533 50); // 50 buckets seems to be the default. 533 50); // 50 buckets seems to be the default.
534 } 534 }
535 } 535 }
536 536
537 // Save the last check time, and schedule the next check. 537 // Save the last check time, and schedule the next check.
538 int64 now = Time::Now().ToInternalValue(); 538 int64 now = Time::Now().ToInternalValue();
539 prefs_->SetInt64(kLastExtensionsUpdateCheck, now); 539 prefs_->SetInt64(kLastExtensionsUpdateCheck, now);
540 ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_)); 540 ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_));
541 } 541 }
542 542
543 void ExtensionUpdater::CheckNow() { 543 namespace {
544 // List of data on fetches we're going to do. We limit the number of
545 // extensions grouped together in one batch to avoid running into the limits
546 // on the length of http GET requests, so there might be multiple
547 // ManifestFetchData* objects with the same base_url.
548 std::multimap<GURL, ManifestFetchData*> fetches;
549 544
550 int no_url_count = 0; 545 struct URLStats {
551 int google_url_count = 0; 546 URLStats()
552 int other_url_count = 0; 547 : no_url_count(0),
553 int theme_count = 0; 548 google_url_count(0),
549 other_url_count(0),
550 theme_count(0) {}
554 551
555 const ExtensionList* extensions = service_->extensions(); 552 void ReportStats() const {
556 for (ExtensionList::const_iterator iter = extensions->begin(); 553 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtensions",
557 iter != extensions->end(); ++iter) { 554 google_url_count + other_url_count -
558 Extension* extension = (*iter); 555 theme_count);
556 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
557 theme_count);
558 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl",
559 google_url_count);
560 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl",
561 other_url_count);
562 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl",
563 no_url_count);
564 }
559 565
566 int no_url_count, google_url_count, other_url_count, theme_count;
567 };
568
569 class ManifestFetchesBuilder {
570 public:
571 explicit ManifestFetchesBuilder(ExtensionUpdateService* service)
572 : service_(service) {
573 DCHECK(service_);
574 }
575
576 void AddExtension(const Extension& extension) {
577 AddExtensionData(extension.location(),
578 extension.id(),
579 *extension.version(),
580 extension.converted_from_user_script(),
581 extension.IsTheme(),
582 extension.update_url());
583 }
584
585 void AddPendingExtension(const std::string& id,
586 const PendingExtensionInfo& info) {
587 AddExtensionData(Extension::INTERNAL, id, info.version,
588 false, info.is_theme, info.update_url);
589 }
590
591 const URLStats& url_stats() const { return url_stats_; }
592
593 // Caller takes ownership of the returned ManifestFetchData
594 // objects. Clears all counters.
595 std::vector<ManifestFetchData*> GetFetches() {
596 std::vector<ManifestFetchData*> fetches;
597 fetches.reserve(fetches_.size());
598 for (std::multimap<GURL, ManifestFetchData*>::iterator it =
599 fetches_.begin(); it != fetches_.end(); ++it) {
600 fetches.push_back(it->second);
601 }
602 fetches_.clear();
603 url_stats_ = URLStats();
604 return fetches;
605 }
606
607 private:
608 void AddExtensionData(Extension::Location location,
609 const std::string& id,
610 const Version& version,
611 bool converted_from_user_script,
612 bool is_theme,
613 const GURL& update_url) {
560 // Only internal and external extensions can be autoupdated. 614 // Only internal and external extensions can be autoupdated.
561 if (extension->location() != Extension::INTERNAL && 615 if (location != Extension::INTERNAL &&
562 !Extension::IsExternalLocation(extension->location())) { 616 !Extension::IsExternalLocation(location)) {
563 continue; 617 return;
564 } 618 }
565 619
566 const GURL& update_url = extension->update_url();
567
568 // Collect histogram data and skip extensions with no update url. 620 // Collect histogram data and skip extensions with no update url.
569 if (update_url.DomainIs("google.com")) { 621 if (update_url.DomainIs("google.com")) {
570 google_url_count++; 622 url_stats_.google_url_count++;
571 } else if (update_url.is_empty() || extension->id().empty()) { 623 } else if (update_url.is_empty() || id.empty()) {
572 // TODO(asargent) when a default URL is added, make sure to update 624 // TODO(asargent) when a default URL is added, make sure to update
573 // the total histogram below. Also, make sure to skip extensions that 625 // the total histogram below. Also, make sure to skip extensions that
574 // are "converted_from_user_script". 626 // are "converted_from_user_script".
575 if (!extension->converted_from_user_script()) 627 if (!converted_from_user_script)
576 no_url_count++; 628 url_stats_.no_url_count++;
577 continue; 629 return;
578 } else { 630 } else {
579 other_url_count++; 631 url_stats_.other_url_count++;
580 } 632 }
581 if (extension->IsTheme()) 633 if (is_theme)
582 theme_count++; 634 url_stats_.theme_count++;
583 635
584 DCHECK(update_url.is_valid()); 636 DCHECK(update_url.is_valid());
585 637
586 ManifestFetchData* fetch = NULL; 638 ManifestFetchData* fetch = NULL;
587 std::multimap<GURL, ManifestFetchData*>::iterator existing_iter = 639 std::multimap<GURL, ManifestFetchData*>::iterator existing_iter =
588 fetches.find(update_url); 640 fetches_.find(update_url);
589 641
590 // Find or create a ManifestFetchData to add this extension to. 642 // Find or create a ManifestFetchData to add this extension to.
591 std::string id = extension->id(); 643 int ping_days = CalculatePingDays(id);
592 std::string version = extension->VersionString(); 644 while (existing_iter != fetches_.end()) {
593 int ping_days = CalculatePingDays(extension->id()); 645 if (existing_iter->second->AddExtension(id, version.GetString(),
594 while (existing_iter != fetches.end()) { 646 ping_days)) {
595 if (existing_iter->second->AddExtension(id, version, ping_days)) {
596 fetch = existing_iter->second; 647 fetch = existing_iter->second;
597 break; 648 break;
598 } 649 }
599 existing_iter++; 650 existing_iter++;
600 } 651 }
601 if (!fetch) { 652 if (!fetch) {
602 fetch = new ManifestFetchData(update_url); 653 fetch = new ManifestFetchData(update_url);
603 fetches.insert(std::pair<GURL, ManifestFetchData*>(update_url, fetch)); 654 fetches_.insert(std::pair<GURL, ManifestFetchData*>(update_url, fetch));
604 bool added = fetch->AddExtension(id, version, ping_days); 655 bool added = fetch->AddExtension(id, version.GetString(), ping_days);
605 DCHECK(added); 656 DCHECK(added);
606 } 657 }
607 } 658 }
608 659
660 // Calculates the value to use for the ping days parameter in manifest
661 // fetches for a given extension.
662 int CalculatePingDays(const std::string& extension_id) {
663 int days = ManifestFetchData::kNeverPinged;
664 Time last_ping_day = service_->LastPingDay(extension_id);
665 if (!last_ping_day.is_null()) {
666 days = (Time::Now() - last_ping_day).InDays();
667 }
668 return days;
669 }
670
671 ExtensionUpdateService* service_;
672
673 // List of data on fetches we're going to do. We limit the number of
674 // extensions grouped together in one batch to avoid running into the limits
675 // on the length of http GET requests, so there might be multiple
676 // ManifestFetchData* objects with the same base_url.
677 std::multimap<GURL, ManifestFetchData*> fetches_;
678
679 URLStats url_stats_;
680
681 DISALLOW_COPY_AND_ASSIGN(ManifestFetchesBuilder);
682 };
683
684 } // namespace
685
686 void ExtensionUpdater::CheckNow() {
687 ManifestFetchesBuilder fetches_builder(service_);
688
689 const ExtensionList* extensions = service_->extensions();
690 for (ExtensionList::const_iterator iter = extensions->begin();
691 iter != extensions->end(); ++iter) {
692 fetches_builder.AddExtension(**iter);
693 }
694
695 const PendingExtensionMap& pending_extensions =
696 service_->pending_extensions();
697 for (PendingExtensionMap::const_iterator iter = pending_extensions.begin();
698 iter != pending_extensions.end(); ++iter) {
699 fetches_builder.AddPendingExtension(iter->first, iter->second);
700 }
701
702 fetches_builder.url_stats().ReportStats();
703
704 std::vector<ManifestFetchData*> fetches(fetches_builder.GetFetches());
705
609 // Start a fetch of the blacklist if needed. 706 // Start a fetch of the blacklist if needed.
610 if (blacklist_checks_enabled_ && service_->HasInstalledExtensions()) { 707 if (blacklist_checks_enabled_ && service_->HasInstalledExtensions()) {
611 ManifestFetchData* blacklist_fetch = 708 ManifestFetchData* blacklist_fetch =
612 new ManifestFetchData(GURL(kBlacklistUpdateUrl)); 709 new ManifestFetchData(GURL(kBlacklistUpdateUrl));
613 std::wstring version = prefs_->GetString(kExtensionBlacklistUpdateVersion); 710 std::wstring version = prefs_->GetString(kExtensionBlacklistUpdateVersion);
614 blacklist_fetch->AddExtension(kBlacklistAppID, WideToASCII(version), 0); 711 blacklist_fetch->AddExtension(kBlacklistAppID, WideToASCII(version), 0);
615 StartUpdateCheck(blacklist_fetch); 712 StartUpdateCheck(blacklist_fetch);
616 } 713 }
617 714
618 // Now start fetching regular extension updates 715 // Now start fetching regular extension updates
619 std::multimap<GURL, ManifestFetchData*>::iterator i = fetches.begin(); 716 for (std::vector<ManifestFetchData*>::const_iterator it = fetches.begin();
620 while (i != fetches.end()) { 717 it != fetches.end(); ++it) {
621 ManifestFetchData *fetch = i->second;
622
623 // StartUpdateCheck makes sure the url isn't already downloading or 718 // StartUpdateCheck makes sure the url isn't already downloading or
624 // scheduled, so we don't need to check before calling it. Ownership of 719 // scheduled, so we don't need to check before calling it. Ownership of
625 // fetch is transferred here. 720 // fetch is transferred here.
626 StartUpdateCheck(fetch); 721 StartUpdateCheck(*it);
627 fetches.erase(i++);
628 } 722 }
629 723 // We don't want to use fetches after this since StartUpdateCheck()
630 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtensions", 724 // takes ownership of its argument.
631 google_url_count + other_url_count - theme_count); 725 fetches.clear();
632 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
633 theme_count);
634 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl",
635 google_url_count);
636 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl",
637 other_url_count);
638 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl",
639 no_url_count);
640 }
641
642 int ExtensionUpdater::CalculatePingDays(const std::string& extension_id) {
643 int days = ManifestFetchData::kNeverPinged;
644 Time last_ping_day = service_->LastPingDay(extension_id);
645 if (!last_ping_day.is_null()) {
646 days = (Time::Now() - last_ping_day).InDays();
647 }
648 return days;
649 } 726 }
650 727
651 bool ExtensionUpdater::GetExistingVersion(const std::string& id, 728 bool ExtensionUpdater::GetExistingVersion(const std::string& id,
652 std::string* version) { 729 std::string* version) {
653 if (id == kBlacklistAppID) { 730 if (id == kBlacklistAppID) {
654 *version = 731 *version =
655 WideToASCII(prefs_->GetString(kExtensionBlacklistUpdateVersion)); 732 WideToASCII(prefs_->GetString(kExtensionBlacklistUpdateVersion));
656 return true; 733 return true;
657 } 734 }
735 PendingExtensionMap::const_iterator it =
736 service_->pending_extensions().find(id);
737 if (it != service_->pending_extensions().end()) {
738 *version = it->second.version.GetString();
739 return true;
740 }
658 Extension* extension = service_->GetExtensionById(id, false); 741 Extension* extension = service_->GetExtensionById(id, false);
659 if (!extension) { 742 if (!extension) {
660 return false; 743 return false;
661 } 744 }
662 *version = extension->version()->GetString(); 745 *version = extension->version()->GetString();
663 return true; 746 return true;
664 } 747 }
665 748
666 std::vector<int> ExtensionUpdater::DetermineUpdates( 749 std::vector<int> ExtensionUpdater::DetermineUpdates(
667 const ManifestFetchData& fetch_data, 750 const ManifestFetchData& fetch_data,
(...skipping 104 matching lines...) Expand 10 before | Expand all | Expand 10 after
772 extension_fetcher_.reset( 855 extension_fetcher_.reset(
773 URLFetcher::Create(kExtensionFetcherId, url, URLFetcher::GET, this)); 856 URLFetcher::Create(kExtensionFetcherId, url, URLFetcher::GET, this));
774 extension_fetcher_->set_request_context( 857 extension_fetcher_->set_request_context(
775 Profile::GetDefaultRequestContext()); 858 Profile::GetDefaultRequestContext());
776 extension_fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES | 859 extension_fetcher_->set_load_flags(net::LOAD_DO_NOT_SEND_COOKIES |
777 net::LOAD_DO_NOT_SAVE_COOKIES); 860 net::LOAD_DO_NOT_SAVE_COOKIES);
778 extension_fetcher_->Start(); 861 extension_fetcher_->Start();
779 current_extension_fetch_ = ExtensionFetch(id, url, hash, version); 862 current_extension_fetch_ = ExtensionFetch(id, url, hash, version);
780 } 863 }
781 } 864 }
OLDNEW
« no previous file with comments | « chrome/browser/extensions/extension_updater.h ('k') | chrome/browser/extensions/extension_updater_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698