Index: content/browser/service_worker/service_worker_storage.cc |
diff --git a/content/browser/service_worker/service_worker_storage.cc b/content/browser/service_worker/service_worker_storage.cc |
index ac8e3322de251e1a528a9f595ed7e3109754728d..ab73931ce614b32d33342a396969431d57f1555a 100644 |
--- a/content/browser/service_worker/service_worker_storage.cc |
+++ b/content/browser/service_worker/service_worker_storage.cc |
@@ -21,6 +21,7 @@ |
#include "content/common/service_worker/service_worker_types.h" |
#include "content/public/browser/browser_thread.h" |
#include "net/base/completion_callback.h" |
+#include "net/base/io_buffer.h" |
#include "net/base/net_errors.h" |
#include "webkit/browser/quota/quota_manager_proxy.h" |
@@ -72,6 +73,133 @@ ServiceWorkerStatusCode DatabaseStatusToStatusCode( |
} |
} |
+class ResponseComparer : public base::RefCounted<ResponseComparer> { |
+ public: |
+ ResponseComparer( |
+ base::WeakPtr<ServiceWorkerStorage> owner, |
+ scoped_ptr<ServiceWorkerResponseReader> lhs, |
+ scoped_ptr<ServiceWorkerResponseReader> rhs, |
+ const ServiceWorkerStorage::CompareCallback& callback) |
+ : owner_(owner), |
+ completion_callback_(callback), |
+ lhs_reader_(lhs.release()), |
+ rhs_reader_(rhs.release()), |
+ completion_count_(0), |
+ previous_result_(0) { |
+ } |
+ |
+ void Start(); |
+ |
+ private: |
+ friend class base::RefCounted<ResponseComparer>; |
+ |
+ static const int kBufferSize = 16 * 1024; |
+ |
+ ~ResponseComparer() {} |
+ void ReadInfos(); |
+ void OnReadInfoComplete(int result); |
+ void ReadSomeData(); |
+ void OnReadDataComplete(int result); |
+ |
+ base::WeakPtr<ServiceWorkerStorage> owner_; |
+ ServiceWorkerStorage::CompareCallback completion_callback_; |
+ scoped_ptr<ServiceWorkerResponseReader> lhs_reader_; |
+ scoped_refptr<HttpResponseInfoIOBuffer> lhs_info_; |
+ scoped_refptr<net::IOBuffer> lhs_buffer_; |
+ scoped_ptr<ServiceWorkerResponseReader> rhs_reader_; |
+ scoped_refptr<HttpResponseInfoIOBuffer> rhs_info_; |
+ scoped_refptr<net::IOBuffer> rhs_buffer_; |
+ int completion_count_; |
+ int previous_result_; |
+ DISALLOW_COPY_AND_ASSIGN(ResponseComparer); |
+}; |
+ |
+void ResponseComparer::Start() { |
+ lhs_buffer_ = new net::IOBuffer(kBufferSize); |
+ lhs_info_ = new HttpResponseInfoIOBuffer(); |
+ rhs_buffer_ = new net::IOBuffer(kBufferSize); |
+ rhs_info_ = new HttpResponseInfoIOBuffer(); |
+ |
+ ReadInfos(); |
+} |
+ |
+void ResponseComparer::ReadInfos() { |
+ lhs_reader_->ReadInfo( |
+ lhs_info_, |
+ base::Bind(&ResponseComparer::OnReadInfoComplete, |
+ this)); |
+ rhs_reader_->ReadInfo( |
+ rhs_info_, |
+ base::Bind(&ResponseComparer::OnReadInfoComplete, |
+ this)); |
+} |
+ |
+void ResponseComparer::OnReadInfoComplete(int result) { |
+ if (completion_callback_.is_null() || !owner_) |
+ return; |
+ if (result < 0) { |
+ completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false); |
+ completion_callback_.Reset(); |
+ return; |
+ } |
+ if (++completion_count_ != 2) |
+ return; |
+ |
+ if (lhs_info_->response_data_size != rhs_info_->response_data_size) { |
+ completion_callback_.Run(SERVICE_WORKER_OK, false); |
+ return; |
+ } |
+ ReadSomeData(); |
+} |
+ |
+void ResponseComparer::ReadSomeData() { |
+ completion_count_ = 0; |
+ lhs_reader_->ReadData( |
+ lhs_buffer_, |
+ kBufferSize, |
+ base::Bind(&ResponseComparer::OnReadDataComplete, this)); |
+ rhs_reader_->ReadData( |
+ rhs_buffer_, |
+ kBufferSize, |
+ base::Bind(&ResponseComparer::OnReadDataComplete, this)); |
+} |
+ |
+void ResponseComparer::OnReadDataComplete(int result) { |
+ if (completion_callback_.is_null() || !owner_) |
+ return; |
+ if (result < 0) { |
+ completion_callback_.Run(SERVICE_WORKER_ERROR_FAILED, false); |
+ completion_callback_.Reset(); |
+ return; |
+ } |
+ if (++completion_count_ != 2) { |
+ previous_result_ = result; |
+ return; |
+ } |
+ |
+ // TODO(michaeln): Probably shouldn't assume that the amounts read from |
+ // each reader will always be the same. This would wrongly signal false |
+ // in that case. |
+ if (result != previous_result_) { |
+ completion_callback_.Run(SERVICE_WORKER_OK, false); |
+ return; |
+ } |
+ |
+ if (result == 0) { |
+ completion_callback_.Run(SERVICE_WORKER_OK, true); |
+ return; |
+ } |
+ |
+ int compare_result = |
+ memcmp(lhs_buffer_->data(), rhs_buffer_->data(), result); |
+ if (compare_result != 0) { |
+ completion_callback_.Run(SERVICE_WORKER_OK, false); |
+ return; |
+ } |
+ |
+ ReadSomeData(); |
+} |
+ |
} // namespace |
ServiceWorkerStorage::InitialData::InitialData() |
@@ -391,6 +519,18 @@ void ServiceWorkerStorage::DoomUncommittedResponse(int64 id) { |
StartPurgingResources(std::vector<int64>(1, id)); |
} |
+void ServiceWorkerStorage::CompareScriptResources( |
+ int64 lhs_id, int64 rhs_id, |
+ const CompareCallback& callback) { |
+ DCHECK(!callback.is_null()); |
+ scoped_refptr<ResponseComparer> comparer = |
+ new ResponseComparer(weak_factory_.GetWeakPtr(), |
+ CreateResponseReader(lhs_id), |
+ CreateResponseReader(rhs_id), |
+ callback); |
+ comparer->Start(); // It deletes itself when done. |
+} |
+ |
void ServiceWorkerStorage::DeleteAndStartOver(const StatusCallback& callback) { |
Disable(); |
@@ -760,6 +900,10 @@ ServiceWorkerStorage::GetOrCreateRegistration( |
version->SetStatus(data.is_active ? |
ServiceWorkerVersion::ACTIVATED : ServiceWorkerVersion::INSTALLED); |
version->script_cache_map()->SetResources(resources); |
+ |
+ // TODO(michaeln): need to activate a waiting version that wasn't |
+ // actrivated in an earlier session, maybe test for this condition |
+ // (waitingversion and no activeversion) when navigating to a page? |
} |
if (version->status() == ServiceWorkerVersion::ACTIVATED) |
@@ -768,8 +912,7 @@ ServiceWorkerStorage::GetOrCreateRegistration( |
registration->SetWaitingVersion(version); |
else |
NOTREACHED(); |
- // TODO(michaeln): Hmmm, what if DeleteReg was invoked after |
- // the Find result we're returning here? NOTREACHED condition? |
+ |
return registration; |
} |