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