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/extensions/updater/extension_downloader.h" | 5 #include "chrome/browser/extensions/updater/extension_downloader.h" |
6 | 6 |
7 #include <utility> | 7 #include <utility> |
8 | 8 |
9 #include "base/bind.h" | 9 #include "base/bind.h" |
10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
(...skipping 132 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
143 return false; | 143 return false; |
144 } | 144 } |
145 | 145 |
146 // If the extension updates itself from the gallery, ignore any update URL | 146 // If the extension updates itself from the gallery, ignore any update URL |
147 // data. At the moment there is no extra data that an extension can | 147 // data. At the moment there is no extra data that an extension can |
148 // communicate to the the gallery update servers. | 148 // communicate to the the gallery update servers. |
149 std::string update_url_data; | 149 std::string update_url_data; |
150 if (!extension.UpdatesFromGallery()) | 150 if (!extension.UpdatesFromGallery()) |
151 update_url_data = delegate_->GetUpdateUrlData(extension.id()); | 151 update_url_data = delegate_->GetUpdateUrlData(extension.id()); |
152 | 152 |
153 // Make sure we use SSL for store-hosted extensions. | |
154 GURL update_url = extension.update_url(); | |
155 if (extension.UpdatesFromGallery() && !update_url.SchemeIsSecure()) | |
156 update_url = extension_urls::GetWebstoreUpdateUrl(); | |
157 | |
153 return AddExtensionData(extension.id(), *extension.version(), | 158 return AddExtensionData(extension.id(), *extension.version(), |
154 extension.GetType(), extension.update_url(), | 159 extension.GetType(), update_url, |
155 update_url_data); | 160 update_url_data); |
156 } | 161 } |
157 | 162 |
158 bool ExtensionDownloader::AddPendingExtension(const std::string& id, | 163 bool ExtensionDownloader::AddPendingExtension(const std::string& id, |
159 const GURL& update_url) { | 164 const GURL& update_url) { |
160 // Use a zero version to ensure that a pending extension will always | 165 // Use a zero version to ensure that a pending extension will always |
161 // be updated, and thus installed (assuming all extensions have | 166 // be updated, and thus installed (assuming all extensions have |
162 // non-zero versions). | 167 // non-zero versions). |
163 Version version("0.0.0.0"); | 168 Version version("0.0.0.0"); |
164 DCHECK(version.IsValid()); | 169 DCHECK(version.IsValid()); |
(...skipping 15 matching lines...) Expand all Loading... | |
180 fetches_preparing_.clear(); | 185 fetches_preparing_.clear(); |
181 } | 186 } |
182 | 187 |
183 void ExtensionDownloader::StartBlacklistUpdate( | 188 void ExtensionDownloader::StartBlacklistUpdate( |
184 const std::string& version, | 189 const std::string& version, |
185 const ManifestFetchData::PingData& ping_data) { | 190 const ManifestFetchData::PingData& ping_data) { |
186 // Note: it is very important that we use the https version of the update | 191 // Note: it is very important that we use the https version of the update |
187 // url here to avoid DNS hijacking of the blacklist, which is not validated | 192 // url here to avoid DNS hijacking of the blacklist, which is not validated |
188 // by a public key signature like .crx files are. | 193 // by a public key signature like .crx files are. |
189 ManifestFetchData* blacklist_fetch = | 194 ManifestFetchData* blacklist_fetch = |
190 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl(true)); | 195 new ManifestFetchData(extension_urls::GetWebstoreUpdateUrl()); |
196 DCHECK(blacklist_fetch->base_url().SchemeIsSecure()); | |
191 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", | 197 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", |
192 kDefaultInstallSource); | 198 kDefaultInstallSource); |
193 StartUpdateCheck(blacklist_fetch); | 199 StartUpdateCheck(blacklist_fetch); |
194 } | 200 } |
195 | 201 |
196 bool ExtensionDownloader::AddExtensionData(const std::string& id, | 202 bool ExtensionDownloader::AddExtensionData(const std::string& id, |
197 const Version& version, | 203 const Version& version, |
198 Extension::Type extension_type, | 204 Extension::Type extension_type, |
199 GURL update_url, | 205 GURL update_url, |
200 const std::string& update_url_data) { | 206 const std::string& update_url_data) { |
201 // Skip extensions with non-empty invalid update URLs. | 207 // Skip extensions with non-empty invalid update URLs. |
202 if (!update_url.is_empty() && !update_url.is_valid()) { | 208 if (!update_url.is_empty() && !update_url.is_valid()) { |
203 LOG(WARNING) << "Extension " << id << " has invalid update url " | 209 LOG(WARNING) << "Extension " << id << " has invalid update url " |
204 << update_url; | 210 << update_url; |
205 return false; | 211 return false; |
206 } | 212 } |
207 | 213 |
214 // Double-check that we're using https for webstore urls. | |
215 if (extension_urls::IsWebstoreUpdateUrl(update_url) && | |
216 !update_url.SchemeIsSecure() && | |
217 extension_urls::GetWebstoreUpdateUrl().SchemeIsSecure()) { | |
218 NOTREACHED() << "Refusing to send non-secure update check for " << id | |
219 << " (" << update_url.spec() << ")"; | |
220 return false; | |
221 } | |
222 | |
208 // Skip extensions with empty IDs. | 223 // Skip extensions with empty IDs. |
209 if (id.empty()) { | 224 if (id.empty()) { |
210 LOG(WARNING) << "Found extension with empty ID"; | 225 LOG(WARNING) << "Found extension with empty ID"; |
211 return false; | 226 return false; |
212 } | 227 } |
213 | 228 |
214 if (update_url.DomainIs("google.com")) { | 229 if (update_url.DomainIs("google.com")) { |
215 url_stats_.google_url_count++; | 230 url_stats_.google_url_count++; |
216 } else if (update_url.is_empty()) { | 231 } else if (update_url.is_empty()) { |
217 url_stats_.no_url_count++; | 232 url_stats_.no_url_count++; |
218 // Fill in default update URL. | 233 // Fill in default update URL. |
219 // | 234 update_url = extension_urls::GetWebstoreUpdateUrl(); |
220 // TODO(akalin): Figure out if we should use the HTTPS version. | |
221 update_url = extension_urls::GetWebstoreUpdateUrl(false); | |
222 } else { | 235 } else { |
223 url_stats_.other_url_count++; | 236 url_stats_.other_url_count++; |
224 } | 237 } |
225 | 238 |
226 switch (extension_type) { | 239 switch (extension_type) { |
227 case Extension::TYPE_THEME: | 240 case Extension::TYPE_THEME: |
228 ++url_stats_.theme_count; | 241 ++url_stats_.theme_count; |
229 break; | 242 break; |
230 case Extension::TYPE_EXTENSION: | 243 case Extension::TYPE_EXTENSION: |
231 case Extension::TYPE_USER_SCRIPT: | 244 case Extension::TYPE_USER_SCRIPT: |
232 ++url_stats_.extension_count; | 245 ++url_stats_.extension_count; |
233 break; | 246 break; |
234 case Extension::TYPE_HOSTED_APP: | 247 case Extension::TYPE_HOSTED_APP: |
235 case Extension::TYPE_PACKAGED_APP: | 248 case Extension::TYPE_PACKAGED_APP: |
236 ++url_stats_.app_count; | 249 ++url_stats_.app_count; |
237 break; | 250 break; |
238 case Extension::TYPE_UNKNOWN: | 251 case Extension::TYPE_UNKNOWN: |
239 default: | 252 default: |
240 ++url_stats_.pending_count; | 253 ++url_stats_.pending_count; |
241 break; | 254 break; |
242 } | 255 } |
243 | 256 |
244 std::vector<GURL> update_urls; | 257 std::vector<GURL> update_urls; |
245 update_urls.push_back(update_url); | 258 update_urls.push_back(update_url); |
246 // If UMA is enabled, also add to ManifestFetchData for the | 259 // If UMA is enabled, also add to ManifestFetchData for the |
247 // webstore update URL. | 260 // webstore update URL. |
248 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && | 261 if (!extension_urls::IsWebstoreUpdateUrl(update_url) && |
249 MetricsServiceHelper::IsMetricsReportingEnabled()) { | 262 MetricsServiceHelper::IsMetricsReportingEnabled()) { |
250 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl(false)); | 263 update_urls.push_back(extension_urls::GetWebstoreUpdateUrl()); |
251 } | 264 } |
252 | 265 |
253 for (size_t i = 0; i < update_urls.size(); ++i) { | 266 for (size_t i = 0; i < update_urls.size(); ++i) { |
254 DCHECK(!update_urls[i].is_empty()); | 267 DCHECK(!update_urls[i].is_empty()); |
255 DCHECK(update_urls[i].is_valid()); | 268 DCHECK(update_urls[i].is_valid()); |
256 | 269 |
257 std::string install_source = i == 0 ? | 270 std::string install_source = i == 0 ? |
258 kDefaultInstallSource : kNotFromWebstoreInstallSource; | 271 kDefaultInstallSource : kNotFromWebstoreInstallSource; |
259 | 272 |
260 ManifestFetchData::PingData ping_data; | 273 ManifestFetchData::PingData ping_data; |
(...skipping 164 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
425 return; | 438 return; |
426 } | 439 } |
427 | 440 |
428 // Examine the parsed manifest and kick off fetches of any new crx files. | 441 // Examine the parsed manifest and kick off fetches of any new crx files. |
429 std::vector<int> updates; | 442 std::vector<int> updates; |
430 DetermineUpdates(fetch_data, *results, &updates); | 443 DetermineUpdates(fetch_data, *results, &updates); |
431 for (size_t i = 0; i < updates.size(); i++) { | 444 for (size_t i = 0; i < updates.size(); i++) { |
432 const UpdateManifest::Result* update = &(results->list.at(updates[i])); | 445 const UpdateManifest::Result* update = &(results->list.at(updates[i])); |
433 const std::string& id = update->extension_id; | 446 const std::string& id = update->extension_id; |
434 not_updated.erase(id); | 447 not_updated.erase(id); |
448 | |
449 GURL crx_url = update->crx_url; | |
435 if (id != kBlacklistAppID) { | 450 if (id != kBlacklistAppID) { |
436 NotifyUpdateFound(update->extension_id); | 451 NotifyUpdateFound(update->extension_id); |
437 } else { | 452 } else { |
438 // The URL of the blacklist file is returned by the server and we need to | 453 // The URL of the blacklist file is returned by the server and we need to |
439 // be sure that we continue to be able to reliably detect whether a URL | 454 // be sure that we continue to be able to reliably detect whether a URL |
440 // references a blacklist file. | 455 // references a blacklist file. |
441 DCHECK(extension_urls::IsBlacklistUpdateUrl(update->crx_url)) | 456 DCHECK(extension_urls::IsBlacklistUpdateUrl(crx_url)) << crx_url; |
442 << update->crx_url; | 457 |
458 // Force https (crbug.com/129587). | |
459 if (!crx_url.SchemeIsSecure()) { | |
Aaron Boodman
2012/05/24 23:17:41
Will this affect non-store updates?
asargent_no_longer_on_chrome
2012/05/24 23:23:53
No, this is in the else block for the "if (id != k
| |
460 url_canon::Replacements<char> replacements; | |
461 std::string scheme("https"); | |
462 replacements.SetScheme(scheme.c_str(), | |
463 url_parse::Component(0, scheme.size())); | |
464 crx_url = crx_url.ReplaceComponents(replacements); | |
465 } | |
443 } | 466 } |
444 FetchUpdatedExtension(update->extension_id, update->crx_url, | 467 FetchUpdatedExtension(update->extension_id, crx_url, update->package_hash, |
445 update->package_hash, update->version); | 468 update->version); |
446 } | 469 } |
447 | 470 |
448 // If the manifest response included a <daystart> element, we want to save | 471 // If the manifest response included a <daystart> element, we want to save |
449 // that value for any extensions which had sent a ping in the request. | 472 // that value for any extensions which had sent a ping in the request. |
450 if (fetch_data.base_url().DomainIs("google.com") && | 473 if (fetch_data.base_url().DomainIs("google.com") && |
451 results->daystart_elapsed_seconds >= 0) { | 474 results->daystart_elapsed_seconds >= 0) { |
452 Time day_start = | 475 Time day_start = |
453 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); | 476 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); |
454 | 477 |
455 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); | 478 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); |
(...skipping 186 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
642 } | 665 } |
643 | 666 |
644 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { | 667 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { |
645 content::NotificationService::current()->Notify( | 668 content::NotificationService::current()->Notify( |
646 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, | 669 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, |
647 content::NotificationService::AllBrowserContextsAndSources(), | 670 content::NotificationService::AllBrowserContextsAndSources(), |
648 content::Details<const std::string>(&id)); | 671 content::Details<const std::string>(&id)); |
649 } | 672 } |
650 | 673 |
651 } // namespace extensions | 674 } // namespace extensions |
OLD | NEW |