| Index: chrome/browser/extensions/extension_updater.cc
|
| diff --git a/chrome/browser/extensions/extension_updater.cc b/chrome/browser/extensions/extension_updater.cc
|
| index de1ca96cfd30d0e80169ea8dbd64984c0d66c3d7..80621f58f22916e02fd80c714c81cd2395d887bf 100644
|
| --- a/chrome/browser/extensions/extension_updater.cc
|
| +++ b/chrome/browser/extensions/extension_updater.cc
|
| @@ -378,7 +378,7 @@ void ExtensionUpdater::OnManifestFetchComplete(const GURL& url,
|
| safe_parser->Start();
|
| } else {
|
| // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546).
|
| - LOG(INFO) << "Failed to fetch manifst '" << url.possibly_invalid_spec() <<
|
| + LOG(INFO) << "Failed to fetch manifest '" << url.possibly_invalid_spec() <<
|
| "' response code:" << response_code;
|
| }
|
| manifest_fetcher_.reset();
|
| @@ -540,59 +540,110 @@ void ExtensionUpdater::TimerFired() {
|
| ScheduleNextCheck(TimeDelta::FromSeconds(frequency_seconds_));
|
| }
|
|
|
| -void ExtensionUpdater::CheckNow() {
|
| - // List of data on fetches we're going to do. We limit the number of
|
| - // extensions grouped together in one batch to avoid running into the limits
|
| - // on the length of http GET requests, so there might be multiple
|
| - // ManifestFetchData* objects with the same base_url.
|
| - std::multimap<GURL, ManifestFetchData*> fetches;
|
| +namespace {
|
| +
|
| +struct URLStats {
|
| + URLStats()
|
| + : no_url_count(0),
|
| + google_url_count(0),
|
| + other_url_count(0),
|
| + theme_count(0) {}
|
| +
|
| + void ReportStats() const {
|
| + UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtensions",
|
| + google_url_count + other_url_count -
|
| + theme_count);
|
| + UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
|
| + theme_count);
|
| + UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl",
|
| + google_url_count);
|
| + UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl",
|
| + other_url_count);
|
| + UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl",
|
| + no_url_count);
|
| + }
|
| +
|
| + int no_url_count, google_url_count, other_url_count, theme_count;
|
| +};
|
|
|
| - int no_url_count = 0;
|
| - int google_url_count = 0;
|
| - int other_url_count = 0;
|
| - int theme_count = 0;
|
| +class ManifestFetchesBuilder {
|
| + public:
|
| + explicit ManifestFetchesBuilder(ExtensionUpdateService* service)
|
| + : service_(service) {
|
| + DCHECK(service_);
|
| + }
|
|
|
| - const ExtensionList* extensions = service_->extensions();
|
| - for (ExtensionList::const_iterator iter = extensions->begin();
|
| - iter != extensions->end(); ++iter) {
|
| - Extension* extension = (*iter);
|
| + void AddExtension(const Extension& extension) {
|
| + AddExtensionData(extension.location(),
|
| + extension.id(),
|
| + *extension.version(),
|
| + extension.converted_from_user_script(),
|
| + extension.IsTheme(),
|
| + extension.update_url());
|
| + }
|
|
|
| - // Only internal and external extensions can be autoupdated.
|
| - if (extension->location() != Extension::INTERNAL &&
|
| - !Extension::IsExternalLocation(extension->location())) {
|
| - continue;
|
| + void AddPendingExtension(const std::string& id,
|
| + const PendingExtensionInfo& info) {
|
| + AddExtensionData(Extension::INTERNAL, id, info.version,
|
| + false, info.is_theme, info.update_url);
|
| + }
|
| +
|
| + const URLStats& url_stats() const { return url_stats_; }
|
| +
|
| + // Caller takes ownership of the returned ManifestFetchData
|
| + // objects. Clears all counters.
|
| + std::vector<ManifestFetchData*> GetFetches() {
|
| + std::vector<ManifestFetchData*> fetches;
|
| + fetches.reserve(fetches_.size());
|
| + for (std::multimap<GURL, ManifestFetchData*>::iterator it =
|
| + fetches_.begin(); it != fetches_.end(); ++it) {
|
| + fetches.push_back(it->second);
|
| }
|
| + fetches_.clear();
|
| + url_stats_ = URLStats();
|
| + return fetches;
|
| + }
|
|
|
| - const GURL& update_url = extension->update_url();
|
| + private:
|
| + void AddExtensionData(Extension::Location location,
|
| + const std::string& id,
|
| + const Version& version,
|
| + bool converted_from_user_script,
|
| + bool is_theme,
|
| + const GURL& update_url) {
|
| + // Only internal and external extensions can be autoupdated.
|
| + if (location != Extension::INTERNAL &&
|
| + !Extension::IsExternalLocation(location)) {
|
| + return;
|
| + }
|
|
|
| // Collect histogram data and skip extensions with no update url.
|
| if (update_url.DomainIs("google.com")) {
|
| - google_url_count++;
|
| - } else if (update_url.is_empty() || extension->id().empty()) {
|
| + url_stats_.google_url_count++;
|
| + } else if (update_url.is_empty() || id.empty()) {
|
| // TODO(asargent) when a default URL is added, make sure to update
|
| // the total histogram below. Also, make sure to skip extensions that
|
| // are "converted_from_user_script".
|
| - if (!extension->converted_from_user_script())
|
| - no_url_count++;
|
| - continue;
|
| + if (!converted_from_user_script)
|
| + url_stats_.no_url_count++;
|
| + return;
|
| } else {
|
| - other_url_count++;
|
| + url_stats_.other_url_count++;
|
| }
|
| - if (extension->IsTheme())
|
| - theme_count++;
|
| + if (is_theme)
|
| + url_stats_.theme_count++;
|
|
|
| DCHECK(update_url.is_valid());
|
|
|
| ManifestFetchData* fetch = NULL;
|
| std::multimap<GURL, ManifestFetchData*>::iterator existing_iter =
|
| - fetches.find(update_url);
|
| + fetches_.find(update_url);
|
|
|
| // Find or create a ManifestFetchData to add this extension to.
|
| - std::string id = extension->id();
|
| - std::string version = extension->VersionString();
|
| - int ping_days = CalculatePingDays(extension->id());
|
| - while (existing_iter != fetches.end()) {
|
| - if (existing_iter->second->AddExtension(id, version, ping_days)) {
|
| + int ping_days = CalculatePingDays(id);
|
| + while (existing_iter != fetches_.end()) {
|
| + if (existing_iter->second->AddExtension(id, version.GetString(),
|
| + ping_days)) {
|
| fetch = existing_iter->second;
|
| break;
|
| }
|
| @@ -600,12 +651,58 @@ void ExtensionUpdater::CheckNow() {
|
| }
|
| if (!fetch) {
|
| fetch = new ManifestFetchData(update_url);
|
| - fetches.insert(std::pair<GURL, ManifestFetchData*>(update_url, fetch));
|
| - bool added = fetch->AddExtension(id, version, ping_days);
|
| + fetches_.insert(std::pair<GURL, ManifestFetchData*>(update_url, fetch));
|
| + bool added = fetch->AddExtension(id, version.GetString(), ping_days);
|
| DCHECK(added);
|
| }
|
| }
|
|
|
| + // Calculates the value to use for the ping days parameter in manifest
|
| + // fetches for a given extension.
|
| + int CalculatePingDays(const std::string& extension_id) {
|
| + int days = ManifestFetchData::kNeverPinged;
|
| + Time last_ping_day = service_->LastPingDay(extension_id);
|
| + if (!last_ping_day.is_null()) {
|
| + days = (Time::Now() - last_ping_day).InDays();
|
| + }
|
| + return days;
|
| + }
|
| +
|
| + ExtensionUpdateService* service_;
|
| +
|
| + // List of data on fetches we're going to do. We limit the number of
|
| + // extensions grouped together in one batch to avoid running into the limits
|
| + // on the length of http GET requests, so there might be multiple
|
| + // ManifestFetchData* objects with the same base_url.
|
| + std::multimap<GURL, ManifestFetchData*> fetches_;
|
| +
|
| + URLStats url_stats_;
|
| +
|
| + DISALLOW_COPY_AND_ASSIGN(ManifestFetchesBuilder);
|
| +};
|
| +
|
| +} // namespace
|
| +
|
| +void ExtensionUpdater::CheckNow() {
|
| + ManifestFetchesBuilder fetches_builder(service_);
|
| +
|
| + const ExtensionList* extensions = service_->extensions();
|
| + for (ExtensionList::const_iterator iter = extensions->begin();
|
| + iter != extensions->end(); ++iter) {
|
| + fetches_builder.AddExtension(**iter);
|
| + }
|
| +
|
| + const PendingExtensionMap& pending_extensions =
|
| + service_->pending_extensions();
|
| + for (PendingExtensionMap::const_iterator iter = pending_extensions.begin();
|
| + iter != pending_extensions.end(); ++iter) {
|
| + fetches_builder.AddPendingExtension(iter->first, iter->second);
|
| + }
|
| +
|
| + fetches_builder.url_stats().ReportStats();
|
| +
|
| + std::vector<ManifestFetchData*> fetches(fetches_builder.GetFetches());
|
| +
|
| // Start a fetch of the blacklist if needed.
|
| if (blacklist_checks_enabled_ && service_->HasInstalledExtensions()) {
|
| ManifestFetchData* blacklist_fetch =
|
| @@ -616,36 +713,16 @@ void ExtensionUpdater::CheckNow() {
|
| }
|
|
|
| // Now start fetching regular extension updates
|
| - std::multimap<GURL, ManifestFetchData*>::iterator i = fetches.begin();
|
| - while (i != fetches.end()) {
|
| - ManifestFetchData *fetch = i->second;
|
| -
|
| + for (std::vector<ManifestFetchData*>::const_iterator it = fetches.begin();
|
| + it != fetches.end(); ++it) {
|
| // StartUpdateCheck makes sure the url isn't already downloading or
|
| // scheduled, so we don't need to check before calling it. Ownership of
|
| // fetch is transferred here.
|
| - StartUpdateCheck(fetch);
|
| - fetches.erase(i++);
|
| - }
|
| -
|
| - UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtensions",
|
| - google_url_count + other_url_count - theme_count);
|
| - UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
|
| - theme_count);
|
| - UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl",
|
| - google_url_count);
|
| - UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl",
|
| - other_url_count);
|
| - UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl",
|
| - no_url_count);
|
| -}
|
| -
|
| -int ExtensionUpdater::CalculatePingDays(const std::string& extension_id) {
|
| - int days = ManifestFetchData::kNeverPinged;
|
| - Time last_ping_day = service_->LastPingDay(extension_id);
|
| - if (!last_ping_day.is_null()) {
|
| - days = (Time::Now() - last_ping_day).InDays();
|
| + StartUpdateCheck(*it);
|
| }
|
| - return days;
|
| + // We don't want to use fetches after this since StartUpdateCheck()
|
| + // takes ownership of its argument.
|
| + fetches.clear();
|
| }
|
|
|
| bool ExtensionUpdater::GetExistingVersion(const std::string& id,
|
| @@ -655,6 +732,12 @@ bool ExtensionUpdater::GetExistingVersion(const std::string& id,
|
| WideToASCII(prefs_->GetString(kExtensionBlacklistUpdateVersion));
|
| return true;
|
| }
|
| + PendingExtensionMap::const_iterator it =
|
| + service_->pending_extensions().find(id);
|
| + if (it != service_->pending_extensions().end()) {
|
| + *version = it->second.version.GetString();
|
| + return true;
|
| + }
|
| Extension* extension = service_->GetExtensionById(id, false);
|
| if (!extension) {
|
| return false;
|
|
|