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/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/bind.h" | 10 #include "base/bind.h" |
(...skipping 579 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
590 STLDeleteElements(&manifests_pending_); | 590 STLDeleteElements(&manifests_pending_); |
591 manifests_pending_.clear(); | 591 manifests_pending_.clear(); |
592 extensions_pending_.clear(); | 592 extensions_pending_.clear(); |
593 } | 593 } |
594 | 594 |
595 void ExtensionUpdater::OnURLFetchComplete(const content::URLFetcher* source) { | 595 void ExtensionUpdater::OnURLFetchComplete(const content::URLFetcher* source) { |
596 // Stop() destroys all our URLFetchers, which means we shouldn't be | 596 // Stop() destroys all our URLFetchers, which means we shouldn't be |
597 // called after Stop() is called. | 597 // called after Stop() is called. |
598 DCHECK(alive_); | 598 DCHECK(alive_); |
599 | 599 |
| 600 VLOG(2) << source->GetResponseCode() << " " << source->GetURL(); |
| 601 |
600 if (source == manifest_fetcher_.get()) { | 602 if (source == manifest_fetcher_.get()) { |
601 std::string data; | 603 std::string data; |
602 source->GetResponseAsString(&data); | 604 source->GetResponseAsString(&data); |
603 OnManifestFetchComplete(source->GetURL(), | 605 OnManifestFetchComplete(source->GetURL(), |
604 source->GetStatus(), | 606 source->GetStatus(), |
605 source->GetResponseCode(), | 607 source->GetResponseCode(), |
606 data); | 608 data); |
607 } else if (source == extension_fetcher_.get()) { | 609 } else if (source == extension_fetcher_.get()) { |
608 OnCRXFetchComplete(source, | 610 OnCRXFetchComplete(source, |
609 source->GetURL(), | 611 source->GetURL(), |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
682 OnParseUpdateManifestSucceeded) | 684 OnParseUpdateManifestSucceeded) |
683 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseUpdateManifest_Failed, | 685 IPC_MESSAGE_HANDLER(ChromeUtilityHostMsg_ParseUpdateManifest_Failed, |
684 OnParseUpdateManifestFailed) | 686 OnParseUpdateManifestFailed) |
685 IPC_MESSAGE_UNHANDLED(handled = false) | 687 IPC_MESSAGE_UNHANDLED(handled = false) |
686 IPC_END_MESSAGE_MAP() | 688 IPC_END_MESSAGE_MAP() |
687 return handled; | 689 return handled; |
688 } | 690 } |
689 | 691 |
690 void OnParseUpdateManifestSucceeded( | 692 void OnParseUpdateManifestSucceeded( |
691 const UpdateManifest::Results& results) { | 693 const UpdateManifest::Results& results) { |
| 694 VLOG(2) << "parsing manifest succeeded (" << fetch_data_->full_url() |
| 695 << ")"; |
692 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 696 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
693 if (!updater_) { | 697 if (!updater_) { |
694 return; | 698 return; |
695 } | 699 } |
696 updater_->HandleManifestResults(*fetch_data_, &results); | 700 updater_->HandleManifestResults(*fetch_data_, &results); |
697 } | 701 } |
698 | 702 |
699 void OnParseUpdateManifestFailed(const std::string& error_message) { | 703 void OnParseUpdateManifestFailed(const std::string& error_message) { |
| 704 VLOG(2) << "parsing manifest failed (" << fetch_data_->full_url() << ")"; |
700 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); | 705 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); |
701 if (!updater_) { | 706 if (!updater_) { |
702 return; | 707 return; |
703 } | 708 } |
704 LOG(WARNING) << "Error parsing update manifest:\n" << error_message; | 709 LOG(WARNING) << "Error parsing update manifest:\n" << error_message; |
705 updater_->HandleManifestResults(*fetch_data_, NULL); | 710 updater_->HandleManifestResults(*fetch_data_, NULL); |
706 } | 711 } |
707 | 712 |
708 private: | 713 private: |
709 ~SafeManifestParser() { | 714 ~SafeManifestParser() { |
(...skipping 11 matching lines...) Expand all Loading... |
721 | 726 |
722 void ExtensionUpdater::OnManifestFetchComplete( | 727 void ExtensionUpdater::OnManifestFetchComplete( |
723 const GURL& url, | 728 const GURL& url, |
724 const net::URLRequestStatus& status, | 729 const net::URLRequestStatus& status, |
725 int response_code, | 730 int response_code, |
726 const std::string& data) { | 731 const std::string& data) { |
727 // We want to try parsing the manifest, and if it indicates updates are | 732 // We want to try parsing the manifest, and if it indicates updates are |
728 // available, we want to fire off requests to fetch those updates. | 733 // available, we want to fire off requests to fetch those updates. |
729 if (status.status() == net::URLRequestStatus::SUCCESS && | 734 if (status.status() == net::URLRequestStatus::SUCCESS && |
730 (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) { | 735 (response_code == 200 || (url.SchemeIsFile() && data.length() > 0))) { |
| 736 VLOG(2) << "beginning manifest parse for " << url; |
731 scoped_refptr<SafeManifestParser> safe_parser( | 737 scoped_refptr<SafeManifestParser> safe_parser( |
732 new SafeManifestParser(data, current_manifest_fetch_.release(), | 738 new SafeManifestParser(data, current_manifest_fetch_.release(), |
733 weak_ptr_factory_.GetWeakPtr())); | 739 weak_ptr_factory_.GetWeakPtr())); |
734 safe_parser->Start(); | 740 safe_parser->Start(); |
735 } else { | 741 } else { |
736 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546). | 742 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546). |
737 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec() | 743 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec() |
738 << "' response code:" << response_code; | 744 << "' response code:" << response_code; |
739 RemoveFromInProgress(current_manifest_fetch_->extension_ids()); | 745 RemoveFromInProgress(current_manifest_fetch_->extension_ids()); |
740 } | 746 } |
(...skipping 131 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
872 extensions_pending_.pop_front(); | 878 extensions_pending_.pop_front(); |
873 FetchUpdatedExtension(next.id, next.url, next.package_hash, next.version); | 879 FetchUpdatedExtension(next.id, next.url, next.package_hash, next.version); |
874 } | 880 } |
875 } | 881 } |
876 | 882 |
877 void ExtensionUpdater::OnCRXFileWritten(const std::string& id, | 883 void ExtensionUpdater::OnCRXFileWritten(const std::string& id, |
878 const FilePath& path, | 884 const FilePath& path, |
879 const GURL& download_url) { | 885 const GURL& download_url) { |
880 DCHECK(alive_); | 886 DCHECK(alive_); |
881 | 887 |
| 888 VLOG(2) << download_url << " written to " << path.value(); |
| 889 |
882 FetchedCRXFile fetched(id, path, download_url); | 890 FetchedCRXFile fetched(id, path, download_url); |
883 fetched_crx_files_.push(fetched); | 891 fetched_crx_files_.push(fetched); |
884 | 892 |
885 MaybeInstallCRXFile(); | 893 MaybeInstallCRXFile(); |
886 } | 894 } |
887 | 895 |
888 bool ExtensionUpdater::MaybeInstallCRXFile() { | 896 bool ExtensionUpdater::MaybeInstallCRXFile() { |
889 if (crx_install_is_running_) | 897 if (crx_install_is_running_) |
890 return false; | 898 return false; |
891 | 899 |
892 while (!fetched_crx_files_.empty() && !crx_install_is_running_) { | 900 while (!fetched_crx_files_.empty() && !crx_install_is_running_) { |
893 const FetchedCRXFile& crx_file = fetched_crx_files_.top(); | 901 const FetchedCRXFile& crx_file = fetched_crx_files_.top(); |
894 | 902 |
| 903 VLOG(2) << "updating " << crx_file.id << " with " << crx_file.path.value(); |
| 904 |
895 // The ExtensionService is now responsible for cleaning up the temp file | 905 // The ExtensionService is now responsible for cleaning up the temp file |
896 // at |extension_file.path|. | 906 // at |extension_file.path|. |
897 CrxInstaller* installer = NULL; | 907 CrxInstaller* installer = NULL; |
898 if (service_->UpdateExtension(crx_file.id, | 908 if (service_->UpdateExtension(crx_file.id, |
899 crx_file.path, | 909 crx_file.path, |
900 crx_file.download_url, | 910 crx_file.download_url, |
901 &installer)) { | 911 &installer)) { |
902 crx_install_is_running_ = true; | 912 crx_install_is_running_ = true; |
903 | 913 |
904 // Source parameter ensures that we only see the completion event for the | 914 // Source parameter ensures that we only see the completion event for the |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
998 return will_check_soon_; | 1008 return will_check_soon_; |
999 } | 1009 } |
1000 | 1010 |
1001 void ExtensionUpdater::DoCheckSoon() { | 1011 void ExtensionUpdater::DoCheckSoon() { |
1002 DCHECK(will_check_soon_); | 1012 DCHECK(will_check_soon_); |
1003 CheckNow(); | 1013 CheckNow(); |
1004 will_check_soon_ = false; | 1014 will_check_soon_ = false; |
1005 } | 1015 } |
1006 | 1016 |
1007 void ExtensionUpdater::CheckNow() { | 1017 void ExtensionUpdater::CheckNow() { |
| 1018 VLOG(2) << "Starting update check"; |
1008 DCHECK(alive_); | 1019 DCHECK(alive_); |
1009 NotifyStarted(); | 1020 NotifyStarted(); |
1010 ManifestFetchesBuilder fetches_builder(service_, extension_prefs_); | 1021 ManifestFetchesBuilder fetches_builder(service_, extension_prefs_); |
1011 | 1022 |
1012 const PendingExtensionManager* pending_extension_manager = | 1023 const PendingExtensionManager* pending_extension_manager = |
1013 service_->pending_extension_manager(); | 1024 service_->pending_extension_manager(); |
1014 std::set<std::string> pending_ids; | 1025 std::set<std::string> pending_ids; |
1015 | 1026 |
1016 PendingExtensionManager::const_iterator iter; | 1027 PendingExtensionManager::const_iterator iter; |
1017 for (iter = pending_extension_manager->begin(); | 1028 for (iter = pending_extension_manager->begin(); |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1094 | 1105 |
1095 // This will only be valid if one of possible_updates specifies | 1106 // This will only be valid if one of possible_updates specifies |
1096 // browser_min_version. | 1107 // browser_min_version. |
1097 Version browser_version; | 1108 Version browser_version; |
1098 PendingExtensionManager* pending_extension_manager = | 1109 PendingExtensionManager* pending_extension_manager = |
1099 service_->pending_extension_manager(); | 1110 service_->pending_extension_manager(); |
1100 | 1111 |
1101 for (size_t i = 0; i < possible_updates.list.size(); i++) { | 1112 for (size_t i = 0; i < possible_updates.list.size(); i++) { |
1102 const UpdateManifest::Result* update = &possible_updates.list[i]; | 1113 const UpdateManifest::Result* update = &possible_updates.list[i]; |
1103 | 1114 |
1104 if (!fetch_data.Includes(update->extension_id)) | 1115 if (!fetch_data.Includes(update->extension_id)) { |
| 1116 VLOG(2) << "Ignoring " << update->extension_id << " from this manifest"; |
1105 continue; | 1117 continue; |
| 1118 } |
| 1119 |
| 1120 if (VLOG_IS_ON(2)) { |
| 1121 if (update->version.empty()) |
| 1122 VLOG(2) << "manifest indicates " << update->extension_id |
| 1123 << " has no update"; |
| 1124 else |
| 1125 VLOG(2) << "manifest indicates " << update->extension_id |
| 1126 << " latest version is '" << update->version << "'"; |
| 1127 } |
1106 | 1128 |
1107 if (!pending_extension_manager->IsIdPending(update->extension_id)) { | 1129 if (!pending_extension_manager->IsIdPending(update->extension_id)) { |
1108 // If we're not installing pending extension, and the update | 1130 // If we're not installing pending extension, and the update |
1109 // version is the same or older than what's already installed, | 1131 // version is the same or older than what's already installed, |
1110 // we don't want it. | 1132 // we don't want it. |
1111 std::string version; | 1133 std::string version; |
1112 if (!GetExistingVersion(update->extension_id, &version)) | 1134 if (!GetExistingVersion(update->extension_id, &version)) { |
| 1135 VLOG(2) << update->extension_id << " is not installed"; |
1113 continue; | 1136 continue; |
| 1137 } |
| 1138 |
| 1139 VLOG(2) << update->extension_id << " is at '" << version << "'"; |
1114 | 1140 |
1115 Version existing_version(version); | 1141 Version existing_version(version); |
1116 Version update_version(update->version); | 1142 Version update_version(update->version); |
1117 | 1143 |
1118 if (!update_version.IsValid() || | 1144 if (!update_version.IsValid() || |
1119 update_version.CompareTo(existing_version) <= 0) { | 1145 update_version.CompareTo(existing_version) <= 0) { |
1120 continue; | 1146 continue; |
1121 } | 1147 } |
1122 } | 1148 } |
1123 | 1149 |
1124 // If the update specifies a browser minimum version, do we qualify? | 1150 // If the update specifies a browser minimum version, do we qualify? |
1125 if (update->browser_min_version.length() > 0) { | 1151 if (update->browser_min_version.length() > 0) { |
1126 // First determine the browser version if we haven't already. | 1152 // First determine the browser version if we haven't already. |
1127 if (!browser_version.IsValid()) { | 1153 if (!browser_version.IsValid()) { |
1128 chrome::VersionInfo version_info; | 1154 chrome::VersionInfo version_info; |
1129 if (version_info.is_valid()) | 1155 if (version_info.is_valid()) |
1130 browser_version = Version(version_info.Version()); | 1156 browser_version = Version(version_info.Version()); |
1131 } | 1157 } |
1132 Version browser_min_version(update->browser_min_version); | 1158 Version browser_min_version(update->browser_min_version); |
1133 if (browser_version.IsValid() && browser_min_version.IsValid() && | 1159 if (browser_version.IsValid() && browser_min_version.IsValid() && |
1134 browser_min_version.CompareTo(browser_version) > 0) { | 1160 browser_min_version.CompareTo(browser_version) > 0) { |
1135 // TODO(asargent) - We may want this to show up in the extensions UI | 1161 // TODO(asargent) - We may want this to show up in the extensions UI |
1136 // eventually. (http://crbug.com/12547). | 1162 // eventually. (http://crbug.com/12547). |
1137 LOG(WARNING) << "Updated version of extension " << update->extension_id | 1163 LOG(WARNING) << "Updated version of extension " << update->extension_id |
1138 << " available, but requires chrome version " | 1164 << " available, but requires chrome version " |
1139 << update->browser_min_version; | 1165 << update->browser_min_version; |
1140 continue; | 1166 continue; |
1141 } | 1167 } |
1142 } | 1168 } |
| 1169 VLOG(2) << "will try to update " << update->extension_id; |
1143 result.push_back(i); | 1170 result.push_back(i); |
1144 } | 1171 } |
1145 return result; | 1172 return result; |
1146 } | 1173 } |
1147 | 1174 |
1148 void ExtensionUpdater::StartUpdateCheck(ManifestFetchData* fetch_data) { | 1175 void ExtensionUpdater::StartUpdateCheck(ManifestFetchData* fetch_data) { |
1149 AddToInProgress(fetch_data->extension_ids()); | 1176 AddToInProgress(fetch_data->extension_ids()); |
1150 | 1177 |
1151 scoped_ptr<ManifestFetchData> scoped_fetch_data(fetch_data); | 1178 scoped_ptr<ManifestFetchData> scoped_fetch_data(fetch_data); |
1152 if (CommandLine::ForCurrentProcess()->HasSwitch( | 1179 if (CommandLine::ForCurrentProcess()->HasSwitch( |
1153 switches::kDisableBackgroundNetworking)) | 1180 switches::kDisableBackgroundNetworking)) |
1154 return; | 1181 return; |
1155 | 1182 |
1156 std::deque<ManifestFetchData*>::const_iterator i; | 1183 std::deque<ManifestFetchData*>::const_iterator i; |
1157 for (i = manifests_pending_.begin(); i != manifests_pending_.end(); i++) { | 1184 for (i = manifests_pending_.begin(); i != manifests_pending_.end(); i++) { |
1158 if (fetch_data->full_url() == (*i)->full_url()) { | 1185 if (fetch_data->full_url() == (*i)->full_url()) { |
1159 // This url is already scheduled to be fetched. | 1186 // This url is already scheduled to be fetched. |
1160 return; | 1187 return; |
1161 } | 1188 } |
1162 } | 1189 } |
1163 | 1190 |
1164 if (manifest_fetcher_.get() != NULL) { | 1191 if (manifest_fetcher_.get() != NULL) { |
1165 if (manifest_fetcher_->GetURL() != fetch_data->full_url()) { | 1192 if (manifest_fetcher_->GetURL() != fetch_data->full_url()) { |
1166 manifests_pending_.push_back(scoped_fetch_data.release()); | 1193 manifests_pending_.push_back(scoped_fetch_data.release()); |
1167 } | 1194 } |
1168 } else { | 1195 } else { |
1169 UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength", | 1196 UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength", |
1170 fetch_data->full_url().possibly_invalid_spec().length()); | 1197 fetch_data->full_url().possibly_invalid_spec().length()); |
1171 | 1198 |
| 1199 if (VLOG_IS_ON(2)) { |
| 1200 const std::set<std::string>& id_set = fetch_data->extension_ids(); |
| 1201 std::vector<std::string> id_vector(id_set.begin(), id_set.end()); |
| 1202 std::string id_list = JoinString(id_vector, ','); |
| 1203 VLOG(2) << "Fetching " << fetch_data->full_url() << " for " |
| 1204 << id_list; |
| 1205 } |
| 1206 |
1172 current_manifest_fetch_.swap(scoped_fetch_data); | 1207 current_manifest_fetch_.swap(scoped_fetch_data); |
1173 manifest_fetcher_.reset(content::URLFetcher::Create( | 1208 manifest_fetcher_.reset(content::URLFetcher::Create( |
1174 kManifestFetcherId, fetch_data->full_url(), content::URLFetcher::GET, | 1209 kManifestFetcherId, fetch_data->full_url(), content::URLFetcher::GET, |
1175 this)); | 1210 this)); |
1176 manifest_fetcher_->SetRequestContext(profile_->GetRequestContext()); | 1211 manifest_fetcher_->SetRequestContext(profile_->GetRequestContext()); |
1177 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 1212 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
1178 net::LOAD_DO_NOT_SAVE_COOKIES | | 1213 net::LOAD_DO_NOT_SAVE_COOKIES | |
1179 net::LOAD_DISABLE_CACHE); | 1214 net::LOAD_DISABLE_CACHE); |
1180 manifest_fetcher_->Start(); | 1215 manifest_fetcher_->Start(); |
1181 } | 1216 } |
(...skipping 23 matching lines...) Expand all Loading... |
1205 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 1240 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
1206 net::LOAD_DO_NOT_SAVE_COOKIES | | 1241 net::LOAD_DO_NOT_SAVE_COOKIES | |
1207 net::LOAD_DISABLE_CACHE); | 1242 net::LOAD_DISABLE_CACHE); |
1208 // Download CRX files to a temp file. The blacklist is small and will be | 1243 // Download CRX files to a temp file. The blacklist is small and will be |
1209 // processed in memory, so it is fetched into a string. | 1244 // processed in memory, so it is fetched into a string. |
1210 if (id != ExtensionUpdater::kBlacklistAppID) { | 1245 if (id != ExtensionUpdater::kBlacklistAppID) { |
1211 extension_fetcher_->SaveResponseToTemporaryFile( | 1246 extension_fetcher_->SaveResponseToTemporaryFile( |
1212 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); | 1247 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); |
1213 } | 1248 } |
1214 | 1249 |
| 1250 VLOG(2) << "Starting fetch of " << url << " for " << id; |
| 1251 |
1215 extension_fetcher_->Start(); | 1252 extension_fetcher_->Start(); |
1216 current_extension_fetch_ = ExtensionFetch(id, url, hash, version); | 1253 current_extension_fetch_ = ExtensionFetch(id, url, hash, version); |
1217 } | 1254 } |
1218 } | 1255 } |
1219 | 1256 |
1220 void ExtensionUpdater::NotifyStarted() { | 1257 void ExtensionUpdater::NotifyStarted() { |
1221 content::NotificationService::current()->Notify( | 1258 content::NotificationService::current()->Notify( |
1222 chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED, | 1259 chrome::NOTIFICATION_EXTENSION_UPDATING_STARTED, |
1223 content::Source<Profile>(profile_), | 1260 content::Source<Profile>(profile_), |
1224 content::NotificationService::NoDetails()); | 1261 content::NotificationService::NoDetails()); |
(...skipping 20 matching lines...) Expand all Loading... |
1245 std::set<std::string>::const_iterator i; | 1282 std::set<std::string>::const_iterator i; |
1246 for (i = ids.begin(); i != ids.end(); ++i) | 1283 for (i = ids.begin(); i != ids.end(); ++i) |
1247 in_progress_ids_.insert(*i); | 1284 in_progress_ids_.insert(*i); |
1248 } | 1285 } |
1249 | 1286 |
1250 void ExtensionUpdater::RemoveFromInProgress(const std::set<std::string>& ids) { | 1287 void ExtensionUpdater::RemoveFromInProgress(const std::set<std::string>& ids) { |
1251 std::set<std::string>::const_iterator i; | 1288 std::set<std::string>::const_iterator i; |
1252 for (i = ids.begin(); i != ids.end(); ++i) | 1289 for (i = ids.begin(); i != ids.end(); ++i) |
1253 in_progress_ids_.erase(*i); | 1290 in_progress_ids_.erase(*i); |
1254 } | 1291 } |
OLD | NEW |