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

Side by Side Diff: chrome/browser/extensions/updater/extension_downloader.cc

Issue 10689097: Enforce the 'requirements' field in manifests. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 8 years, 5 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) 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 17 matching lines...) Expand all
28 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_details.h" 29 #include "content/public/browser/notification_details.h"
30 #include "content/public/browser/notification_service.h" 30 #include "content/public/browser/notification_service.h"
31 #include "net/base/load_flags.h" 31 #include "net/base/load_flags.h"
32 #include "net/url_request/url_fetcher.h" 32 #include "net/url_request/url_fetcher.h"
33 #include "net/url_request/url_request_status.h" 33 #include "net/url_request/url_request_status.h"
34 34
35 using base::Time; 35 using base::Time;
36 using base::TimeDelta; 36 using base::TimeDelta;
37 using content::BrowserThread; 37 using content::BrowserThread;
38 using extensions::ManifestFetchData;
38 39
39 namespace extensions { 40 namespace extensions {
40 41
41 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist"; 42 const char ExtensionDownloader::kBlacklistAppID[] = "com.google.crx.blacklist";
42 43
43 namespace { 44 namespace {
44 45
45 const char kNotFromWebstoreInstallSource[] = "notfromwebstore"; 46 const char kNotFromWebstoreInstallSource[] = "notfromwebstore";
46 const char kDefaultInstallSource[] = ""; 47 const char kDefaultInstallSource[] = "";
47 48
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 base::Bind(&CheckThatCRXIsReadable, crx_path)); 100 base::Bind(&CheckThatCRXIsReadable, crx_path));
100 } 101 }
101 } 102 }
102 103
103 } // namespace 104 } // namespace
104 105
105 ExtensionDownloader::ExtensionFetch::ExtensionFetch() 106 ExtensionDownloader::ExtensionFetch::ExtensionFetch()
106 : id(""), 107 : id(""),
107 url(), 108 url(),
108 package_hash(""), 109 package_hash(""),
109 version("") {} 110 version(""),
111 is_sync(false) {}
110 112
111 ExtensionDownloader::ExtensionFetch::ExtensionFetch( 113 ExtensionDownloader::ExtensionFetch::ExtensionFetch(
112 const std::string& id, 114 const std::string& id,
113 const GURL& url, 115 const GURL& url,
114 const std::string& package_hash, 116 const std::string& package_hash,
115 const std::string& version) 117 const std::string& version,
116 : id(id), url(url), package_hash(package_hash), version(version) {} 118 const bool is_sync)
119 : id(id), url(url), package_hash(package_hash), version(version),
120 is_sync(is_sync) {}
117 121
118 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {} 122 ExtensionDownloader::ExtensionFetch::~ExtensionFetch() {}
119 123
120 ExtensionDownloader::ExtensionDownloader( 124 ExtensionDownloader::ExtensionDownloader(
121 ExtensionDownloaderDelegate* delegate, 125 ExtensionDownloaderDelegate* delegate,
122 net::URLRequestContextGetter* request_context) 126 net::URLRequestContextGetter* request_context)
123 : delegate_(delegate), 127 : delegate_(delegate),
124 request_context_(request_context), 128 request_context_(request_context),
125 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) { 129 weak_ptr_factory_(ALLOW_THIS_IN_INITIALIZER_LIST(this)) {
126 DCHECK(delegate_); 130 DCHECK(delegate_);
(...skipping 18 matching lines...) Expand all
145 149
146 // If the extension updates itself from the gallery, ignore any update URL 150 // 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 151 // data. At the moment there is no extra data that an extension can
148 // communicate to the the gallery update servers. 152 // communicate to the the gallery update servers.
149 std::string update_url_data; 153 std::string update_url_data;
150 if (!extension.UpdatesFromGallery()) 154 if (!extension.UpdatesFromGallery())
151 update_url_data = delegate_->GetUpdateUrlData(extension.id()); 155 update_url_data = delegate_->GetUpdateUrlData(extension.id());
152 156
153 return AddExtensionData(extension.id(), *extension.version(), 157 return AddExtensionData(extension.id(), *extension.version(),
154 extension.GetType(), extension.update_url(), 158 extension.GetType(), extension.update_url(),
155 update_url_data); 159 update_url_data, false);
156 } 160 }
157 161
158 bool ExtensionDownloader::AddPendingExtension(const std::string& id, 162 bool ExtensionDownloader::AddPendingExtension(const std::string& id,
159 const GURL& update_url) { 163 const GURL& update_url,
164 bool is_sync) {
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());
165 170
166 return AddExtensionData(id, version, Extension::TYPE_UNKNOWN, update_url, ""); 171 return AddExtensionData(id, version, Extension::TYPE_UNKNOWN, update_url, "",
172 is_sync);
167 } 173 }
168 174
169 void ExtensionDownloader::StartAllPending() { 175 void ExtensionDownloader::StartAllPending() {
170 ReportStats(); 176 ReportStats();
171 url_stats_ = URLStats(); 177 url_stats_ = URLStats();
172 178
173 for (FetchMap::iterator it = fetches_preparing_.begin(); 179 for (FetchMap::iterator it = fetches_preparing_.begin();
174 it != fetches_preparing_.end(); ++it) { 180 it != fetches_preparing_.end(); ++it) {
175 const std::vector<ManifestFetchData*>& list = it->second; 181 const std::vector<ManifestFetchData*>& list = it->second;
176 for (size_t i = 0; i < list.size(); ++i) { 182 for (size_t i = 0; i < list.size(); ++i) {
177 StartUpdateCheck(list[i]); 183 StartUpdateCheck(list[i]);
178 } 184 }
179 } 185 }
180 fetches_preparing_.clear(); 186 fetches_preparing_.clear();
181 } 187 }
182 188
183 void ExtensionDownloader::StartBlacklistUpdate( 189 void ExtensionDownloader::StartBlacklistUpdate(
184 const std::string& version, 190 const std::string& version, const ManifestFetchData::PingData& ping_data) {
185 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(true));
191 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "", 196 blacklist_fetch->AddExtension(kBlacklistAppID, version, &ping_data, "",
192 kDefaultInstallSource); 197 kDefaultInstallSource, false /* is_sync */);
193 StartUpdateCheck(blacklist_fetch); 198 StartUpdateCheck(blacklist_fetch);
194 } 199 }
195 200
196 bool ExtensionDownloader::AddExtensionData(const std::string& id, 201 bool ExtensionDownloader::AddExtensionData(const std::string& id,
197 const Version& version, 202 const Version& version,
198 Extension::Type extension_type, 203 Extension::Type extension_type,
199 GURL update_url, 204 GURL update_url,
200 const std::string& update_url_data) { 205 const std::string& update_url_data,
206 bool is_sync) {
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
208 // Skip extensions with empty IDs. 214 // Skip extensions with empty IDs.
209 if (id.empty()) { 215 if (id.empty()) {
210 LOG(WARNING) << "Found extension with empty ID"; 216 LOG(WARNING) << "Found extension with empty ID";
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after
264 270
265 // Find or create a ManifestFetchData to add this extension to. 271 // Find or create a ManifestFetchData to add this extension to.
266 ManifestFetchData* fetch = NULL; 272 ManifestFetchData* fetch = NULL;
267 FetchMap::iterator existing_iter = fetches_preparing_.find(update_urls[i]); 273 FetchMap::iterator existing_iter = fetches_preparing_.find(update_urls[i]);
268 if (existing_iter != fetches_preparing_.end() && 274 if (existing_iter != fetches_preparing_.end() &&
269 !existing_iter->second.empty()) { 275 !existing_iter->second.empty()) {
270 // Try to add to the ManifestFetchData at the end of the list. 276 // Try to add to the ManifestFetchData at the end of the list.
271 ManifestFetchData* existing_fetch = existing_iter->second.back(); 277 ManifestFetchData* existing_fetch = existing_iter->second.back();
272 if (existing_fetch->AddExtension(id, version.GetString(), 278 if (existing_fetch->AddExtension(id, version.GetString(),
273 optional_ping_data, update_url_data, 279 optional_ping_data, update_url_data,
274 install_source)) { 280 install_source, is_sync)) {
275 fetch = existing_fetch; 281 fetch = existing_fetch;
276 } 282 }
277 } 283 }
278 if (!fetch) { 284 if (!fetch) {
279 // Otherwise add a new element to the list, if the list doesn't exist or 285 // Otherwise add a new element to the list, if the list doesn't exist or
280 // if its last element is already full. 286 // if its last element is already full.
281 fetch = new ManifestFetchData(update_urls[i]); 287 fetch = new ManifestFetchData(update_urls[i]);
282 fetches_preparing_[update_urls[i]].push_back(fetch); 288 fetches_preparing_[update_urls[i]].push_back(fetch);
283 bool added = fetch->AddExtension(id, version.GetString(), 289 bool added = fetch->AddExtension(id, version.GetString(),
284 optional_ping_data, 290 optional_ping_data,
285 update_url_data, 291 update_url_data,
286 install_source); 292 install_source,
293 is_sync);
287 DCHECK(added); 294 DCHECK(added);
288 } 295 }
289 } 296 }
290 297
291 return true; 298 return true;
292 } 299 }
293 300
294 void ExtensionDownloader::ReportStats() const { 301 void ExtensionDownloader::ReportStats() const {
295 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension", 302 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckExtension",
296 url_stats_.extension_count); 303 url_stats_.extension_count);
297 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme", 304 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckTheme",
298 url_stats_.theme_count); 305 url_stats_.theme_count);
299 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckApp", 306 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckApp",
300 url_stats_.app_count); 307 url_stats_.app_count);
301 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPending", 308 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckPending",
302 url_stats_.pending_count); 309 url_stats_.pending_count);
303 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl", 310 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckGoogleUrl",
304 url_stats_.google_url_count); 311 url_stats_.google_url_count);
305 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl", 312 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckOtherUrl",
306 url_stats_.other_url_count); 313 url_stats_.other_url_count);
307 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl", 314 UMA_HISTOGRAM_COUNTS_100("Extensions.UpdateCheckNoUrl",
308 url_stats_.no_url_count); 315 url_stats_.no_url_count);
309 } 316 }
310 317
311 void ExtensionDownloader::StartUpdateCheck(ManifestFetchData* fetch_data) { 318 void ExtensionDownloader::StartUpdateCheck(ManifestFetchData* fetch_data) {
312 scoped_ptr<ManifestFetchData> scoped_fetch_data(fetch_data); 319 scoped_ptr<ManifestFetchData> scoped_fetch_data(fetch_data);
313 const std::set<std::string>& id_set(fetch_data->extension_ids()); 320 const ManifestFetchData::ExtensionInfoMap& id_map(
321 fetch_data->extension_infos());
314 322
315 if (CommandLine::ForCurrentProcess()->HasSwitch( 323 if (CommandLine::ForCurrentProcess()->HasSwitch(
316 switches::kDisableBackgroundNetworking)) { 324 switches::kDisableBackgroundNetworking)) {
317 NotifyExtensionsDownloadFailed(id_set, 325 NotifyExtensionsDownloadFailed(id_map,
318 ExtensionDownloaderDelegate::DISABLED); 326 ExtensionDownloaderDelegate::DISABLED);
319 return; 327 return;
320 } 328 }
321 329
322 std::deque<ManifestFetchData*>::const_iterator i; 330 std::deque<ManifestFetchData*>::const_iterator i;
323 for (i = manifests_pending_.begin(); i != manifests_pending_.end(); i++) { 331 for (i = manifests_pending_.begin(); i != manifests_pending_.end(); i++) {
324 if (fetch_data->full_url() == (*i)->full_url()) { 332 if (fetch_data->full_url() == (*i)->full_url()) {
325 // This url is already scheduled to be fetched. 333 // This url is already scheduled to be fetched.
326 return; 334 return;
327 } 335 }
328 } 336 }
329 337
330 if (manifest_fetcher_.get() != NULL) { 338 if (manifest_fetcher_.get() != NULL) {
331 if (manifest_fetcher_->GetURL() != fetch_data->full_url()) { 339 if (manifest_fetcher_->GetURL() != fetch_data->full_url()) {
332 manifests_pending_.push_back(scoped_fetch_data.release()); 340 manifests_pending_.push_back(scoped_fetch_data.release());
333 } 341 }
334 } else { 342 } else {
335 UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength", 343 UMA_HISTOGRAM_COUNTS("Extensions.UpdateCheckUrlLength",
336 fetch_data->full_url().possibly_invalid_spec().length()); 344 fetch_data->full_url().possibly_invalid_spec().length());
337 345
338 if (VLOG_IS_ON(2)) { 346 if (VLOG_IS_ON(2)) {
339 std::vector<std::string> id_vector(id_set.begin(), id_set.end()); 347 std::vector<std::string> id_vector;
348 ManifestFetchData::ExtensionInfoMap::const_iterator it;
349 for (it = id_map.begin(); it != id_map.end(); ++it)
350 id_vector.push_back(it->first);
340 std::string id_list = JoinString(id_vector, ','); 351 std::string id_list = JoinString(id_vector, ',');
341 VLOG(2) << "Fetching " << fetch_data->full_url() << " for " 352 VLOG(2) << "Fetching " << fetch_data->full_url() << " for " << id_list;
342 << id_list;
343 } 353 }
344 354
345 current_manifest_fetch_.swap(scoped_fetch_data); 355 current_manifest_fetch_.swap(scoped_fetch_data);
346 manifest_fetcher_.reset(net::URLFetcher::Create( 356 manifest_fetcher_.reset(net::URLFetcher::Create(
347 kManifestFetcherId, fetch_data->full_url(), net::URLFetcher::GET, 357 kManifestFetcherId, fetch_data->full_url(), net::URLFetcher::GET,
348 this)); 358 this));
349 manifest_fetcher_->SetRequestContext(request_context_); 359 manifest_fetcher_->SetRequestContext(request_context_);
350 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 360 manifest_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
351 net::LOAD_DO_NOT_SAVE_COOKIES | 361 net::LOAD_DO_NOT_SAVE_COOKIES |
352 net::LOAD_DISABLE_CACHE); 362 net::LOAD_DISABLE_CACHE);
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
390 data, 400 data,
391 current_manifest_fetch_.release(), 401 current_manifest_fetch_.release(),
392 base::Bind(&ExtensionDownloader::HandleManifestResults, 402 base::Bind(&ExtensionDownloader::HandleManifestResults,
393 weak_ptr_factory_.GetWeakPtr()))); 403 weak_ptr_factory_.GetWeakPtr())));
394 safe_parser->Start(); 404 safe_parser->Start();
395 } else { 405 } else {
396 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546). 406 // TODO(asargent) Do exponential backoff here. (http://crbug.com/12546).
397 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec() 407 VLOG(1) << "Failed to fetch manifest '" << url.possibly_invalid_spec()
398 << "' response code:" << response_code; 408 << "' response code:" << response_code;
399 NotifyExtensionsDownloadFailed( 409 NotifyExtensionsDownloadFailed(
400 current_manifest_fetch_->extension_ids(), 410 current_manifest_fetch_->extension_infos(),
401 ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED); 411 ExtensionDownloaderDelegate::MANIFEST_FETCH_FAILED);
402 } 412 }
403 manifest_fetcher_.reset(); 413 manifest_fetcher_.reset();
404 current_manifest_fetch_.reset(); 414 current_manifest_fetch_.reset();
405 415
406 // If we have any pending manifest requests, fire off the next one. 416 // If we have any pending manifest requests, fire off the next one.
407 if (!manifests_pending_.empty()) { 417 if (!manifests_pending_.empty()) {
408 ManifestFetchData* manifest_fetch = manifests_pending_.front(); 418 ManifestFetchData* manifest_fetch = manifests_pending_.front();
409 manifests_pending_.pop_front(); 419 manifests_pending_.pop_front();
410 StartUpdateCheck(manifest_fetch); 420 StartUpdateCheck(manifest_fetch);
411 } 421 }
412 } 422 }
413 423
414 void ExtensionDownloader::HandleManifestResults( 424 void ExtensionDownloader::HandleManifestResults(
415 const ManifestFetchData& fetch_data, 425 const ManifestFetchData& fetch_data,
416 const UpdateManifest::Results* results) { 426 const UpdateManifest::Results* results) {
417 // Keep a list of extensions that will not be updated, so that the |delegate_| 427 // Keep a list of extensions that will not be updated, so that the |delegate_|
418 // can be notified once we're done here. 428 // can be notified once we're done here.
419 std::set<std::string> not_updated(fetch_data.extension_ids()); 429 ManifestFetchData::ExtensionInfoMap not_updated(fetch_data.extension_infos());
420 430
421 if (!results) { 431 if (!results) {
422 NotifyExtensionsDownloadFailed( 432 NotifyExtensionsDownloadFailed(
423 not_updated, 433 not_updated,
424 ExtensionDownloaderDelegate::MANIFEST_INVALID); 434 ExtensionDownloaderDelegate::MANIFEST_INVALID);
425 return; 435 return;
426 } 436 }
427 437
428 // Examine the parsed manifest and kick off fetches of any new crx files. 438 // Examine the parsed manifest and kick off fetches of any new crx files.
429 std::vector<int> updates; 439 std::vector<int> updates;
430 DetermineUpdates(fetch_data, *results, &updates); 440 DetermineUpdates(fetch_data, *results, &updates);
431 for (size_t i = 0; i < updates.size(); i++) { 441 for (size_t i = 0; i < updates.size(); i++) {
432 const UpdateManifest::Result* update = &(results->list.at(updates[i])); 442 const UpdateManifest::Result* update = &(results->list.at(updates[i]));
433 const std::string& id = update->extension_id; 443 const std::string& id = update->extension_id;
444 bool is_sync = not_updated[id].is_sync;
434 not_updated.erase(id); 445 not_updated.erase(id);
435 if (id != kBlacklistAppID) { 446 if (id != kBlacklistAppID) {
436 NotifyUpdateFound(update->extension_id); 447 NotifyUpdateFound(update->extension_id);
437 } else { 448 } else {
438 // The URL of the blacklist file is returned by the server and we need to 449 // 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 450 // be sure that we continue to be able to reliably detect whether a URL
440 // references a blacklist file. 451 // references a blacklist file.
441 DCHECK(extension_urls::IsBlacklistUpdateUrl(update->crx_url)) 452 DCHECK(extension_urls::IsBlacklistUpdateUrl(update->crx_url))
442 << update->crx_url; 453 << update->crx_url;
443 } 454 }
444 FetchUpdatedExtension(update->extension_id, update->crx_url, 455 FetchUpdatedExtension(update->extension_id, update->crx_url,
445 update->package_hash, update->version); 456 update->package_hash, update->version,
457 is_sync);
446 } 458 }
447 459
448 // If the manifest response included a <daystart> element, we want to save 460 // 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. 461 // that value for any extensions which had sent a ping in the request.
450 if (fetch_data.base_url().DomainIs("google.com") && 462 if (fetch_data.base_url().DomainIs("google.com") &&
451 results->daystart_elapsed_seconds >= 0) { 463 results->daystart_elapsed_seconds >= 0) {
452 Time day_start = 464 Time day_start =
453 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds); 465 Time::Now() - TimeDelta::FromSeconds(results->daystart_elapsed_seconds);
454 466
455 const std::set<std::string>& extension_ids = fetch_data.extension_ids(); 467 const ManifestFetchData::ExtensionInfoMap& extension_ids =
456 std::set<std::string>::const_iterator i; 468 fetch_data.extension_infos();
469 ManifestFetchData::ExtensionInfoMap::const_iterator i;
457 for (i = extension_ids.begin(); i != extension_ids.end(); i++) { 470 for (i = extension_ids.begin(); i != extension_ids.end(); i++) {
458 const std::string& id = *i; 471 const std::string& id = i->first;
459 ExtensionDownloaderDelegate::PingResult& result = ping_results_[id]; 472 ExtensionDownloaderDelegate::PingResult& result = ping_results_[id];
460 result.did_ping = fetch_data.DidPing(id, ManifestFetchData::ROLLCALL); 473 result.did_ping = fetch_data.DidPing(id, ManifestFetchData::ROLLCALL);
461 result.day_start = day_start; 474 result.day_start = day_start;
462 } 475 }
463 } 476 }
464 477
465 NotifyExtensionsDownloadFailed( 478 NotifyExtensionsDownloadFailed(
466 not_updated, 479 not_updated,
467 ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE); 480 ExtensionDownloaderDelegate::NO_UPDATE_AVAILABLE);
468 } 481 }
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after
534 } 547 }
535 VLOG(2) << "will try to update " << id; 548 VLOG(2) << "will try to update " << id;
536 result->push_back(i); 549 result->push_back(i);
537 } 550 }
538 } 551 }
539 552
540 // Begins (or queues up) download of an updated extension. 553 // Begins (or queues up) download of an updated extension.
541 void ExtensionDownloader::FetchUpdatedExtension(const std::string& id, 554 void ExtensionDownloader::FetchUpdatedExtension(const std::string& id,
542 const GURL& url, 555 const GURL& url,
543 const std::string& hash, 556 const std::string& hash,
544 const std::string& version) { 557 const std::string& version,
558 const bool is_sync) {
545 if (!url.is_valid()) { 559 if (!url.is_valid()) {
546 // TODO(asargent): This can sometimes be invalid. See crbug.com/130881. 560 // TODO(asargent): This can sometimes be invalid. See crbug.com/130881.
547 LOG(ERROR) << "Invalid URL: '" << url.possibly_invalid_spec() 561 LOG(ERROR) << "Invalid URL: '" << url.possibly_invalid_spec()
548 << "' for extension " << id; 562 << "' for extension " << id;
549 return; 563 return;
550 } 564 }
551 565
552 for (std::deque<ExtensionFetch>::const_iterator iter = 566 for (std::deque<ExtensionFetch>::const_iterator iter =
553 extensions_pending_.begin(); 567 extensions_pending_.begin();
554 iter != extensions_pending_.end(); ++iter) { 568 iter != extensions_pending_.end(); ++iter) {
555 if (iter->id == id || iter->url == url) { 569 if (iter->id == id || iter->url == url) {
556 return; // already scheduled 570 return; // already scheduled
557 } 571 }
558 } 572 }
559 573
560 if (extension_fetcher_.get() != NULL) { 574 if (extension_fetcher_.get() != NULL) {
561 if (extension_fetcher_->GetURL() != url) { 575 if (extension_fetcher_->GetURL() != url) {
562 extensions_pending_.push_back(ExtensionFetch(id, url, hash, version)); 576 extensions_pending_.push_back(ExtensionFetch(id, url, hash, version,
577 is_sync));
563 } 578 }
564 } else { 579 } else {
565 extension_fetcher_.reset(net::URLFetcher::Create( 580 extension_fetcher_.reset(net::URLFetcher::Create(
566 kExtensionFetcherId, url, net::URLFetcher::GET, this)); 581 kExtensionFetcherId, url, net::URLFetcher::GET, this));
567 extension_fetcher_->SetRequestContext(request_context_); 582 extension_fetcher_->SetRequestContext(request_context_);
568 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 583 extension_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
569 net::LOAD_DO_NOT_SAVE_COOKIES | 584 net::LOAD_DO_NOT_SAVE_COOKIES |
570 net::LOAD_DISABLE_CACHE); 585 net::LOAD_DISABLE_CACHE);
571 // Download CRX files to a temp file. The blacklist is small and will be 586 // Download CRX files to a temp file. The blacklist is small and will be
572 // processed in memory, so it is fetched into a string. 587 // processed in memory, so it is fetched into a string.
573 if (id != kBlacklistAppID) { 588 if (id != kBlacklistAppID) {
574 extension_fetcher_->SaveResponseToTemporaryFile( 589 extension_fetcher_->SaveResponseToTemporaryFile(
575 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE)); 590 BrowserThread::GetMessageLoopProxyForThread(BrowserThread::FILE));
576 } 591 }
577 592
578 VLOG(2) << "Starting fetch of " << url << " for " << id; 593 VLOG(2) << "Starting fetch of " << url << " for " << id;
579 594
580 extension_fetcher_->Start(); 595 extension_fetcher_->Start();
581 current_extension_fetch_ = ExtensionFetch(id, url, hash, version); 596 current_extension_fetch_ = ExtensionFetch(id, url, hash, version, is_sync);
582 } 597 }
583 } 598 }
584 599
585 void ExtensionDownloader::OnCRXFetchComplete( 600 void ExtensionDownloader::OnCRXFetchComplete(
586 const net::URLFetcher* source, 601 const net::URLFetcher* source,
587 const GURL& url, 602 const GURL& url,
588 const net::URLRequestStatus& status, 603 const net::URLRequestStatus& status,
589 int response_code) { 604 int response_code) {
590 const std::string& id = current_extension_fetch_.id; 605 const std::string& id = current_extension_fetch_.id;
591 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id]; 606 const ExtensionDownloaderDelegate::PingResult& ping = ping_results_[id];
(...skipping 15 matching lines...) Expand all
607 delegate_->OnBlacklistDownloadFinished( 622 delegate_->OnBlacklistDownloadFinished(
608 data, current_extension_fetch_.package_hash, 623 data, current_extension_fetch_.package_hash,
609 current_extension_fetch_.version, ping); 624 current_extension_fetch_.version, ping);
610 } else { 625 } else {
611 FilePath crx_path; 626 FilePath crx_path;
612 // Take ownership of the file at |crx_path|. 627 // Take ownership of the file at |crx_path|.
613 CHECK(source->GetResponseAsFilePath(true, &crx_path)); 628 CHECK(source->GetResponseAsFilePath(true, &crx_path));
614 RecordCRXWriteHistogram(true, crx_path); 629 RecordCRXWriteHistogram(true, crx_path);
615 delegate_->OnExtensionDownloadFinished(id, crx_path, url, 630 delegate_->OnExtensionDownloadFinished(id, crx_path, url,
616 current_extension_fetch_.version, 631 current_extension_fetch_.version,
617 ping); 632 ping,
633 current_extension_fetch_.is_sync);
618 } 634 }
619 } else { 635 } else {
620 // TODO(asargent) do things like exponential backoff, handling 636 // TODO(asargent) do things like exponential backoff, handling
621 // 503 Service Unavailable / Retry-After headers, etc. here. 637 // 503 Service Unavailable / Retry-After headers, etc. here.
622 // (http://crbug.com/12546). 638 // (http://crbug.com/12546).
623 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec() 639 VLOG(1) << "Failed to fetch extension '" << url.possibly_invalid_spec()
624 << "' response code:" << response_code; 640 << "' response code:" << response_code;
625 delegate_->OnExtensionDownloadFailed( 641 delegate_->OnExtensionDownloadFailed(
626 id, ExtensionDownloaderDelegate::CRX_FETCH_FAILED, ping); 642 id, ExtensionDownloaderDelegate::CRX_FETCH_FAILED, ping);
627 } 643 }
628 644
629 extension_fetcher_.reset(); 645 extension_fetcher_.reset();
630 current_extension_fetch_ = ExtensionFetch(); 646 current_extension_fetch_ = ExtensionFetch();
631 ping_results_.erase(id); 647 ping_results_.erase(id);
632 648
633 // If there are any pending downloads left, start the next one. 649 // If there are any pending downloads left, start the next one.
634 if (!extensions_pending_.empty()) { 650 if (!extensions_pending_.empty()) {
635 ExtensionFetch next = extensions_pending_.front(); 651 ExtensionFetch next = extensions_pending_.front();
636 extensions_pending_.pop_front(); 652 extensions_pending_.pop_front();
637 FetchUpdatedExtension(next.id, next.url, next.package_hash, next.version); 653 FetchUpdatedExtension(next.id, next.url, next.package_hash, next.version,
654 next.is_sync);
638 } 655 }
639 } 656 }
640 657
641 void ExtensionDownloader::NotifyExtensionsDownloadFailed( 658 void ExtensionDownloader::NotifyExtensionsDownloadFailed(
642 const std::set<std::string>& extension_ids, 659 const ManifestFetchData::ExtensionInfoMap& extension_ids,
643 ExtensionDownloaderDelegate::Error error) { 660 ExtensionDownloaderDelegate::Error error) {
644 for (std::set<std::string>::const_iterator it = extension_ids.begin(); 661 ManifestFetchData::ExtensionInfoMap::const_iterator it;
645 it != extension_ids.end(); ++it) { 662 for (it = extension_ids.begin(); it != extension_ids.end(); ++it) {
646 delegate_->OnExtensionDownloadFailed(*it, error, ping_results_[*it]); 663 delegate_->OnExtensionDownloadFailed(it->first, error,
647 ping_results_.erase(*it); 664 ping_results_[it->first]);
665 ping_results_.erase(it->first);
648 } 666 }
649 } 667 }
650 668
651 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) { 669 void ExtensionDownloader::NotifyUpdateFound(const std::string& id) {
652 content::NotificationService::current()->Notify( 670 content::NotificationService::current()->Notify(
653 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND, 671 chrome::NOTIFICATION_EXTENSION_UPDATE_FOUND,
654 content::NotificationService::AllBrowserContextsAndSources(), 672 content::NotificationService::AllBrowserContextsAndSources(),
655 content::Details<const std::string>(&id)); 673 content::Details<const std::string>(&id));
656 } 674 }
657 675
658 } // namespace extensions 676 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698