| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "content/browser/service_worker/service_worker_storage.h" | 5 #include "content/browser/service_worker/service_worker_storage.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/bind_helpers.h" | 9 #include "base/bind_helpers.h" |
| 10 #include "base/file_util.h" | 10 #include "base/file_util.h" |
| 11 #include "base/message_loop/message_loop.h" | 11 #include "base/message_loop/message_loop.h" |
| 12 #include "base/sequenced_task_runner.h" | 12 #include "base/sequenced_task_runner.h" |
| 13 #include "base/task_runner_util.h" | 13 #include "base/task_runner_util.h" |
| 14 #include "content/browser/service_worker/service_worker_context_core.h" | 14 #include "content/browser/service_worker/service_worker_context_core.h" |
| 15 #include "content/browser/service_worker/service_worker_disk_cache.h" | 15 #include "content/browser/service_worker/service_worker_disk_cache.h" |
| 16 #include "content/browser/service_worker/service_worker_info.h" | 16 #include "content/browser/service_worker/service_worker_info.h" |
| 17 #include "content/browser/service_worker/service_worker_metrics.h" | 17 #include "content/browser/service_worker/service_worker_metrics.h" |
| 18 #include "content/browser/service_worker/service_worker_registration.h" | 18 #include "content/browser/service_worker/service_worker_registration.h" |
| 19 #include "content/browser/service_worker/service_worker_utils.h" | 19 #include "content/browser/service_worker/service_worker_utils.h" |
| 20 #include "content/browser/service_worker/service_worker_version.h" | 20 #include "content/browser/service_worker/service_worker_version.h" |
| 21 #include "content/common/service_worker/service_worker_types.h" | 21 #include "content/common/service_worker/service_worker_types.h" |
| 22 #include "content/public/browser/browser_thread.h" | 22 #include "content/public/browser/browser_thread.h" |
| 23 #include "net/base/completion_callback.h" | 23 #include "net/base/completion_callback.h" |
| 24 #include "net/base/io_buffer.h" |
| 24 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
| 25 #include "webkit/browser/quota/quota_manager_proxy.h" | 26 #include "webkit/browser/quota/quota_manager_proxy.h" |
| 26 | 27 |
| 27 namespace content { | 28 namespace content { |
| 28 | 29 |
| 29 namespace { | 30 namespace { |
| 30 | 31 |
| 31 void RunSoon(const tracked_objects::Location& from_here, | 32 void RunSoon(const tracked_objects::Location& from_here, |
| 32 const base::Closure& closure) { | 33 const base::Closure& closure) { |
| 33 base::MessageLoop::current()->PostTask(from_here, closure); | 34 base::MessageLoop::current()->PostTask(from_here, closure); |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 65 return SERVICE_WORKER_OK; | 66 return SERVICE_WORKER_OK; |
| 66 case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND: | 67 case ServiceWorkerDatabase::STATUS_ERROR_NOT_FOUND: |
| 67 return SERVICE_WORKER_ERROR_NOT_FOUND; | 68 return SERVICE_WORKER_ERROR_NOT_FOUND; |
| 68 case ServiceWorkerDatabase::STATUS_ERROR_MAX: | 69 case ServiceWorkerDatabase::STATUS_ERROR_MAX: |
| 69 NOTREACHED(); | 70 NOTREACHED(); |
| 70 default: | 71 default: |
| 71 return SERVICE_WORKER_ERROR_FAILED; | 72 return SERVICE_WORKER_ERROR_FAILED; |
| 72 } | 73 } |
| 73 } | 74 } |
| 74 | 75 |
| 76 class ResponseComparer : public base::RefCounted<ResponseComparer> { |
| 77 public: |
| 78 ResponseComparer( |
| 79 base::WeakPtr<ServiceWorkerStorage> owner, |
| 80 scoped_ptr<ServiceWorkerResponseReader> lhs, |
| 81 scoped_ptr<ServiceWorkerResponseReader> rhs, |
| 82 const ServiceWorkerStorage::CompareCallback& callback) |
| 83 : owner_(owner), |
| 84 completion_callback_(callback), |
| 85 lhs_reader_(lhs.release()), |
| 86 rhs_reader_(rhs.release()), |
| 87 completion_count_(0), |
| 88 previous_result_(0) { |
| 89 } |
| 90 |
| 91 void Start(); |
| 92 |
| 93 private: |
| 94 friend class base::RefCounted<ResponseComparer>; |
| 95 |
| 96 static const int kBufferSize = 16 * 1024; |
| 97 |
| 98 ~ResponseComparer() {} |
| 99 void ReadInfos(); |
| 100 void OnReadInfoComplete(int result); |
| 101 void ReadSomeData(); |
| 102 void OnReadDataComplete(int result); |
| 103 |
| 104 base::WeakPtr<ServiceWorkerStorage> owner_; |
| 105 ServiceWorkerStorage::CompareCallback completion_callback_; |
| 106 scoped_ptr<ServiceWorkerResponseReader> lhs_reader_; |
| 107 scoped_refptr<HttpResponseInfoIOBuffer> lhs_info_; |
| 108 scoped_refptr<net::IOBuffer> lhs_buffer_; |
| 109 scoped_ptr<ServiceWorkerResponseReader> rhs_reader_; |
| 110 scoped_refptr<HttpResponseInfoIOBuffer> rhs_info_; |
| 111 scoped_refptr<net::IOBuffer> rhs_buffer_; |
| 112 int completion_count_; |
| 113 int previous_result_; |
| 114 DISALLOW_COPY_AND_ASSIGN(ResponseComparer); |
| 115 }; |
| 116 |
| 117 void ResponseComparer::Start() { |
| 118 lhs_buffer_ = new net::IOBuffer(kBufferSize); |
| 119 lhs_info_ = new HttpResponseInfoIOBuffer(); |
| 120 rhs_buffer_ = new net::IOBuffer(kBufferSize); |
| 121 rhs_info_ = new HttpResponseInfoIOBuffer(); |
| 122 |
| 123 ReadInfos(); |
| 124 } |
| 125 |
| 126 void ResponseComparer::ReadInfos() { |
| 127 lhs_reader_->ReadInfo( |
| 128 lhs_info_, |
| 129 base::Bind(&ResponseComparer::OnReadInfoComplete, |
| 130 this)); |
| 131 rhs_reader_->ReadInfo( |
| 132 rhs_info_, |
| 133 base::Bind(&ResponseComparer::OnReadInfoComplete, |
| 134 this)); |
| 135 } |
| 136 |
| 137 void ResponseComparer::OnReadInfoComplete(int result) { |
| 138 if (completion_callback_.is_null() || !owner_) |
| 139 return; |
| 140 if (result < 0) { |
| 141 completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false); |
| 142 completion_callback_.Reset(); |
| 143 return; |
| 144 } |
| 145 if (++completion_count_ != 2) |
| 146 return; |
| 147 |
| 148 if (lhs_info_->response_data_size != rhs_info_->response_data_size) { |
| 149 completion_callback_.Run(SERVICE_WORKER_OK, false); |
| 150 return; |
| 151 } |
| 152 ReadSomeData(); |
| 153 } |
| 154 |
| 155 void ResponseComparer::ReadSomeData() { |
| 156 completion_count_ = 0; |
| 157 lhs_reader_->ReadData( |
| 158 lhs_buffer_, |
| 159 kBufferSize, |
| 160 base::Bind(&ResponseComparer::OnReadDataComplete, this)); |
| 161 rhs_reader_->ReadData( |
| 162 rhs_buffer_, |
| 163 kBufferSize, |
| 164 base::Bind(&ResponseComparer::OnReadDataComplete, this)); |
| 165 } |
| 166 |
| 167 void ResponseComparer::OnReadDataComplete(int result) { |
| 168 if (completion_callback_.is_null() || !owner_) |
| 169 return; |
| 170 if (result < 0) { |
| 171 completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false); |
| 172 completion_callback_.Reset(); |
| 173 return; |
| 174 } |
| 175 if (++completion_count_ != 2) { |
| 176 previous_result_ = result; |
| 177 return; |
| 178 } |
| 179 |
| 180 // TODO(michaeln): Probably shouldn't assume that the amounts read from |
| 181 // each reader will always be the same. This would wrongly signal false |
| 182 // in that case. |
| 183 if (result != previous_result_) { |
| 184 completion_callback_.Run(SERVICE_WORKER_OK, false); |
| 185 return; |
| 186 } |
| 187 |
| 188 if (result == 0) { |
| 189 completion_callback_.Run(SERVICE_WORKER_OK, true); |
| 190 return; |
| 191 } |
| 192 |
| 193 int compare_result = |
| 194 memcmp(lhs_buffer_->data(), rhs_buffer_->data(), result); |
| 195 if (compare_result != 0) { |
| 196 completion_callback_.Run(SERVICE_WORKER_OK, false); |
| 197 return; |
| 198 } |
| 199 |
| 200 ReadSomeData(); |
| 201 } |
| 202 |
| 75 } // namespace | 203 } // namespace |
| 76 | 204 |
| 77 ServiceWorkerStorage::InitialData::InitialData() | 205 ServiceWorkerStorage::InitialData::InitialData() |
| 78 : next_registration_id(kInvalidServiceWorkerRegistrationId), | 206 : next_registration_id(kInvalidServiceWorkerRegistrationId), |
| 79 next_version_id(kInvalidServiceWorkerVersionId), | 207 next_version_id(kInvalidServiceWorkerVersionId), |
| 80 next_resource_id(kInvalidServiceWorkerResourceId) { | 208 next_resource_id(kInvalidServiceWorkerResourceId) { |
| 81 } | 209 } |
| 82 | 210 |
| 83 ServiceWorkerStorage::InitialData::~InitialData() { | 211 ServiceWorkerStorage::InitialData::~InitialData() { |
| 84 } | 212 } |
| (...skipping 299 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 384 DCHECK_NE(kInvalidServiceWorkerResponseId, id); | 512 DCHECK_NE(kInvalidServiceWorkerResponseId, id); |
| 385 database_task_runner_->PostTask( | 513 database_task_runner_->PostTask( |
| 386 FROM_HERE, | 514 FROM_HERE, |
| 387 base::Bind(base::IgnoreResult( | 515 base::Bind(base::IgnoreResult( |
| 388 &ServiceWorkerDatabase::PurgeUncommittedResourceIds), | 516 &ServiceWorkerDatabase::PurgeUncommittedResourceIds), |
| 389 base::Unretained(database_.get()), | 517 base::Unretained(database_.get()), |
| 390 std::set<int64>(&id, &id + 1))); | 518 std::set<int64>(&id, &id + 1))); |
| 391 StartPurgingResources(std::vector<int64>(1, id)); | 519 StartPurgingResources(std::vector<int64>(1, id)); |
| 392 } | 520 } |
| 393 | 521 |
| 522 void ServiceWorkerStorage::CompareScriptResources( |
| 523 int64 lhs_id, int64 rhs_id, |
| 524 const CompareCallback& callback) { |
| 525 DCHECK(!callback.is_null()); |
| 526 scoped_refptr<ResponseComparer> comparer = |
| 527 new ResponseComparer(weak_factory_.GetWeakPtr(), |
| 528 CreateResponseReader(lhs_id), |
| 529 CreateResponseReader(rhs_id), |
| 530 callback); |
| 531 comparer->Start(); // It deletes itself when done. |
| 532 } |
| 533 |
| 394 void ServiceWorkerStorage::DeleteAndStartOver(const StatusCallback& callback) { | 534 void ServiceWorkerStorage::DeleteAndStartOver(const StatusCallback& callback) { |
| 395 Disable(); | 535 Disable(); |
| 396 | 536 |
| 397 // Delete the database on the database thread. | 537 // Delete the database on the database thread. |
| 398 PostTaskAndReplyWithResult( | 538 PostTaskAndReplyWithResult( |
| 399 database_task_runner_, | 539 database_task_runner_, |
| 400 FROM_HERE, | 540 FROM_HERE, |
| 401 base::Bind(&ServiceWorkerDatabase::DestroyDatabase, | 541 base::Bind(&ServiceWorkerDatabase::DestroyDatabase, |
| 402 base::Unretained(database_.get())), | 542 base::Unretained(database_.get())), |
| 403 base::Bind(&ServiceWorkerStorage::DidDeleteDatabase, | 543 base::Bind(&ServiceWorkerStorage::DidDeleteDatabase, |
| (...skipping 349 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 753 | 893 |
| 754 registration = new ServiceWorkerRegistration( | 894 registration = new ServiceWorkerRegistration( |
| 755 data.scope, data.script, data.registration_id, context_); | 895 data.scope, data.script, data.registration_id, context_); |
| 756 scoped_refptr<ServiceWorkerVersion> version = | 896 scoped_refptr<ServiceWorkerVersion> version = |
| 757 context_->GetLiveVersion(data.version_id); | 897 context_->GetLiveVersion(data.version_id); |
| 758 if (!version) { | 898 if (!version) { |
| 759 version = new ServiceWorkerVersion(registration, data.version_id, context_); | 899 version = new ServiceWorkerVersion(registration, data.version_id, context_); |
| 760 version->SetStatus(data.is_active ? | 900 version->SetStatus(data.is_active ? |
| 761 ServiceWorkerVersion::ACTIVATED : ServiceWorkerVersion::INSTALLED); | 901 ServiceWorkerVersion::ACTIVATED : ServiceWorkerVersion::INSTALLED); |
| 762 version->script_cache_map()->SetResources(resources); | 902 version->script_cache_map()->SetResources(resources); |
| 903 |
| 904 // TODO(michaeln): need to activate a waiting version that wasn't |
| 905 // actrivated in an earlier session, maybe test for this condition |
| 906 // (waitingversion and no activeversion) when navigating to a page? |
| 763 } | 907 } |
| 764 | 908 |
| 765 if (version->status() == ServiceWorkerVersion::ACTIVATED) | 909 if (version->status() == ServiceWorkerVersion::ACTIVATED) |
| 766 registration->SetActiveVersion(version); | 910 registration->SetActiveVersion(version); |
| 767 else if (version->status() == ServiceWorkerVersion::INSTALLED) | 911 else if (version->status() == ServiceWorkerVersion::INSTALLED) |
| 768 registration->SetWaitingVersion(version); | 912 registration->SetWaitingVersion(version); |
| 769 else | 913 else |
| 770 NOTREACHED(); | 914 NOTREACHED(); |
| 771 // TODO(michaeln): Hmmm, what if DeleteReg was invoked after | 915 |
| 772 // the Find result we're returning here? NOTREACHED condition? | |
| 773 return registration; | 916 return registration; |
| 774 } | 917 } |
| 775 | 918 |
| 776 ServiceWorkerRegistration* | 919 ServiceWorkerRegistration* |
| 777 ServiceWorkerStorage::FindInstallingRegistrationForDocument( | 920 ServiceWorkerStorage::FindInstallingRegistrationForDocument( |
| 778 const GURL& document_url) { | 921 const GURL& document_url) { |
| 779 DCHECK(!document_url.has_ref()); | 922 DCHECK(!document_url.has_ref()); |
| 780 | 923 |
| 781 LongestScopeMatcher matcher(document_url); | 924 LongestScopeMatcher matcher(document_url); |
| 782 ServiceWorkerRegistration* match = NULL; | 925 ServiceWorkerRegistration* match = NULL; |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1174 // Give up the corruption recovery until the browser restarts. | 1317 // Give up the corruption recovery until the browser restarts. |
| 1175 LOG(ERROR) << "Failed to delete the diskcache."; | 1318 LOG(ERROR) << "Failed to delete the diskcache."; |
| 1176 callback.Run(SERVICE_WORKER_ERROR_FAILED); | 1319 callback.Run(SERVICE_WORKER_ERROR_FAILED); |
| 1177 return; | 1320 return; |
| 1178 } | 1321 } |
| 1179 DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully."; | 1322 DVLOG(1) << "Deleted ServiceWorkerDiskCache successfully."; |
| 1180 callback.Run(SERVICE_WORKER_OK); | 1323 callback.Run(SERVICE_WORKER_OK); |
| 1181 } | 1324 } |
| 1182 | 1325 |
| 1183 } // namespace content | 1326 } // namespace content |
| OLD | NEW |