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