OLD | NEW |
1 // Copyright (c) 2010 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 "webkit/appcache/appcache_storage_impl.h" | 5 #include "webkit/appcache/appcache_storage_impl.h" |
6 | 6 |
7 #include "app/sql/connection.h" | 7 #include "app/sql/connection.h" |
8 #include "app/sql/transaction.h" | 8 #include "app/sql/transaction.h" |
9 #include "base/file_util.h" | 9 #include "base/file_util.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/message_loop.h" | 11 #include "base/message_loop.h" |
(...skipping 490 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
502 would_exceed_quota_ = true; | 502 would_exceed_quota_ = true; |
503 success_ = false; | 503 success_ = false; |
504 return; | 504 return; |
505 } | 505 } |
506 | 506 |
507 success_ = transaction.Commit(); | 507 success_ = transaction.Commit(); |
508 } | 508 } |
509 | 509 |
510 void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() { | 510 void AppCacheStorageImpl::StoreGroupAndCacheTask::RunCompleted() { |
511 if (success_) { | 511 if (success_) { |
512 // TODO(kkanetkar): Add to creation time when that's enabled. | |
513 storage_->origins_with_groups_.insert(group_->manifest_url().GetOrigin()); | 512 storage_->origins_with_groups_.insert(group_->manifest_url().GetOrigin()); |
514 if (cache_ != group_->newest_complete_cache()) { | 513 if (cache_ != group_->newest_complete_cache()) { |
515 cache_->set_complete(true); | 514 cache_->set_complete(true); |
516 group_->AddCache(cache_); | 515 group_->AddCache(cache_); |
517 } | 516 } |
| 517 if (group_->creation_time().is_null()) |
| 518 group_->set_creation_time(group_record_.creation_time); |
518 group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_); | 519 group_->AddNewlyDeletableResponseIds(&newly_deletable_response_ids_); |
519 } | 520 } |
520 FOR_EACH_DELEGATE(delegates_, | 521 FOR_EACH_DELEGATE(delegates_, |
521 OnGroupAndNewestCacheStored(group_, cache_, success_, | 522 OnGroupAndNewestCacheStored(group_, cache_, success_, |
522 would_exceed_quota_)); | 523 would_exceed_quota_)); |
523 group_ = NULL; | 524 group_ = NULL; |
524 cache_ = NULL; | 525 cache_ = NULL; |
525 } | 526 } |
526 | 527 |
527 void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() { | 528 void AppCacheStorageImpl::StoreGroupAndCacheTask::CancelCompletion() { |
528 // Overriden to safely drop our reference to the group and cache | 529 // Overriden to safely drop our reference to the group and cache |
529 // which are not thread safe refcounted. | 530 // which are not thread safe refcounted. |
530 DatabaseTask::CancelCompletion(); | 531 DatabaseTask::CancelCompletion(); |
531 group_ = NULL; | 532 group_ = NULL; |
532 cache_ = NULL; | 533 cache_ = NULL; |
533 } | 534 } |
534 | 535 |
535 // FindMainResponseTask ------- | 536 // FindMainResponseTask ------- |
536 | 537 |
537 class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask { | 538 class AppCacheStorageImpl::FindMainResponseTask : public DatabaseTask { |
538 public: | 539 public: |
539 FindMainResponseTask(AppCacheStorageImpl* storage, const GURL& url, | 540 FindMainResponseTask(AppCacheStorageImpl* storage, |
| 541 const GURL& url, |
| 542 const GURL& preferred_manifest_url, |
540 const AppCacheWorkingSet::GroupMap* groups_in_use) | 543 const AppCacheWorkingSet::GroupMap* groups_in_use) |
541 : DatabaseTask(storage), url_(url), cache_id_(kNoCacheId) { | 544 : DatabaseTask(storage), url_(url), |
| 545 preferred_manifest_url_(preferred_manifest_url), |
| 546 cache_id_(kNoCacheId) { |
542 if (groups_in_use) { | 547 if (groups_in_use) { |
543 for (AppCacheWorkingSet::GroupMap::const_iterator it = | 548 for (AppCacheWorkingSet::GroupMap::const_iterator it = |
544 groups_in_use->begin(); | 549 groups_in_use->begin(); |
545 it != groups_in_use->end(); ++it) { | 550 it != groups_in_use->end(); ++it) { |
546 AppCacheGroup* group = it->second; | 551 AppCacheGroup* group = it->second; |
547 AppCache* cache = group->newest_complete_cache(); | 552 AppCache* cache = group->newest_complete_cache(); |
548 if (group->is_obsolete() || !cache) | 553 if (group->is_obsolete() || !cache) |
549 continue; | 554 continue; |
550 cache_ids_in_use_.insert(cache->cache_id()); | 555 cache_ids_in_use_.insert(cache->cache_id()); |
551 } | 556 } |
552 } | 557 } |
553 } | 558 } |
554 | 559 |
555 virtual void Run(); | 560 virtual void Run(); |
556 virtual void RunCompleted(); | 561 virtual void RunCompleted(); |
557 | 562 |
| 563 private: |
| 564 typedef std::vector<AppCacheDatabase::FallbackNameSpaceRecord*> |
| 565 FallbackNameSpaceVector; |
| 566 bool FindExactMatch(int64 preferred_id); |
| 567 bool FindFallback(int64 preferred_id); |
| 568 bool FindFirstValidFallback(const FallbackNameSpaceVector& fallbacks); |
| 569 |
558 GURL url_; | 570 GURL url_; |
| 571 GURL preferred_manifest_url_; |
559 std::set<int64> cache_ids_in_use_; | 572 std::set<int64> cache_ids_in_use_; |
560 AppCacheEntry entry_; | 573 AppCacheEntry entry_; |
561 AppCacheEntry fallback_entry_; | 574 AppCacheEntry fallback_entry_; |
562 GURL fallback_url_; | 575 GURL fallback_url_; |
563 int64 cache_id_; | 576 int64 cache_id_; |
564 GURL manifest_url_; | 577 GURL manifest_url_; |
565 }; | 578 }; |
566 | 579 |
567 // Helpers for FindMainResponseTask::Run() | 580 // Helpers for FindMainResponseTask::Run() |
568 namespace { | 581 namespace { |
| 582 class SortByCachePreference |
| 583 : public std::binary_function< |
| 584 AppCacheDatabase::EntryRecord, |
| 585 AppCacheDatabase::EntryRecord, |
| 586 bool> { |
| 587 public: |
| 588 SortByCachePreference(int64 preferred_id, const std::set<int64>& in_use_ids) |
| 589 : preferred_id_(preferred_id), in_use_ids_(in_use_ids) { |
| 590 } |
| 591 bool operator()( |
| 592 const AppCacheDatabase::EntryRecord& lhs, |
| 593 const AppCacheDatabase::EntryRecord& rhs) { |
| 594 return compute_value(lhs) > compute_value(rhs); |
| 595 } |
| 596 private: |
| 597 int compute_value(const AppCacheDatabase::EntryRecord& entry) { |
| 598 if (entry.cache_id == preferred_id_) |
| 599 return 100; |
| 600 else if (in_use_ids_.find(entry.cache_id) != in_use_ids_.end()) |
| 601 return 50; |
| 602 return 0; |
| 603 } |
| 604 int64 preferred_id_; |
| 605 const std::set<int64>& in_use_ids_; |
| 606 }; |
| 607 |
569 bool SortByLength( | 608 bool SortByLength( |
570 const AppCacheDatabase::FallbackNameSpaceRecord& lhs, | 609 const AppCacheDatabase::FallbackNameSpaceRecord& lhs, |
571 const AppCacheDatabase::FallbackNameSpaceRecord& rhs) { | 610 const AppCacheDatabase::FallbackNameSpaceRecord& rhs) { |
572 return lhs.namespace_url.spec().length() > rhs.namespace_url.spec().length(); | 611 return lhs.namespace_url.spec().length() > rhs.namespace_url.spec().length(); |
573 } | 612 } |
574 | 613 |
575 class NetworkNamespaceHelper { | 614 class NetworkNamespaceHelper { |
576 public: | 615 public: |
577 explicit NetworkNamespaceHelper(AppCacheDatabase* database) | 616 explicit NetworkNamespaceHelper(AppCacheDatabase* database) |
578 : database_(database) { | 617 : database_(database) { |
(...skipping 23 matching lines...) Expand all Loading... |
602 urls->push_back(iter->namespace_url); | 641 urls->push_back(iter->namespace_url); |
603 ++iter; | 642 ++iter; |
604 } | 643 } |
605 } | 644 } |
606 | 645 |
607 // Key is cache id | 646 // Key is cache id |
608 typedef std::map<int64, std::vector<GURL> > WhiteListMap; | 647 typedef std::map<int64, std::vector<GURL> > WhiteListMap; |
609 WhiteListMap namespaces_map_; | 648 WhiteListMap namespaces_map_; |
610 AppCacheDatabase* database_; | 649 AppCacheDatabase* database_; |
611 }; | 650 }; |
| 651 |
| 652 bool FindManifestForEntry( |
| 653 const AppCacheDatabase::EntryRecord& entry_record, |
| 654 AppCacheDatabase* database, |
| 655 GURL* manifest_url_out) { |
| 656 AppCacheDatabase::GroupRecord group_record; |
| 657 if (!database->FindGroupForCache(entry_record.cache_id, &group_record)) { |
| 658 NOTREACHED() << "A cache without a group is not expected."; |
| 659 return false; |
| 660 } |
| 661 *manifest_url_out = group_record.manifest_url; |
| 662 return true; |
| 663 } |
| 664 |
612 } // namespace | 665 } // namespace |
613 | 666 |
614 void AppCacheStorageImpl::FindMainResponseTask::Run() { | 667 void AppCacheStorageImpl::FindMainResponseTask::Run() { |
615 // We have a bias for hits from caches that are in use. | 668 // NOTE: The heuristics around choosing amoungst multiple candidates |
| 669 // is underspecified, and just plain not fully understood. This needs |
| 670 // to be refined. |
616 | 671 |
617 // TODO(michaeln): The heuristics around choosing amoungst | 672 // The 'preferred_manifest_url' is the url of the manifest associated |
618 // multiple candidates is under specified, and just plain | 673 // with the page that opened or embedded the page being loaded now. |
619 // not fully understood. Refine these over time. In particular, | 674 // We have a strong preference to use resources from that cache. |
620 // * prefer candidates from newer caches | 675 // We also have a lesser bias to use resources from caches that are currently |
621 // * take into account the cache associated with the document | 676 // being used by other unrelated pages. |
622 // that initiated the navigation | 677 // TODO(michaeln): come up with a 'preferred_manifest_url' in more cases |
623 // * take into account the cache associated with the document | 678 // - when navigating a frame whose current contents are from an appcache |
624 // currently residing in the frame being navigated | 679 // - when clicking an href in a frame that is appcached |
| 680 int64 preferred_cache_id = kNoCacheId; |
| 681 if (!preferred_manifest_url_.is_empty()) { |
| 682 AppCacheDatabase::GroupRecord preferred_group; |
| 683 AppCacheDatabase::CacheRecord preferred_cache; |
| 684 if (database_->FindGroupForManifestUrl( |
| 685 preferred_manifest_url_, &preferred_group) && |
| 686 database_->FindCacheForGroup( |
| 687 preferred_group.group_id, &preferred_cache)) { |
| 688 preferred_cache_id = preferred_cache.cache_id; |
| 689 } |
| 690 } |
625 | 691 |
626 // First look for an exact match. We don't worry about whether | 692 if (FindExactMatch(preferred_cache_id) || |
627 // the containing cache is in-use in this loop because the | 693 FindFallback(preferred_cache_id)) { |
628 // storage class's FindResponseForMainRequest method does that | 694 // We found something. |
629 // as a pre-optimization. | 695 DCHECK(cache_id_ != kNoCacheId && !manifest_url_.is_empty()); |
| 696 return; |
| 697 } |
| 698 |
| 699 // We didn't find anything. |
| 700 DCHECK(cache_id_ == kNoCacheId && manifest_url_.is_empty()); |
| 701 } |
| 702 |
| 703 bool AppCacheStorageImpl:: |
| 704 FindMainResponseTask::FindExactMatch(int64 preferred_cache_id) { |
630 std::vector<AppCacheDatabase::EntryRecord> entries; | 705 std::vector<AppCacheDatabase::EntryRecord> entries; |
631 if (database_->FindEntriesForUrl(url_, &entries) && !entries.empty()) { | 706 if (database_->FindEntriesForUrl(url_, &entries) && !entries.empty()) { |
| 707 // Sort them in order of preference, from the preferred_cache first, |
| 708 // followed by hits from caches that are 'in use', then the rest. |
| 709 std::sort(entries.begin(), entries.end(), |
| 710 SortByCachePreference(preferred_cache_id, cache_ids_in_use_)); |
| 711 |
| 712 // Take the first with a valid, non-foreign entry. |
632 std::vector<AppCacheDatabase::EntryRecord>::iterator iter; | 713 std::vector<AppCacheDatabase::EntryRecord>::iterator iter; |
633 for (iter = entries.begin(); iter < entries.end(); ++iter) { | 714 for (iter = entries.begin(); iter < entries.end(); ++iter) { |
634 if (iter->flags & AppCacheEntry::FOREIGN) | 715 if ((iter->flags & AppCacheEntry::FOREIGN) || |
635 continue; | 716 !FindManifestForEntry(*iter, database_, &manifest_url_)) { |
636 | |
637 AppCacheDatabase::GroupRecord group_record; | |
638 if (!database_->FindGroupForCache(iter->cache_id, &group_record)) { | |
639 NOTREACHED() << "A cache without a group is not expected."; | |
640 continue; | 717 continue; |
641 } | 718 } |
642 entry_ = AppCacheEntry(iter->flags, iter->response_id); | 719 entry_ = AppCacheEntry(iter->flags, iter->response_id); |
643 cache_id_ = iter->cache_id; | 720 cache_id_ = iter->cache_id; |
644 manifest_url_ = group_record.manifest_url; | 721 return true; // We found an exact match. |
645 return; | |
646 } | 722 } |
647 } | 723 } |
| 724 return false; |
| 725 } |
648 | 726 |
649 // No exact matches, look at the fallback namespaces for this origin. | 727 bool AppCacheStorageImpl:: |
650 std::vector<AppCacheDatabase::FallbackNameSpaceRecord> fallbacks; | 728 FindMainResponseTask::FindFallback(int64 preferred_cache_id) { |
651 if (!database_->FindFallbackNameSpacesForOrigin(url_.GetOrigin(), &fallbacks) | 729 std::vector<AppCacheDatabase::FallbackNameSpaceRecord> all_fallbacks; |
652 || fallbacks.empty()) { | 730 if (!database_->FindFallbackNameSpacesForOrigin( |
653 return; | 731 url_.GetOrigin(), &all_fallbacks) |
| 732 || all_fallbacks.empty()) { |
| 733 return false; |
654 } | 734 } |
655 | 735 |
656 // Sort by namespace url string length, longest to shortest, | 736 // Sort them by length, longer matches within the same cache/bucket take |
657 // since longer matches trump when matching a url to a namespace. | 737 // precedence. |
658 std::sort(fallbacks.begin(), fallbacks.end(), SortByLength); | 738 std::sort(all_fallbacks.begin(), all_fallbacks.end(), SortByLength); |
659 | 739 |
660 bool has_candidate = false; | 740 // Filter the list and bin them into buckets. |
661 GURL candidate_fallback_namespace; | 741 NetworkNamespaceHelper network_namespace_helper(database_); |
| 742 FallbackNameSpaceVector preferred_fallbacks; |
| 743 FallbackNameSpaceVector inuse_fallbacks; |
| 744 FallbackNameSpaceVector other_fallbacks; |
662 std::vector<AppCacheDatabase::FallbackNameSpaceRecord>::iterator iter; | 745 std::vector<AppCacheDatabase::FallbackNameSpaceRecord>::iterator iter; |
663 NetworkNamespaceHelper network_namespace_helper(database_); | 746 for (iter = all_fallbacks.begin(); iter < all_fallbacks.end(); ++iter) { |
664 for (iter = fallbacks.begin(); iter < fallbacks.end(); ++iter) { | 747 // Skip those that aren't a prefix match. |
665 // Skip this fallback namespace if the requested url falls into a network | 748 if (!StartsWithASCII(url_.spec(), iter->namespace_url.spec(), true)) |
666 // namespace of the containing appcache. | 749 continue; |
| 750 |
| 751 // Skip fallback namespaces where the requested url falls into a network |
| 752 // namespace of its containing appcache. |
667 if (network_namespace_helper.IsInNetworkNamespace(url_, iter->cache_id)) | 753 if (network_namespace_helper.IsInNetworkNamespace(url_, iter->cache_id)) |
668 continue; | 754 continue; |
669 | 755 |
670 if (has_candidate && | 756 // Bin them into one of our three buckets. |
671 (candidate_fallback_namespace.spec().length() > | 757 if (iter->cache_id == preferred_cache_id) |
672 iter->namespace_url.spec().length())) { | 758 preferred_fallbacks.push_back(&(*iter)); |
673 break; // Stop iterating since longer namespace prefix matches win. | 759 else if (cache_ids_in_use_.find(iter->cache_id) != cache_ids_in_use_.end()) |
674 } | 760 inuse_fallbacks.push_back(&(*iter)); |
| 761 else |
| 762 other_fallbacks.push_back(&(*iter)); |
| 763 } |
675 | 764 |
676 if (StartsWithASCII(url_.spec(), iter->namespace_url.spec(), true)) { | 765 if (FindFirstValidFallback(preferred_fallbacks) || |
677 bool is_cache_in_use = cache_ids_in_use_.find(iter->cache_id) != | 766 FindFirstValidFallback(inuse_fallbacks) || |
678 cache_ids_in_use_.end(); | 767 FindFirstValidFallback(other_fallbacks)) |
| 768 return true; // We found one. |
679 | 769 |
680 bool take_new_candidate = !has_candidate || is_cache_in_use; | 770 // We didn't find anything. |
| 771 return false; |
| 772 } |
681 | 773 |
682 AppCacheDatabase::EntryRecord entry_record; | 774 bool AppCacheStorageImpl:: |
683 if (take_new_candidate && | 775 FindMainResponseTask::FindFirstValidFallback( |
684 database_->FindEntry(iter->cache_id, iter->fallback_entry_url, | 776 const FallbackNameSpaceVector& fallbacks) { |
685 &entry_record)) { | 777 // Take the first with a valid, non-foreign entry. |
686 if (entry_record.flags & AppCacheEntry::FOREIGN) | 778 FallbackNameSpaceVector::const_iterator iter; |
687 continue; | 779 for (iter = fallbacks.begin(); iter < fallbacks.end(); ++iter) { |
688 AppCacheDatabase::GroupRecord group_record; | 780 AppCacheDatabase::EntryRecord entry_record; |
689 if (!database_->FindGroupForCache(iter->cache_id, &group_record)) { | 781 if (database_->FindEntry((*iter)->cache_id, (*iter)->fallback_entry_url, |
690 NOTREACHED() << "A cache without a group is not expected."; | 782 &entry_record)) { |
691 continue; | 783 if ((entry_record.flags & AppCacheEntry::FOREIGN) || |
692 } | 784 !FindManifestForEntry(entry_record, database_, &manifest_url_)) { |
693 cache_id_ = iter->cache_id; | 785 continue; |
694 fallback_url_ = iter->fallback_entry_url; | |
695 manifest_url_ = group_record.manifest_url; | |
696 fallback_entry_ = AppCacheEntry( | |
697 entry_record.flags, entry_record.response_id); | |
698 if (is_cache_in_use) | |
699 break; // Stop iterating since we favor hits from in-use caches. | |
700 candidate_fallback_namespace = iter->namespace_url; | |
701 has_candidate = true; | |
702 } | 786 } |
| 787 cache_id_ = (*iter)->cache_id; |
| 788 fallback_url_ = (*iter)->fallback_entry_url; |
| 789 fallback_entry_ = AppCacheEntry( |
| 790 entry_record.flags, entry_record.response_id); |
| 791 return true; // We found one. |
703 } | 792 } |
704 } | 793 } |
| 794 return false; // We didn't find a match. |
705 } | 795 } |
706 | 796 |
707 void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() { | 797 void AppCacheStorageImpl::FindMainResponseTask::RunCompleted() { |
708 storage_->CheckPolicyAndCallOnMainResponseFound( | 798 storage_->CheckPolicyAndCallOnMainResponseFound( |
709 &delegates_, url_, entry_, fallback_url_, fallback_entry_, | 799 &delegates_, url_, entry_, fallback_url_, fallback_entry_, |
710 cache_id_, manifest_url_); | 800 cache_id_, manifest_url_); |
711 } | 801 } |
712 | 802 |
713 // MarkEntryAsForeignTask ------- | 803 // MarkEntryAsForeignTask ------- |
714 | 804 |
(...skipping 316 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1031 // the simple update case in a very heavy weight way (delete all and | 1121 // the simple update case in a very heavy weight way (delete all and |
1032 // the reinsert all over again). | 1122 // the reinsert all over again). |
1033 DCHECK(group && delegate && newest_cache); | 1123 DCHECK(group && delegate && newest_cache); |
1034 scoped_refptr<StoreGroupAndCacheTask> task( | 1124 scoped_refptr<StoreGroupAndCacheTask> task( |
1035 new StoreGroupAndCacheTask(this, group, newest_cache)); | 1125 new StoreGroupAndCacheTask(this, group, newest_cache)); |
1036 task->AddDelegate(GetOrCreateDelegateReference(delegate)); | 1126 task->AddDelegate(GetOrCreateDelegateReference(delegate)); |
1037 task->Schedule(); | 1127 task->Schedule(); |
1038 } | 1128 } |
1039 | 1129 |
1040 void AppCacheStorageImpl::FindResponseForMainRequest( | 1130 void AppCacheStorageImpl::FindResponseForMainRequest( |
1041 const GURL& url, Delegate* delegate) { | 1131 const GURL& url, const GURL& preferred_manifest_url, |
| 1132 Delegate* delegate) { |
1042 DCHECK(delegate); | 1133 DCHECK(delegate); |
1043 | 1134 |
1044 const GURL* url_ptr = &url; | 1135 const GURL* url_ptr = &url; |
1045 GURL url_no_ref; | 1136 GURL url_no_ref; |
1046 if (url.has_ref()) { | 1137 if (url.has_ref()) { |
1047 GURL::Replacements replacements; | 1138 GURL::Replacements replacements; |
1048 replacements.ClearRef(); | 1139 replacements.ClearRef(); |
1049 url_no_ref = url.ReplaceComponents(replacements); | 1140 url_no_ref = url.ReplaceComponents(replacements); |
1050 url_ptr = &url_no_ref; | 1141 url_ptr = &url_no_ref; |
1051 } | 1142 } |
1052 | 1143 |
1053 const GURL origin = url.GetOrigin(); | 1144 const GURL origin = url.GetOrigin(); |
1054 | 1145 |
1055 // First look in our working set for a direct hit without having to query | 1146 // First look in our working set for a direct hit without having to query |
1056 // the database. | 1147 // the database. |
1057 const AppCacheWorkingSet::GroupMap* groups_in_use = | 1148 const AppCacheWorkingSet::GroupMap* groups_in_use = |
1058 working_set()->GetGroupsInOrigin(origin); | 1149 working_set()->GetGroupsInOrigin(origin); |
1059 if (groups_in_use) { | 1150 if (groups_in_use) { |
1060 for (AppCacheWorkingSet::GroupMap::const_iterator it = | 1151 if (!preferred_manifest_url.is_empty()) { |
1061 groups_in_use->begin(); | 1152 AppCacheWorkingSet::GroupMap::const_iterator found = |
1062 it != groups_in_use->end(); ++it) { | 1153 groups_in_use->find(preferred_manifest_url); |
1063 AppCacheGroup* group = it->second; | 1154 if (found != groups_in_use->end() && |
1064 AppCache* cache = group->newest_complete_cache(); | 1155 FindResponseForMainRequestInGroup( |
1065 if (group->is_obsolete() || !cache) | 1156 found->second, *url_ptr, delegate)) { |
1066 continue; | 1157 return; |
1067 | 1158 } |
1068 AppCacheEntry* entry = cache->GetEntry(*url_ptr); | 1159 } else { |
1069 if (entry && !entry->IsForeign()) { | 1160 for (AppCacheWorkingSet::GroupMap::const_iterator it = |
1070 ScheduleSimpleTask(method_factory_.NewRunnableMethod( | 1161 groups_in_use->begin(); |
1071 &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse, | 1162 it != groups_in_use->end(); ++it) { |
1072 url, *entry, make_scoped_refptr(group), make_scoped_refptr(cache), | 1163 if (FindResponseForMainRequestInGroup( |
1073 make_scoped_refptr(GetOrCreateDelegateReference(delegate)))); | 1164 it->second, *url_ptr, delegate)) { |
1074 return; | 1165 return; |
| 1166 } |
1075 } | 1167 } |
1076 } | 1168 } |
1077 } | 1169 } |
1078 | 1170 |
1079 if (IsInitTaskComplete() && | 1171 if (IsInitTaskComplete() && |
1080 origins_with_groups_.find(origin) == origins_with_groups_.end()) { | 1172 origins_with_groups_.find(origin) == origins_with_groups_.end()) { |
1081 // No need to query the database, return async'ly but without going thru | 1173 // No need to query the database, return async'ly but without going thru |
1082 // the DB thread. | 1174 // the DB thread. |
1083 scoped_refptr<AppCacheGroup> no_group; | 1175 scoped_refptr<AppCacheGroup> no_group; |
1084 scoped_refptr<AppCache> no_cache; | 1176 scoped_refptr<AppCache> no_cache; |
1085 ScheduleSimpleTask(method_factory_.NewRunnableMethod( | 1177 ScheduleSimpleTask(method_factory_.NewRunnableMethod( |
1086 &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse, | 1178 &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse, |
1087 url, AppCacheEntry(), no_group, no_cache, | 1179 url, AppCacheEntry(), no_group, no_cache, |
1088 make_scoped_refptr(GetOrCreateDelegateReference(delegate)))); | 1180 make_scoped_refptr(GetOrCreateDelegateReference(delegate)))); |
1089 return; | 1181 return; |
1090 } | 1182 } |
1091 | 1183 |
1092 // We have to query the database, schedule a database task to do so. | 1184 // We have to query the database, schedule a database task to do so. |
1093 scoped_refptr<FindMainResponseTask> task( | 1185 scoped_refptr<FindMainResponseTask> task( |
1094 new FindMainResponseTask(this, *url_ptr, groups_in_use)); | 1186 new FindMainResponseTask(this, *url_ptr, preferred_manifest_url, |
| 1187 groups_in_use)); |
1095 task->AddDelegate(GetOrCreateDelegateReference(delegate)); | 1188 task->AddDelegate(GetOrCreateDelegateReference(delegate)); |
1096 task->Schedule(); | 1189 task->Schedule(); |
1097 } | 1190 } |
1098 | 1191 |
| 1192 bool AppCacheStorageImpl::FindResponseForMainRequestInGroup( |
| 1193 AppCacheGroup* group, const GURL& url, Delegate* delegate) { |
| 1194 AppCache* cache = group->newest_complete_cache(); |
| 1195 if (group->is_obsolete() || !cache) |
| 1196 return false; |
| 1197 |
| 1198 AppCacheEntry* entry = cache->GetEntry(url); |
| 1199 if (!entry || entry->IsForeign()) |
| 1200 return false; |
| 1201 |
| 1202 ScheduleSimpleTask(method_factory_.NewRunnableMethod( |
| 1203 &AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse, |
| 1204 url, *entry, make_scoped_refptr(group), make_scoped_refptr(cache), |
| 1205 make_scoped_refptr(GetOrCreateDelegateReference(delegate)))); |
| 1206 return true; |
| 1207 } |
| 1208 |
1099 void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse( | 1209 void AppCacheStorageImpl::DeliverShortCircuitedFindMainResponse( |
1100 const GURL& url, AppCacheEntry found_entry, | 1210 const GURL& url, AppCacheEntry found_entry, |
1101 scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> cache, | 1211 scoped_refptr<AppCacheGroup> group, scoped_refptr<AppCache> cache, |
1102 scoped_refptr<DelegateReference> delegate_ref) { | 1212 scoped_refptr<DelegateReference> delegate_ref) { |
1103 if (delegate_ref->delegate) { | 1213 if (delegate_ref->delegate) { |
1104 DelegateReferenceVector delegates(1, delegate_ref); | 1214 DelegateReferenceVector delegates(1, delegate_ref); |
1105 CheckPolicyAndCallOnMainResponseFound( | 1215 CheckPolicyAndCallOnMainResponseFound( |
1106 &delegates, url, found_entry, | 1216 &delegates, url, found_entry, |
1107 GURL(), AppCacheEntry(), | 1217 GURL(), AppCacheEntry(), |
1108 cache.get() ? cache->cache_id() : kNoCacheId, | 1218 cache.get() ? cache->cache_id() : kNoCacheId, |
(...skipping 270 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1379 Disable(); | 1489 Disable(); |
1380 if (!is_incognito_) { | 1490 if (!is_incognito_) { |
1381 VLOG(1) << "Deleting existing appcache data and starting over."; | 1491 VLOG(1) << "Deleting existing appcache data and starting over."; |
1382 AppCacheThread::PostTask(AppCacheThread::db(), FROM_HERE, | 1492 AppCacheThread::PostTask(AppCacheThread::db(), FROM_HERE, |
1383 NewRunnableFunction(DeleteDirectory, cache_directory_)); | 1493 NewRunnableFunction(DeleteDirectory, cache_directory_)); |
1384 } | 1494 } |
1385 } | 1495 } |
1386 } | 1496 } |
1387 | 1497 |
1388 } // namespace appcache | 1498 } // namespace appcache |
OLD | NEW |