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/appcache/appcache_update_job.h" | 5 #include "webkit/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.h" | 10 #include "base/message_loop.h" |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
102 job->service_->request_context()->CreateRequest(url, this))) { | 102 job->service_->request_context()->CreateRequest(url, this))) { |
103 } | 103 } |
104 | 104 |
105 AppCacheUpdateJob::URLFetcher::~URLFetcher() { | 105 AppCacheUpdateJob::URLFetcher::~URLFetcher() { |
106 } | 106 } |
107 | 107 |
108 void AppCacheUpdateJob::URLFetcher::Start() { | 108 void AppCacheUpdateJob::URLFetcher::Start() { |
109 request_->set_first_party_for_cookies(job_->manifest_url_); | 109 request_->set_first_party_for_cookies(job_->manifest_url_); |
110 request_->set_load_flags(request_->load_flags() | | 110 request_->set_load_flags(request_->load_flags() | |
111 net::LOAD_DISABLE_INTERCEPT); | 111 net::LOAD_DISABLE_INTERCEPT); |
112 if (existing_response_headers_) | 112 if (existing_response_headers_.get()) |
113 AddConditionalHeaders(existing_response_headers_); | 113 AddConditionalHeaders(existing_response_headers_.get()); |
114 request_->Start(); | 114 request_->Start(); |
115 } | 115 } |
116 | 116 |
117 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( | 117 void AppCacheUpdateJob::URLFetcher::OnReceivedRedirect( |
118 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { | 118 net::URLRequest* request, const GURL& new_url, bool* defer_redirect) { |
119 DCHECK(request_ == request); | 119 DCHECK(request_ == request); |
120 // Redirect is not allowed by the update process. | 120 // Redirect is not allowed by the update process. |
121 request->Cancel(); | 121 request->Cancel(); |
122 OnResponseCompleted(); | 122 OnResponseCompleted(); |
123 } | 123 } |
(...skipping 22 matching lines...) Expand all Loading... |
146 } | 146 } |
147 | 147 |
148 // Write response info to storage for URL fetches. Wait for async write | 148 // Write response info to storage for URL fetches. Wait for async write |
149 // completion before reading any response data. | 149 // completion before reading any response data. |
150 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { | 150 if (fetch_type_ == URL_FETCH || fetch_type_ == MASTER_ENTRY_FETCH) { |
151 response_writer_.reset(job_->CreateResponseWriter()); | 151 response_writer_.reset(job_->CreateResponseWriter()); |
152 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( | 152 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( |
153 new HttpResponseInfoIOBuffer( | 153 new HttpResponseInfoIOBuffer( |
154 new net::HttpResponseInfo(request->response_info()))); | 154 new net::HttpResponseInfo(request->response_info()))); |
155 response_writer_->WriteInfo( | 155 response_writer_->WriteInfo( |
156 io_buffer, | 156 io_buffer.get(), |
157 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); | 157 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); |
158 } else { | 158 } else { |
159 ReadResponseData(); | 159 ReadResponseData(); |
160 } | 160 } |
161 } else { | 161 } else { |
162 OnResponseCompleted(); | 162 OnResponseCompleted(); |
163 } | 163 } |
164 } | 164 } |
165 | 165 |
166 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( | 166 void AppCacheUpdateJob::URLFetcher::OnReadCompleted( |
167 net::URLRequest* request, int bytes_read) { | 167 net::URLRequest* request, int bytes_read) { |
168 DCHECK(request_ == request); | 168 DCHECK(request_ == request); |
169 bool data_consumed = true; | 169 bool data_consumed = true; |
170 if (request->status().is_success() && bytes_read > 0) { | 170 if (request->status().is_success() && bytes_read > 0) { |
171 data_consumed = ConsumeResponseData(bytes_read); | 171 data_consumed = ConsumeResponseData(bytes_read); |
172 if (data_consumed) { | 172 if (data_consumed) { |
173 bytes_read = 0; | 173 bytes_read = 0; |
174 while (request->Read(buffer_, kBufferSize, &bytes_read)) { | 174 while (request->Read(buffer_.get(), kBufferSize, &bytes_read)) { |
175 if (bytes_read > 0) { | 175 if (bytes_read > 0) { |
176 data_consumed = ConsumeResponseData(bytes_read); | 176 data_consumed = ConsumeResponseData(bytes_read); |
177 if (!data_consumed) | 177 if (!data_consumed) |
178 break; // wait for async data processing, then read more | 178 break; // wait for async data processing, then read more |
179 } else { | 179 } else { |
180 break; | 180 break; |
181 } | 181 } |
182 } | 182 } |
183 } | 183 } |
184 } | 184 } |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 return; | 219 return; |
220 } | 220 } |
221 ReadResponseData(); | 221 ReadResponseData(); |
222 } | 222 } |
223 | 223 |
224 void AppCacheUpdateJob::URLFetcher::ReadResponseData() { | 224 void AppCacheUpdateJob::URLFetcher::ReadResponseData() { |
225 InternalUpdateState state = job_->internal_state_; | 225 InternalUpdateState state = job_->internal_state_; |
226 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED) | 226 if (state == CACHE_FAILURE || state == CANCELLED || state == COMPLETED) |
227 return; | 227 return; |
228 int bytes_read = 0; | 228 int bytes_read = 0; |
229 request_->Read(buffer_, kBufferSize, &bytes_read); | 229 request_->Read(buffer_.get(), kBufferSize, &bytes_read); |
230 OnReadCompleted(request_.get(), bytes_read); | 230 OnReadCompleted(request_.get(), bytes_read); |
231 } | 231 } |
232 | 232 |
233 // Returns false if response data is processed asynchronously, in which | 233 // Returns false if response data is processed asynchronously, in which |
234 // case ReadResponseData will be invoked when it is safe to continue | 234 // case ReadResponseData will be invoked when it is safe to continue |
235 // reading more response data from the request. | 235 // reading more response data from the request. |
236 bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) { | 236 bool AppCacheUpdateJob::URLFetcher::ConsumeResponseData(int bytes_read) { |
237 DCHECK_GT(bytes_read, 0); | 237 DCHECK_GT(bytes_read, 0); |
238 switch (fetch_type_) { | 238 switch (fetch_type_) { |
239 case MANIFEST_FETCH: | 239 case MANIFEST_FETCH: |
240 case MANIFEST_REFETCH: | 240 case MANIFEST_REFETCH: |
241 manifest_data_.append(buffer_->data(), bytes_read); | 241 manifest_data_.append(buffer_->data(), bytes_read); |
242 break; | 242 break; |
243 case URL_FETCH: | 243 case URL_FETCH: |
244 case MASTER_ENTRY_FETCH: | 244 case MASTER_ENTRY_FETCH: |
245 DCHECK(response_writer_.get()); | 245 DCHECK(response_writer_.get()); |
246 response_writer_->WriteData( | 246 response_writer_->WriteData( |
247 buffer_, bytes_read, | 247 buffer_.get(), bytes_read, |
248 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); | 248 base::Bind(&URLFetcher::OnWriteComplete, base::Unretained(this))); |
249 return false; // wait for async write completion to continue reading | 249 return false; // wait for async write completion to continue reading |
250 default: | 250 default: |
251 NOTREACHED(); | 251 NOTREACHED(); |
252 } | 252 } |
253 return true; | 253 return true; |
254 } | 254 } |
255 | 255 |
256 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() { | 256 void AppCacheUpdateJob::URLFetcher::OnResponseCompleted() { |
257 // Retry for 503s where retry-after is 0. | 257 // Retry for 503s where retry-after is 0. |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
304 manifest_fetcher_(NULL), | 304 manifest_fetcher_(NULL), |
305 stored_state_(UNSTORED) { | 305 stored_state_(UNSTORED) { |
306 } | 306 } |
307 | 307 |
308 AppCacheUpdateJob::~AppCacheUpdateJob() { | 308 AppCacheUpdateJob::~AppCacheUpdateJob() { |
309 if (internal_state_ != COMPLETED) | 309 if (internal_state_ != COMPLETED) |
310 Cancel(); | 310 Cancel(); |
311 | 311 |
312 DCHECK(!manifest_fetcher_); | 312 DCHECK(!manifest_fetcher_); |
313 DCHECK(pending_url_fetches_.empty()); | 313 DCHECK(pending_url_fetches_.empty()); |
314 DCHECK(!inprogress_cache_); | 314 DCHECK(!inprogress_cache_.get()); |
315 DCHECK(pending_master_entries_.empty()); | 315 DCHECK(pending_master_entries_.empty()); |
316 DCHECK(master_entry_fetches_.empty()); | 316 DCHECK(master_entry_fetches_.empty()); |
317 | 317 |
318 if (group_) | 318 if (group_) |
319 group_->SetUpdateStatus(AppCacheGroup::IDLE); | 319 group_->SetUpdateStatus(AppCacheGroup::IDLE); |
320 } | 320 } |
321 | 321 |
322 void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, | 322 void AppCacheUpdateJob::StartUpdate(AppCacheHost* host, |
323 const GURL& new_master_resource) { | 323 const GURL& new_master_resource) { |
324 DCHECK(group_->update_job() == this); | 324 DCHECK(group_->update_job() == this); |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
418 // Asynchronously load response info for manifest from newest cache. | 418 // Asynchronously load response info for manifest from newest cache. |
419 service_->storage()->LoadResponseInfo(manifest_url_, group_->group_id(), | 419 service_->storage()->LoadResponseInfo(manifest_url_, group_->group_id(), |
420 entry->response_id(), this); | 420 entry->response_id(), this); |
421 } else { | 421 } else { |
422 manifest_fetcher_->Start(); | 422 manifest_fetcher_->Start(); |
423 } | 423 } |
424 } else { | 424 } else { |
425 DCHECK(internal_state_ == REFETCH_MANIFEST); | 425 DCHECK(internal_state_ == REFETCH_MANIFEST); |
426 DCHECK(manifest_response_info_.get()); | 426 DCHECK(manifest_response_info_.get()); |
427 manifest_fetcher_->set_existing_response_headers( | 427 manifest_fetcher_->set_existing_response_headers( |
428 manifest_response_info_->headers); | 428 manifest_response_info_->headers.get()); |
429 manifest_fetcher_->Start(); | 429 manifest_fetcher_->Start(); |
430 } | 430 } |
431 } | 431 } |
432 | 432 |
433 | 433 |
434 void AppCacheUpdateJob::HandleManifestFetchCompleted( | 434 void AppCacheUpdateJob::HandleManifestFetchCompleted( |
435 URLFetcher* fetcher) { | 435 URLFetcher* fetcher) { |
436 DCHECK_EQ(internal_state_, FETCH_MANIFEST); | 436 DCHECK_EQ(internal_state_, FETCH_MANIFEST); |
437 DCHECK_EQ(manifest_fetcher_, fetcher); | 437 DCHECK_EQ(manifest_fetcher_, fetcher); |
438 manifest_fetcher_ = NULL; | 438 manifest_fetcher_ = NULL; |
(...skipping 73 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
512 service_->storage()->NewCacheId()); | 512 service_->storage()->NewCacheId()); |
513 BuildUrlFileList(manifest); | 513 BuildUrlFileList(manifest); |
514 inprogress_cache_->InitializeWithManifest(&manifest); | 514 inprogress_cache_->InitializeWithManifest(&manifest); |
515 | 515 |
516 // Associate all pending master hosts with the newly created cache. | 516 // Associate all pending master hosts with the newly created cache. |
517 for (PendingMasters::iterator it = pending_master_entries_.begin(); | 517 for (PendingMasters::iterator it = pending_master_entries_.begin(); |
518 it != pending_master_entries_.end(); ++it) { | 518 it != pending_master_entries_.end(); ++it) { |
519 PendingHosts& hosts = it->second; | 519 PendingHosts& hosts = it->second; |
520 for (PendingHosts::iterator host_it = hosts.begin(); | 520 for (PendingHosts::iterator host_it = hosts.begin(); |
521 host_it != hosts.end(); ++host_it) { | 521 host_it != hosts.end(); ++host_it) { |
522 (*host_it)->AssociateIncompleteCache(inprogress_cache_, manifest_url_); | 522 (*host_it)-> |
| 523 AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_); |
523 } | 524 } |
524 } | 525 } |
525 | 526 |
526 group_->SetUpdateStatus(AppCacheGroup::DOWNLOADING); | 527 group_->SetUpdateStatus(AppCacheGroup::DOWNLOADING); |
527 NotifyAllAssociatedHosts(DOWNLOADING_EVENT); | 528 NotifyAllAssociatedHosts(DOWNLOADING_EVENT); |
528 FetchUrls(); | 529 FetchUrls(); |
529 FetchMasterEntries(); | 530 FetchMasterEntries(); |
530 MaybeCompleteUpdate(); // if not done, continues when async fetches complete | 531 MaybeCompleteUpdate(); // if not done, continues when async fetches complete |
531 } | 532 } |
532 | 533 |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
615 int response_code = request->status().is_success() | 616 int response_code = request->status().is_success() |
616 ? request->GetResponseCode() : -1; | 617 ? request->GetResponseCode() : -1; |
617 | 618 |
618 PendingMasters::iterator found = pending_master_entries_.find(url); | 619 PendingMasters::iterator found = pending_master_entries_.find(url); |
619 DCHECK(found != pending_master_entries_.end()); | 620 DCHECK(found != pending_master_entries_.end()); |
620 PendingHosts& hosts = found->second; | 621 PendingHosts& hosts = found->second; |
621 | 622 |
622 // Section 6.9.4. No update case: step 7.3, else step 22. | 623 // Section 6.9.4. No update case: step 7.3, else step 22. |
623 if (response_code / 100 == 2) { | 624 if (response_code / 100 == 2) { |
624 // Add fetched master entry to the appropriate cache. | 625 // Add fetched master entry to the appropriate cache. |
625 AppCache* cache = inprogress_cache_ ? inprogress_cache_.get() : | 626 AppCache* cache = inprogress_cache_.get() ? inprogress_cache_.get() : |
626 group_->newest_complete_cache(); | 627 group_->newest_complete_cache(); |
627 DCHECK(fetcher->response_writer()); | 628 DCHECK(fetcher->response_writer()); |
628 AppCacheEntry master_entry(AppCacheEntry::MASTER, | 629 AppCacheEntry master_entry(AppCacheEntry::MASTER, |
629 fetcher->response_writer()->response_id(), | 630 fetcher->response_writer()->response_id(), |
630 fetcher->response_writer()->amount_written()); | 631 fetcher->response_writer()->amount_written()); |
631 if (cache->AddOrModifyEntry(url, master_entry)) | 632 if (cache->AddOrModifyEntry(url, master_entry)) |
632 added_master_entries_.push_back(url); | 633 added_master_entries_.push_back(url); |
633 else | 634 else |
634 duplicate_response_ids_.push_back(master_entry.response_id()); | 635 duplicate_response_ids_.push_back(master_entry.response_id()); |
635 | 636 |
636 // In no-update case, associate host with the newest cache. | 637 // In no-update case, associate host with the newest cache. |
637 if (!inprogress_cache_) { | 638 if (!inprogress_cache_.get()) { |
638 // TODO(michaeln): defer until the updated cache has been stored | 639 // TODO(michaeln): defer until the updated cache has been stored |
639 DCHECK(cache == group_->newest_complete_cache()); | 640 DCHECK(cache == group_->newest_complete_cache()); |
640 for (PendingHosts::iterator host_it = hosts.begin(); | 641 for (PendingHosts::iterator host_it = hosts.begin(); |
641 host_it != hosts.end(); ++host_it) { | 642 host_it != hosts.end(); ++host_it) { |
642 (*host_it)->AssociateCompleteCache(cache); | 643 (*host_it)->AssociateCompleteCache(cache); |
643 } | 644 } |
644 } | 645 } |
645 } else { | 646 } else { |
646 HostNotifier host_notifier; | 647 HostNotifier host_notifier; |
647 for (PendingHosts::iterator host_it = hosts.begin(); | 648 for (PendingHosts::iterator host_it = hosts.begin(); |
648 host_it != hosts.end(); ++host_it) { | 649 host_it != hosts.end(); ++host_it) { |
649 AppCacheHost* host = *host_it; | 650 AppCacheHost* host = *host_it; |
650 host_notifier.AddHost(host); | 651 host_notifier.AddHost(host); |
651 | 652 |
652 // In downloading case, disassociate host from inprogress cache. | 653 // In downloading case, disassociate host from inprogress cache. |
653 if (inprogress_cache_) | 654 if (inprogress_cache_.get()) |
654 host->AssociateNoCache(GURL()); | 655 host->AssociateNoCache(GURL()); |
655 | 656 |
656 host->RemoveObserver(this); | 657 host->RemoveObserver(this); |
657 } | 658 } |
658 hosts.clear(); | 659 hosts.clear(); |
659 | 660 |
660 const char* kFormatString = "Master entry fetch failed (%d) %s"; | 661 const char* kFormatString = "Master entry fetch failed (%d) %s"; |
661 const std::string message = base::StringPrintf(kFormatString, | 662 const std::string message = base::StringPrintf(kFormatString, |
662 response_code, request->url().spec().c_str()); | 663 response_code, request->url().spec().c_str()); |
663 host_notifier.SendErrorNotifications(message); | 664 host_notifier.SendErrorNotifications(message); |
664 | 665 |
665 // In downloading case, update result is different if all master entries | 666 // In downloading case, update result is different if all master entries |
666 // failed vs. only some failing. | 667 // failed vs. only some failing. |
667 if (inprogress_cache_) { | 668 if (inprogress_cache_.get()) { |
668 // Only count successful downloads to know if all master entries failed. | 669 // Only count successful downloads to know if all master entries failed. |
669 pending_master_entries_.erase(found); | 670 pending_master_entries_.erase(found); |
670 --master_entries_completed_; | 671 --master_entries_completed_; |
671 | 672 |
672 // Section 6.9.4, step 22.3. | 673 // Section 6.9.4, step 22.3. |
673 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { | 674 if (update_type_ == CACHE_ATTEMPT && pending_master_entries_.empty()) { |
674 HandleCacheFailure(message); | 675 HandleCacheFailure(message); |
675 return; | 676 return; |
676 } | 677 } |
677 } | 678 } |
(...skipping 18 matching lines...) Expand all Loading... |
696 // an entry in the cache. | 697 // an entry in the cache. |
697 AppCacheEntry* entry = inprogress_cache_->GetEntry(manifest_url_); | 698 AppCacheEntry* entry = inprogress_cache_->GetEntry(manifest_url_); |
698 if (entry) { | 699 if (entry) { |
699 entry->add_types(AppCacheEntry::MANIFEST); | 700 entry->add_types(AppCacheEntry::MANIFEST); |
700 StoreGroupAndCache(); | 701 StoreGroupAndCache(); |
701 } else { | 702 } else { |
702 manifest_response_writer_.reset(CreateResponseWriter()); | 703 manifest_response_writer_.reset(CreateResponseWriter()); |
703 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( | 704 scoped_refptr<HttpResponseInfoIOBuffer> io_buffer( |
704 new HttpResponseInfoIOBuffer(manifest_response_info_.release())); | 705 new HttpResponseInfoIOBuffer(manifest_response_info_.release())); |
705 manifest_response_writer_->WriteInfo( | 706 manifest_response_writer_->WriteInfo( |
706 io_buffer, | 707 io_buffer.get(), |
707 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, | 708 base::Bind(&AppCacheUpdateJob::OnManifestInfoWriteComplete, |
708 base::Unretained(this))); | 709 base::Unretained(this))); |
709 } | 710 } |
710 } else { | 711 } else { |
711 VLOG(1) << "Request status: " << request->status().status() | 712 VLOG(1) << "Request status: " << request->status().status() |
712 << " error: " << request->status().error() | 713 << " error: " << request->status().error() |
713 << " response code: " << response_code; | 714 << " response code: " << response_code; |
714 ScheduleUpdateRetry(kRerunDelayMs); | 715 ScheduleUpdateRetry(kRerunDelayMs); |
715 HandleCacheFailure("Manifest changed during update, scheduling retry"); | 716 HandleCacheFailure("Manifest changed during update, scheduling retry"); |
716 } | 717 } |
717 } | 718 } |
718 | 719 |
719 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { | 720 void AppCacheUpdateJob::OnManifestInfoWriteComplete(int result) { |
720 if (result > 0) { | 721 if (result > 0) { |
721 scoped_refptr<net::StringIOBuffer> io_buffer( | 722 scoped_refptr<net::StringIOBuffer> io_buffer( |
722 new net::StringIOBuffer(manifest_data_)); | 723 new net::StringIOBuffer(manifest_data_)); |
723 manifest_response_writer_->WriteData( | 724 manifest_response_writer_->WriteData( |
724 io_buffer, manifest_data_.length(), | 725 io_buffer.get(), manifest_data_.length(), |
725 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, | 726 base::Bind(&AppCacheUpdateJob::OnManifestDataWriteComplete, |
726 base::Unretained(this))); | 727 base::Unretained(this))); |
727 } else { | 728 } else { |
728 HandleCacheFailure("Failed to write the manifest headers to storage"); | 729 HandleCacheFailure("Failed to write the manifest headers to storage"); |
729 } | 730 } |
730 } | 731 } |
731 | 732 |
732 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { | 733 void AppCacheUpdateJob::OnManifestDataWriteComplete(int result) { |
733 if (result > 0) { | 734 if (result > 0) { |
734 AppCacheEntry entry(AppCacheEntry::MANIFEST, | 735 AppCacheEntry entry(AppCacheEntry::MANIFEST, |
735 manifest_response_writer_->response_id(), | 736 manifest_response_writer_->response_id(), |
736 manifest_response_writer_->amount_written()); | 737 manifest_response_writer_->amount_written()); |
737 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) | 738 if (!inprogress_cache_->AddOrModifyEntry(manifest_url_, entry)) |
738 duplicate_response_ids_.push_back(entry.response_id()); | 739 duplicate_response_ids_.push_back(entry.response_id()); |
739 StoreGroupAndCache(); | 740 StoreGroupAndCache(); |
740 } else { | 741 } else { |
741 HandleCacheFailure("Failed to write the manifest data to storage"); | 742 HandleCacheFailure("Failed to write the manifest data to storage"); |
742 } | 743 } |
743 } | 744 } |
744 | 745 |
745 void AppCacheUpdateJob::StoreGroupAndCache() { | 746 void AppCacheUpdateJob::StoreGroupAndCache() { |
746 DCHECK(stored_state_ == UNSTORED); | 747 DCHECK(stored_state_ == UNSTORED); |
747 stored_state_ = STORING; | 748 stored_state_ = STORING; |
748 scoped_refptr<AppCache> newest_cache; | 749 scoped_refptr<AppCache> newest_cache; |
749 if (inprogress_cache_) | 750 if (inprogress_cache_.get()) |
750 newest_cache.swap(inprogress_cache_); | 751 newest_cache.swap(inprogress_cache_); |
751 else | 752 else |
752 newest_cache = group_->newest_complete_cache(); | 753 newest_cache = group_->newest_complete_cache(); |
753 newest_cache->set_update_time(base::Time::Now()); | 754 newest_cache->set_update_time(base::Time::Now()); |
754 | 755 |
755 // TODO(michaeln): dcheck is fishing for clues to crbug/95101 | 756 // TODO(michaeln): dcheck is fishing for clues to crbug/95101 |
756 DCHECK_EQ(manifest_url_, group_->manifest_url()); | 757 DCHECK_EQ(manifest_url_, group_->manifest_url()); |
757 service_->storage()->StoreGroupAndNewestCache(group_, newest_cache, | 758 service_->storage()->StoreGroupAndNewestCache(group_, newest_cache.get(), |
758 this); // async | 759 this); // async |
759 } | 760 } |
760 | 761 |
761 void AppCacheUpdateJob::OnGroupAndNewestCacheStored(AppCacheGroup* group, | 762 void AppCacheUpdateJob::OnGroupAndNewestCacheStored(AppCacheGroup* group, |
762 AppCache* newest_cache, | 763 AppCache* newest_cache, |
763 bool success, | 764 bool success, |
764 bool would_exceed_quota) { | 765 bool would_exceed_quota) { |
765 DCHECK(stored_state_ == STORING); | 766 DCHECK(stored_state_ == STORING); |
766 if (success) { | 767 if (success) { |
767 stored_state_ = STORED; | 768 stored_state_ = STORED; |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
807 HostNotifier host_notifier; | 808 HostNotifier host_notifier; |
808 AddAllAssociatedHostsToNotifier(&host_notifier); | 809 AddAllAssociatedHostsToNotifier(&host_notifier); |
809 host_notifier.SendErrorNotifications(error_message); | 810 host_notifier.SendErrorNotifications(error_message); |
810 } | 811 } |
811 | 812 |
812 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( | 813 void AppCacheUpdateJob::AddAllAssociatedHostsToNotifier( |
813 HostNotifier* host_notifier) { | 814 HostNotifier* host_notifier) { |
814 // Collect hosts so we only send one notification per frontend. | 815 // Collect hosts so we only send one notification per frontend. |
815 // A host can only be associated with a single cache so no need to worry | 816 // A host can only be associated with a single cache so no need to worry |
816 // about duplicate hosts being added to the notifier. | 817 // about duplicate hosts being added to the notifier. |
817 if (inprogress_cache_) { | 818 if (inprogress_cache_.get()) { |
818 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); | 819 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == CACHE_FAILURE); |
819 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); | 820 host_notifier->AddHosts(inprogress_cache_->associated_hosts()); |
820 } | 821 } |
821 | 822 |
822 AppCacheGroup::Caches old_caches = group_->old_caches(); | 823 AppCacheGroup::Caches old_caches = group_->old_caches(); |
823 for (AppCacheGroup::Caches::const_iterator it = old_caches.begin(); | 824 for (AppCacheGroup::Caches::const_iterator it = old_caches.begin(); |
824 it != old_caches.end(); ++it) { | 825 it != old_caches.end(); ++it) { |
825 host_notifier->AddHosts((*it)->associated_hosts()); | 826 host_notifier->AddHosts((*it)->associated_hosts()); |
826 } | 827 } |
827 | 828 |
(...skipping 26 matching lines...) Expand all Loading... |
854 return; | 855 return; |
855 } | 856 } |
856 | 857 |
857 // Load manifest data from storage to compare against fetched manifest. | 858 // Load manifest data from storage to compare against fetched manifest. |
858 manifest_response_reader_.reset( | 859 manifest_response_reader_.reset( |
859 service_->storage()->CreateResponseReader(manifest_url_, | 860 service_->storage()->CreateResponseReader(manifest_url_, |
860 group_->group_id(), | 861 group_->group_id(), |
861 entry->response_id())); | 862 entry->response_id())); |
862 read_manifest_buffer_ = new net::IOBuffer(kBufferSize); | 863 read_manifest_buffer_ = new net::IOBuffer(kBufferSize); |
863 manifest_response_reader_->ReadData( | 864 manifest_response_reader_->ReadData( |
864 read_manifest_buffer_, kBufferSize, | 865 read_manifest_buffer_.get(), kBufferSize, |
865 base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete, | 866 base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete, |
866 base::Unretained(this))); // async read | 867 base::Unretained(this))); // async read |
867 } | 868 } |
868 | 869 |
869 void AppCacheUpdateJob::OnManifestDataReadComplete(int result) { | 870 void AppCacheUpdateJob::OnManifestDataReadComplete(int result) { |
870 if (result > 0) { | 871 if (result > 0) { |
871 loaded_manifest_data_.append(read_manifest_buffer_->data(), result); | 872 loaded_manifest_data_.append(read_manifest_buffer_->data(), result); |
872 manifest_response_reader_->ReadData( | 873 manifest_response_reader_->ReadData( |
873 read_manifest_buffer_, kBufferSize, | 874 read_manifest_buffer_.get(), kBufferSize, |
874 base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete, | 875 base::Bind(&AppCacheUpdateJob::OnManifestDataReadComplete, |
875 base::Unretained(this))); // read more | 876 base::Unretained(this))); // read more |
876 } else { | 877 } else { |
877 read_manifest_buffer_ = NULL; | 878 read_manifest_buffer_ = NULL; |
878 manifest_response_reader_.reset(); | 879 manifest_response_reader_.reset(); |
879 ContinueHandleManifestFetchCompleted( | 880 ContinueHandleManifestFetchCompleted( |
880 result < 0 || manifest_data_ != loaded_manifest_data_); | 881 result < 0 || manifest_data_ != loaded_manifest_data_); |
881 } | 882 } |
882 } | 883 } |
883 | 884 |
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
952 URLFetcher* fetcher = new URLFetcher( | 953 URLFetcher* fetcher = new URLFetcher( |
953 url_to_fetch.url, URLFetcher::URL_FETCH, this); | 954 url_to_fetch.url, URLFetcher::URL_FETCH, this); |
954 if (url_to_fetch.existing_response_info.get()) { | 955 if (url_to_fetch.existing_response_info.get()) { |
955 DCHECK(group_->newest_complete_cache()); | 956 DCHECK(group_->newest_complete_cache()); |
956 AppCacheEntry* existing_entry = | 957 AppCacheEntry* existing_entry = |
957 group_->newest_complete_cache()->GetEntry(url_to_fetch.url); | 958 group_->newest_complete_cache()->GetEntry(url_to_fetch.url); |
958 DCHECK(existing_entry); | 959 DCHECK(existing_entry); |
959 DCHECK(existing_entry->response_id() == | 960 DCHECK(existing_entry->response_id() == |
960 url_to_fetch.existing_response_info->response_id()); | 961 url_to_fetch.existing_response_info->response_id()); |
961 fetcher->set_existing_response_headers( | 962 fetcher->set_existing_response_headers( |
962 url_to_fetch.existing_response_info->http_response_info()->headers); | 963 url_to_fetch.existing_response_info->http_response_info()-> |
| 964 headers.get()); |
963 fetcher->set_existing_entry(*existing_entry); | 965 fetcher->set_existing_entry(*existing_entry); |
964 } | 966 } |
965 fetcher->Start(); | 967 fetcher->Start(); |
966 pending_url_fetches_.insert( | 968 pending_url_fetches_.insert( |
967 PendingUrlFetches::value_type(url_to_fetch.url, fetcher)); | 969 PendingUrlFetches::value_type(url_to_fetch.url, fetcher)); |
968 } | 970 } |
969 } | 971 } |
970 } | 972 } |
971 | 973 |
972 void AppCacheUpdateJob::CancelAllUrlFetches() { | 974 void AppCacheUpdateJob::CancelAllUrlFetches() { |
(...skipping 17 matching lines...) Expand all Loading... |
990 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) | 992 if (entry.IsExplicit() || entry.IsFallback() || entry.IsIntercept()) |
991 return false; | 993 return false; |
992 | 994 |
993 // TODO(jennb): decide if entry should be skipped to expire it from cache | 995 // TODO(jennb): decide if entry should be skipped to expire it from cache |
994 return false; | 996 return false; |
995 } | 997 } |
996 | 998 |
997 bool AppCacheUpdateJob::AlreadyFetchedEntry(const GURL& url, | 999 bool AppCacheUpdateJob::AlreadyFetchedEntry(const GURL& url, |
998 int entry_type) { | 1000 int entry_type) { |
999 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE); | 1001 DCHECK(internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE); |
1000 AppCacheEntry* existing = inprogress_cache_ ? | 1002 AppCacheEntry* existing = inprogress_cache_.get() ? |
1001 inprogress_cache_->GetEntry(url) : | 1003 inprogress_cache_->GetEntry(url) : |
1002 group_->newest_complete_cache()->GetEntry(url); | 1004 group_->newest_complete_cache()->GetEntry(url); |
1003 if (existing) { | 1005 if (existing) { |
1004 existing->add_types(entry_type); | 1006 existing->add_types(entry_type); |
1005 return true; | 1007 return true; |
1006 } | 1008 } |
1007 return false; | 1009 return false; |
1008 } | 1010 } |
1009 | 1011 |
1010 void AppCacheUpdateJob::AddMasterEntryToFetchList(AppCacheHost* host, | 1012 void AppCacheUpdateJob::AddMasterEntryToFetchList(AppCacheHost* host, |
1011 const GURL& url, | 1013 const GURL& url, |
1012 bool is_new) { | 1014 bool is_new) { |
1013 DCHECK(!IsTerminating()); | 1015 DCHECK(!IsTerminating()); |
1014 | 1016 |
1015 if (internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE) { | 1017 if (internal_state_ == DOWNLOADING || internal_state_ == NO_UPDATE) { |
1016 AppCache* cache; | 1018 AppCache* cache; |
1017 if (inprogress_cache_) { | 1019 if (inprogress_cache_.get()) { |
1018 // always associate | 1020 // always associate |
1019 host->AssociateIncompleteCache(inprogress_cache_, manifest_url_); | 1021 host->AssociateIncompleteCache(inprogress_cache_.get(), manifest_url_); |
1020 cache = inprogress_cache_.get(); | 1022 cache = inprogress_cache_.get(); |
1021 } else { | 1023 } else { |
1022 cache = group_->newest_complete_cache(); | 1024 cache = group_->newest_complete_cache(); |
1023 } | 1025 } |
1024 | 1026 |
1025 // Update existing entry if it has already been fetched. | 1027 // Update existing entry if it has already been fetched. |
1026 AppCacheEntry* entry = cache->GetEntry(url); | 1028 AppCacheEntry* entry = cache->GetEntry(url); |
1027 if (entry) { | 1029 if (entry) { |
1028 entry->add_types(AppCacheEntry::MASTER); | 1030 entry->add_types(AppCacheEntry::MASTER); |
1029 if (internal_state_ == NO_UPDATE && !inprogress_cache_) { | 1031 if (internal_state_ == NO_UPDATE && !inprogress_cache_.get()) { |
1030 // only associate if have entry | 1032 // only associate if have entry |
1031 host->AssociateCompleteCache(cache); | 1033 host->AssociateCompleteCache(cache); |
1032 } | 1034 } |
1033 if (is_new) | 1035 if (is_new) |
1034 ++master_entries_completed_; // pretend fetching completed | 1036 ++master_entries_completed_; // pretend fetching completed |
1035 return; | 1037 return; |
1036 } | 1038 } |
1037 } | 1039 } |
1038 | 1040 |
1039 // Add to fetch list if not already fetching. | 1041 // Add to fetch list if not already fetching. |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1142 } | 1144 } |
1143 | 1145 |
1144 void AppCacheUpdateJob::OnResponseInfoLoaded( | 1146 void AppCacheUpdateJob::OnResponseInfoLoaded( |
1145 AppCacheResponseInfo* response_info, int64 response_id) { | 1147 AppCacheResponseInfo* response_info, int64 response_id) { |
1146 const net::HttpResponseInfo* http_info = response_info ? | 1148 const net::HttpResponseInfo* http_info = response_info ? |
1147 response_info->http_response_info() : NULL; | 1149 response_info->http_response_info() : NULL; |
1148 | 1150 |
1149 // Needed response info for a manifest fetch request. | 1151 // Needed response info for a manifest fetch request. |
1150 if (internal_state_ == FETCH_MANIFEST) { | 1152 if (internal_state_ == FETCH_MANIFEST) { |
1151 if (http_info) | 1153 if (http_info) |
1152 manifest_fetcher_->set_existing_response_headers(http_info->headers); | 1154 manifest_fetcher_-> |
| 1155 set_existing_response_headers(http_info->headers.get()); |
1153 manifest_fetcher_->Start(); | 1156 manifest_fetcher_->Start(); |
1154 return; | 1157 return; |
1155 } | 1158 } |
1156 | 1159 |
1157 LoadingResponses::iterator found = loading_responses_.find(response_id); | 1160 LoadingResponses::iterator found = loading_responses_.find(response_id); |
1158 DCHECK(found != loading_responses_.end()); | 1161 DCHECK(found != loading_responses_.end()); |
1159 const GURL& url = found->second; | 1162 const GURL& url = found->second; |
1160 | 1163 |
1161 if (!http_info) { | 1164 if (!http_info) { |
1162 LoadFromNewestCacheFailed(url, NULL); // no response found | 1165 LoadFromNewestCacheFailed(url, NULL); // no response found |
1163 } else { | 1166 } else { |
1164 // Check if response can be re-used according to HTTP caching semantics. | 1167 // Check if response can be re-used according to HTTP caching semantics. |
1165 // Responses with a "vary" header get treated as expired. | 1168 // Responses with a "vary" header get treated as expired. |
1166 const std::string name = "vary"; | 1169 const std::string name = "vary"; |
1167 std::string value; | 1170 std::string value; |
1168 void* iter = NULL; | 1171 void* iter = NULL; |
1169 if (!http_info->headers || | 1172 if (!http_info->headers.get() || |
1170 http_info->headers->RequiresValidation(http_info->request_time, | 1173 http_info->headers->RequiresValidation(http_info->request_time, |
1171 http_info->response_time, | 1174 http_info->response_time, |
1172 base::Time::Now()) || | 1175 base::Time::Now()) || |
1173 http_info->headers->EnumerateHeader(&iter, name, &value)) { | 1176 http_info->headers->EnumerateHeader(&iter, name, &value)) { |
1174 LoadFromNewestCacheFailed(url, response_info); | 1177 LoadFromNewestCacheFailed(url, response_info); |
1175 } else { | 1178 } else { |
1176 DCHECK(group_->newest_complete_cache()); | 1179 DCHECK(group_->newest_complete_cache()); |
1177 AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url); | 1180 AppCacheEntry* copy_me = group_->newest_complete_cache()->GetEntry(url); |
1178 DCHECK(copy_me); | 1181 DCHECK(copy_me); |
1179 DCHECK(copy_me->response_id() == response_id); | 1182 DCHECK(copy_me->response_id() == response_id); |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1303 (*host_it)->RemoveObserver(this); | 1306 (*host_it)->RemoveObserver(this); |
1304 } | 1307 } |
1305 } | 1308 } |
1306 | 1309 |
1307 pending_master_entries_.clear(); | 1310 pending_master_entries_.clear(); |
1308 } | 1311 } |
1309 | 1312 |
1310 void AppCacheUpdateJob::DiscardInprogressCache() { | 1313 void AppCacheUpdateJob::DiscardInprogressCache() { |
1311 service_->storage()->DoomResponses(manifest_url_, stored_response_ids_); | 1314 service_->storage()->DoomResponses(manifest_url_, stored_response_ids_); |
1312 | 1315 |
1313 if (!inprogress_cache_) { | 1316 if (!inprogress_cache_.get()) { |
1314 // We have to undo the changes we made, if any, to the existing cache. | 1317 // We have to undo the changes we made, if any, to the existing cache. |
1315 for (std::vector<GURL>::iterator iter = added_master_entries_.begin(); | 1318 for (std::vector<GURL>::iterator iter = added_master_entries_.begin(); |
1316 iter != added_master_entries_.end(); ++iter) { | 1319 iter != added_master_entries_.end(); ++iter) { |
1317 DCHECK(group_->newest_complete_cache()); | 1320 DCHECK(group_->newest_complete_cache()); |
1318 group_->newest_complete_cache()->RemoveEntry(*iter); | 1321 group_->newest_complete_cache()->RemoveEntry(*iter); |
1319 } | 1322 } |
1320 return; | 1323 return; |
1321 } | 1324 } |
1322 | 1325 |
1323 AppCache::AppCacheHosts& hosts = inprogress_cache_->associated_hosts(); | 1326 AppCache::AppCacheHosts& hosts = inprogress_cache_->associated_hosts(); |
(...skipping 14 matching lines...) Expand all Loading... |
1338 | 1341 |
1339 // Break the connection with the group so the group cannot call delete | 1342 // Break the connection with the group so the group cannot call delete |
1340 // on this object after we've posted a task to delete ourselves. | 1343 // on this object after we've posted a task to delete ourselves. |
1341 group_->SetUpdateStatus(AppCacheGroup::IDLE); | 1344 group_->SetUpdateStatus(AppCacheGroup::IDLE); |
1342 group_ = NULL; | 1345 group_ = NULL; |
1343 | 1346 |
1344 MessageLoop::current()->DeleteSoon(FROM_HERE, this); | 1347 MessageLoop::current()->DeleteSoon(FROM_HERE, this); |
1345 } | 1348 } |
1346 | 1349 |
1347 } // namespace appcache | 1350 } // namespace appcache |
OLD | NEW |