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 "webkit/browser/appcache/appcache_update_job.h" | 5 #include "webkit/browser/appcache/appcache_update_job.h" |
6 | 6 |
7 #include "base/bind.h" | 7 #include "base/bind.h" |
8 #include "base/bind_helpers.h" | 8 #include "base/bind_helpers.h" |
9 #include "base/compiler_specific.h" | 9 #include "base/compiler_specific.h" |
10 #include "base/message_loop/message_loop.h" | 10 #include "base/message_loop/message_loop.h" |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
78 | 78 |
79 void SendErrorNotifications(const ErrorDetails& details) { | 79 void SendErrorNotifications(const ErrorDetails& details) { |
80 DCHECK(!details.message.empty()); | 80 DCHECK(!details.message.empty()); |
81 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); | 81 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); |
82 it != hosts_to_notify.end(); ++it) { | 82 it != hosts_to_notify.end(); ++it) { |
83 AppCacheFrontend* frontend = it->first; | 83 AppCacheFrontend* frontend = it->first; |
84 frontend->OnErrorEventRaised(it->second, details); | 84 frontend->OnErrorEventRaised(it->second, details); |
85 } | 85 } |
86 } | 86 } |
87 | 87 |
| 88 void SendLogMessage(const std::string& message) { |
| 89 for (NotifyHostMap::iterator it = hosts_to_notify.begin(); |
| 90 it != hosts_to_notify.end(); ++it) { |
| 91 AppCacheFrontend* frontend = it->first; |
| 92 for (HostIds::iterator id = it->second.begin(); |
| 93 id != it->second.end(); ++id) { |
| 94 frontend->OnLogMessage(*id, LOG_WARNING, message); |
| 95 } |
| 96 } |
| 97 } |
| 98 |
88 private: | 99 private: |
89 NotifyHostMap hosts_to_notify; | 100 NotifyHostMap hosts_to_notify; |
90 }; | 101 }; |
91 | 102 |
92 AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url, | 103 AppCacheUpdateJob::UrlToFetch::UrlToFetch(const GURL& url, |
93 bool checked, | 104 bool checked, |
94 AppCacheResponseInfo* info) | 105 AppCacheResponseInfo* info) |
95 : url(url), | 106 : url(url), |
96 storage_checked(checked), | 107 storage_checked(checked), |
97 existing_response_info(info) { | 108 existing_response_info(info) { |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
332 AppCacheUpdateJob::AppCacheUpdateJob(AppCacheService* service, | 343 AppCacheUpdateJob::AppCacheUpdateJob(AppCacheService* service, |
333 AppCacheGroup* group) | 344 AppCacheGroup* group) |
334 : service_(service), | 345 : service_(service), |
335 manifest_url_(group->manifest_url()), | 346 manifest_url_(group->manifest_url()), |
336 group_(group), | 347 group_(group), |
337 update_type_(UNKNOWN_TYPE), | 348 update_type_(UNKNOWN_TYPE), |
338 internal_state_(FETCH_MANIFEST), | 349 internal_state_(FETCH_MANIFEST), |
339 master_entries_completed_(0), | 350 master_entries_completed_(0), |
340 url_fetches_completed_(0), | 351 url_fetches_completed_(0), |
341 manifest_fetcher_(NULL), | 352 manifest_fetcher_(NULL), |
| 353 manifest_has_valid_mime_type_(false), |
342 stored_state_(UNSTORED), | 354 stored_state_(UNSTORED), |
343 storage_(service->storage()) { | 355 storage_(service->storage()) { |
344 service_->AddObserver(this); | 356 service_->AddObserver(this); |
345 } | 357 } |
346 | 358 |
347 AppCacheUpdateJob::~AppCacheUpdateJob() { | 359 AppCacheUpdateJob::~AppCacheUpdateJob() { |
348 if (service_) | 360 if (service_) |
349 service_->RemoveObserver(this); | 361 service_->RemoveObserver(this); |
350 if (internal_state_ != COMPLETED) | 362 if (internal_state_ != COMPLETED) |
351 Cancel(); | 363 Cancel(); |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
482 DCHECK_EQ(internal_state_, FETCH_MANIFEST); | 494 DCHECK_EQ(internal_state_, FETCH_MANIFEST); |
483 DCHECK_EQ(manifest_fetcher_, fetcher); | 495 DCHECK_EQ(manifest_fetcher_, fetcher); |
484 manifest_fetcher_ = NULL; | 496 manifest_fetcher_ = NULL; |
485 | 497 |
486 net::URLRequest* request = fetcher->request(); | 498 net::URLRequest* request = fetcher->request(); |
487 int response_code = -1; | 499 int response_code = -1; |
488 bool is_valid_response_code = false; | 500 bool is_valid_response_code = false; |
489 if (request->status().is_success()) { | 501 if (request->status().is_success()) { |
490 response_code = request->GetResponseCode(); | 502 response_code = request->GetResponseCode(); |
491 is_valid_response_code = (response_code / 100 == 2); | 503 is_valid_response_code = (response_code / 100 == 2); |
| 504 |
| 505 std::string mime_type; |
| 506 request->GetMimeType(&mime_type); |
| 507 manifest_has_valid_mime_type_ = (mime_type == "text/cache-manifest"); |
492 } | 508 } |
493 | 509 |
494 if (is_valid_response_code) { | 510 if (is_valid_response_code) { |
495 manifest_data_ = fetcher->manifest_data(); | 511 manifest_data_ = fetcher->manifest_data(); |
496 manifest_response_info_.reset( | 512 manifest_response_info_.reset( |
497 new net::HttpResponseInfo(request->response_info())); | 513 new net::HttpResponseInfo(request->response_info())); |
498 if (update_type_ == UPGRADE_ATTEMPT) | 514 if (update_type_ == UPGRADE_ATTEMPT) |
499 CheckIfManifestChanged(); // continues asynchronously | 515 CheckIfManifestChanged(); // continues asynchronously |
500 else | 516 else |
501 ContinueHandleManifestFetchCompleted(true); | 517 ContinueHandleManifestFetchCompleted(true); |
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
554 internal_state_ = NO_UPDATE; | 570 internal_state_ = NO_UPDATE; |
555 | 571 |
556 // Wait for pending master entries to download. | 572 // Wait for pending master entries to download. |
557 FetchMasterEntries(); | 573 FetchMasterEntries(); |
558 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps | 574 MaybeCompleteUpdate(); // if not done, run async 6.9.4 step 7 substeps |
559 return; | 575 return; |
560 } | 576 } |
561 | 577 |
562 Manifest manifest; | 578 Manifest manifest; |
563 if (!ParseManifest(manifest_url_, manifest_data_.data(), | 579 if (!ParseManifest(manifest_url_, manifest_data_.data(), |
564 manifest_data_.length(), manifest)) { | 580 manifest_data_.length(), |
| 581 manifest_has_valid_mime_type_ ? |
| 582 PARSE_MANIFEST_ALLOWING_INTERCEPTS : |
| 583 PARSE_MANIFEST_PER_STANDARD, |
| 584 manifest)) { |
565 const char* kFormatString = "Failed to parse manifest %s"; | 585 const char* kFormatString = "Failed to parse manifest %s"; |
566 const std::string message = base::StringPrintf(kFormatString, | 586 const std::string message = base::StringPrintf(kFormatString, |
567 manifest_url_.spec().c_str()); | 587 manifest_url_.spec().c_str()); |
568 HandleCacheFailure( | 588 HandleCacheFailure( |
569 ErrorDetails( | 589 ErrorDetails( |
570 message, SIGNATURE_ERROR, GURL(), 0, false /*is_cross_origin*/), | 590 message, SIGNATURE_ERROR, GURL(), 0, false /*is_cross_origin*/), |
571 MANIFEST_ERROR, | 591 MANIFEST_ERROR, |
572 GURL()); | 592 GURL()); |
573 VLOG(1) << message; | 593 VLOG(1) << message; |
574 return; | 594 return; |
575 } | 595 } |
576 | 596 |
577 // Proceed with update process. Section 6.9.4 steps 8-20. | 597 // Proceed with update process. Section 6.9.4 steps 8-20. |
578 internal_state_ = DOWNLOADING; | 598 internal_state_ = DOWNLOADING; |
579 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); | 599 inprogress_cache_ = new AppCache(storage_, storage_->NewCacheId()); |
580 BuildUrlFileList(manifest); | 600 BuildUrlFileList(manifest); |
581 inprogress_cache_->InitializeWithManifest(&manifest); | 601 inprogress_cache_->InitializeWithManifest(&manifest); |
582 | 602 |
583 // Associate all pending master hosts with the newly created cache. | 603 // Associate all pending master hosts with the newly created cache. |
584 for (PendingMasters::iterator it = pending_master_entries_.begin(); | 604 for (PendingMasters::iterator it = pending_master_entries_.begin(); |
585 it != pending_master_entries_.end(); ++it) { | 605 it != pending_master_entries_.end(); ++it) { |
586 PendingHosts& hosts = it->second; | 606 PendingHosts& hosts = it->second; |
587 for (PendingHosts::iterator host_it = hosts.begin(); | 607 for (PendingHosts::iterator host_it = hosts.begin(); |
588 host_it != hosts.end(); ++host_it) { | 608 host_it != hosts.end(); ++host_it) { |
589 (*host_it) | 609 (*host_it) |
590 ->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_); | 610 ->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_); |
591 } | 611 } |
592 } | 612 } |
593 | 613 |
| 614 if (manifest.did_ignore_intercept_namespaces) { |
| 615 // Must be done after associating all pending master hosts. |
| 616 std::string message( |
| 617 "Ignoring the INTERCEPT section of the application cache manifest " |
| 618 "because the content type is not text/cache-manifest"); |
| 619 LogConsoleMessageToAll(message); |
| 620 } |
| 621 |
594 group_->SetUpdateStatus(AppCacheGroup::DOWNLOADING); | 622 group_->SetUpdateStatus(AppCacheGroup::DOWNLOADING); |
595 NotifyAllAssociatedHosts(DOWNLOADING_EVENT); | 623 NotifyAllAssociatedHosts(DOWNLOADING_EVENT); |
596 FetchUrls(); | 624 FetchUrls(); |
597 FetchMasterEntries(); | 625 FetchMasterEntries(); |
598 MaybeCompleteUpdate(); // if not done, continues when async fetches complete | 626 MaybeCompleteUpdate(); // if not done, continues when async fetches complete |
599 } | 627 } |
600 | 628 |
601 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { | 629 void AppCacheUpdateJob::HandleUrlFetchCompleted(URLFetcher* fetcher) { |
602 DCHECK(internal_state_ == DOWNLOADING); | 630 DCHECK(internal_state_ == DOWNLOADING); |
603 | 631 |
(...skipping 347 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
951 DCHECK(url_file_list_.size() == url_fetches_completed_); | 979 DCHECK(url_file_list_.size() == url_fetches_completed_); |
952 NotifyAllProgress(GURL()); | 980 NotifyAllProgress(GURL()); |
953 } | 981 } |
954 | 982 |
955 void AppCacheUpdateJob::NotifyAllError(const ErrorDetails& details) { | 983 void AppCacheUpdateJob::NotifyAllError(const ErrorDetails& details) { |
956 HostNotifier host_notifier; | 984 HostNotifier host_notifier; |
957 AddAllAssociatedHostsToNotifier(&host_notifier); | 985 AddAllAssociatedHostsToNotifier(&host_notifier); |
958 host_notifier.SendErrorNotifications(details); | 986 host_notifier.SendErrorNotifications(details); |
959 } | 987 } |
960 | 988 |
| 989 void AppCacheUpdateJob::LogConsoleMessageToAll(const std::string& message) { |
| 990 HostNotifier host_notifier; |
| 991 AddAllAssociatedHostsToNotifier(&host_notifier); |
| 992 host_notifier.SendLogMessage(message); |
| 993 } |
| 994 |
961 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( | 995 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( |
962 HostNotifier* host_notifier) { | 996 HostNotifier* host_notifier) { |
963 // Collect hosts so we only send one notification per frontend. | 997 // Collect hosts so we only send one notification per frontend. |
964 // A host can only be associated with a single cache so no need to worry | 998 // A host can only be associated with a single cache so no need to worry |
965 // about duplicate hosts being added to the notifier. | 999 // about duplicate hosts being added to the notifier. |
966 if (inprogress_cache_.get()) { | 1000 if (inprogress_cache_.get()) { |
967 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); | 1001 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); |
968 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); | 1002 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); |
969 } | 1003 } |
970 | 1004 |
(...skipping 591 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1562 | 1596 |
1563 // Break the connection with the group so the group cannot call delete | 1597 // Break the connection with the group so the group cannot call delete |
1564 // on this object after we've posted a task to delete ourselves. | 1598 // on this object after we've posted a task to delete ourselves. |
1565 group_->SetUpdateStatus(AppCacheGroup::IDLE); | 1599 group_->SetUpdateStatus(AppCacheGroup::IDLE); |
1566 group_ = NULL; | 1600 group_ = NULL; |
1567 | 1601 |
1568 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 1602 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
1569 } | 1603 } |
1570 | 1604 |
1571 } // namespace appcache | 1605 } // namespace appcache |
OLD | NEW |