Commit aec50d02 authored by momohatt's avatar momohatt Committed by Commit Bot

Add pause_when_not_identical option for ServiceWorkerCacheWriter

This patch adds pause_when_not_identical option for making
ServiceWorkerCacheWriter::MaybeWriteData() return before writing the
new body into the storage when the scripts are not identical.
This option is necessary for extending byte-for-byte update check
of service worker importScripts() resources.

Bug: 648295
Change-Id: If33412cd6e63393ad3fdae514b1588a33f17399a
Reviewed-on: https://chromium-review.googlesource.com/1198651
Commit-Queue: Momoko Hattori <momohatt@google.com>
Reviewed-by: default avatarMakoto Shimazu <shimazu@chromium.org>
Reviewed-by: default avatarKinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#589492}
parent 50bc19d4
...@@ -117,11 +117,12 @@ int ServiceWorkerCacheWriter::DoLoop(int status) { ...@@ -117,11 +117,12 @@ int ServiceWorkerCacheWriter::DoLoop(int status) {
ServiceWorkerCacheWriter::ServiceWorkerCacheWriter( ServiceWorkerCacheWriter::ServiceWorkerCacheWriter(
std::unique_ptr<ServiceWorkerResponseReader> compare_reader, std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader, std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
std::unique_ptr<ServiceWorkerResponseWriter> writer) std::unique_ptr<ServiceWorkerResponseWriter> writer,
bool pause_when_not_identical)
: state_(STATE_START), : state_(STATE_START),
io_pending_(false), io_pending_(false),
comparing_(false), comparing_(false),
did_replace_(false), pause_when_not_identical_(pause_when_not_identical),
compare_reader_(std::move(compare_reader)), compare_reader_(std::move(compare_reader)),
copy_reader_(std::move(copy_reader)), copy_reader_(std::move(copy_reader)),
writer_(std::move(writer)), writer_(std::move(writer)),
...@@ -185,6 +186,12 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData( ...@@ -185,6 +186,12 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
// STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write // STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write
// is done by MaybeWriteHeaders. // is done by MaybeWriteHeaders.
DCHECK(state_ == STATE_READ_DATA_FOR_COMPARE_DONE || DCHECK(state_ == STATE_READ_DATA_FOR_COMPARE_DONE ||
// |state_| can be STATE_READ_HEADERS_FOR_COPY only when the
// |pause_when_not_identical_| option is enabled, and the cache
// writer finds that the network data is not identical with the
// stored data.
(state_ == STATE_READ_HEADERS_FOR_COPY &&
pause_when_not_identical_ && data_not_identical_) ||
state_ == STATE_READ_HEADERS_FOR_COPY_DONE || state_ == STATE_READ_HEADERS_FOR_COPY_DONE ||
state_ == STATE_READ_DATA_FOR_COPY_DONE || state_ == STATE_READ_DATA_FOR_COPY_DONE ||
state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE || state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
...@@ -192,7 +199,6 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData( ...@@ -192,7 +199,6 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE) state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE)
<< "Unexpected state: " << state_; << "Unexpected state: " << state_;
} }
return result >= 0 ? net::OK : static_cast<net::Error>(result); return result >= 0 ? net::OK : static_cast<net::Error>(result);
} }
...@@ -260,7 +266,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) { ...@@ -260,7 +266,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
if (result == 0 && len_to_write_ != 0) { if (result == 0 && len_to_write_ != 0) {
comparing_ = false; comparing_ = false;
state_ = STATE_READ_HEADERS_FOR_COPY; state_ = STATE_READ_HEADERS_FOR_COPY;
return net::OK; data_not_identical_ = true;
return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
} }
// Compare the data from the ServiceWorker script cache to the data from the // Compare the data from the ServiceWorker script cache to the data from the
...@@ -272,7 +279,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) { ...@@ -272,7 +279,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
// over, then start writing network data back after the changed point. // over, then start writing network data back after the changed point.
comparing_ = false; comparing_ = false;
state_ = STATE_READ_HEADERS_FOR_COPY; state_ = STATE_READ_HEADERS_FOR_COPY;
return net::OK; data_not_identical_ = true;
return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
} }
compare_offset_ += result; compare_offset_ += result;
...@@ -295,7 +303,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) { ...@@ -295,7 +303,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) { if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) {
comparing_ = false; comparing_ = false;
state_ = STATE_READ_HEADERS_FOR_COPY; state_ = STATE_READ_HEADERS_FOR_COPY;
return net::OK; data_not_identical_ = true;
return pause_when_not_identical_ ? net::ERR_IO_PENDING : net::OK;
} }
bytes_compared_ += compare_offset_; bytes_compared_ += compare_offset_;
...@@ -492,10 +501,14 @@ void ServiceWorkerCacheWriter::AsyncDoLoop(int result) { ...@@ -492,10 +501,14 @@ void ServiceWorkerCacheWriter::AsyncDoLoop(int result) {
// later invocation of AsyncDoLoop. // later invocation of AsyncDoLoop.
if (result != net::ERR_IO_PENDING) { if (result != net::ERR_IO_PENDING) {
OnWriteCompleteCallback callback = std::move(pending_callback_); OnWriteCompleteCallback callback = std::move(pending_callback_);
pending_callback_.Reset();
net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result); net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result);
io_pending_ = false; io_pending_ = false;
std::move(callback).Run(error); std::move(callback).Run(error);
return;
}
if (pause_when_not_identical_ && data_not_identical_) {
OnWriteCompleteCallback callback = std::move(pending_callback_);
std::move(callback).Run(net::ERR_IO_PENDING);
} }
} }
......
...@@ -42,10 +42,16 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter { ...@@ -42,10 +42,16 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// The |compare_reader| may be null, in which case this instance will // The |compare_reader| may be null, in which case this instance will
// unconditionally write back data supplied to |MaybeWriteHeaders| and // unconditionally write back data supplied to |MaybeWriteHeaders| and
// |MaybeWriteData|. // |MaybeWriteData|.
//
// When |pause_when_not_identical| is true and the cache writer detects a
// difference between bodies from the network and from the storage, the
// comparison stops immediately and the cache writer returns
// net::ERR_IO_PENDING, with nothing written to the storage.
ServiceWorkerCacheWriter( ServiceWorkerCacheWriter(
std::unique_ptr<ServiceWorkerResponseReader> compare_reader, std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader, std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
std::unique_ptr<ServiceWorkerResponseWriter> writer); std::unique_ptr<ServiceWorkerResponseWriter> writer,
bool pause_when_not_identical);
~ServiceWorkerCacheWriter(); ~ServiceWorkerCacheWriter();
...@@ -73,6 +79,7 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter { ...@@ -73,6 +79,7 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Returns a count of bytes written back to the cache. // Returns a count of bytes written back to the cache.
size_t bytes_written() const { return bytes_written_; } size_t bytes_written() const { return bytes_written_; }
bool did_replace() const { return did_replace_; } bool did_replace() const { return did_replace_; }
bool data_not_identical() const { return data_not_identical_; }
private: private:
// States for the state machine. // States for the state machine.
...@@ -219,7 +226,14 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter { ...@@ -219,7 +226,14 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Count of bytes written back to |writer_|. // Count of bytes written back to |writer_|.
size_t bytes_written_; size_t bytes_written_;
bool did_replace_; bool did_replace_ = false;
// When the cache writer finds any differences between bodies from the network
// and from the storage, |data_not_identical_| is set to true. At the same
// time, if the |pause_when_not_identical_| is true, the cache writer pauses
// immediately.
const bool pause_when_not_identical_;
bool data_not_identical_ = false;
std::unique_ptr<ServiceWorkerResponseReader> compare_reader_; std::unique_ptr<ServiceWorkerResponseReader> compare_reader_;
std::unique_ptr<ServiceWorkerResponseReader> copy_reader_; std::unique_ptr<ServiceWorkerResponseReader> copy_reader_;
......
...@@ -115,7 +115,8 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader( ...@@ -115,7 +115,8 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
} }
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>( cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
std::move(compare_reader), std::move(copy_reader), std::move(compare_reader), std::move(copy_reader),
storage->CreateResponseWriter(cache_resource_id)); storage->CreateResponseWriter(cache_resource_id),
false /* pause_when_not_identical */);
version_->script_cache_map()->NotifyStartedCaching(request_url_, version_->script_cache_map()->NotifyStartedCaching(request_url_,
cache_resource_id); cache_resource_id);
......
...@@ -112,7 +112,8 @@ void ServiceWorkerWriteToCacheJob::StartAsync() { ...@@ -112,7 +112,8 @@ void ServiceWorkerWriteToCacheJob::StartAsync() {
} }
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>( cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
std::move(compare_reader), std::move(copy_reader), std::move(compare_reader), std::move(copy_reader),
context_->storage()->CreateResponseWriter(resource_id_)); context_->storage()->CreateResponseWriter(resource_id_),
false /* pause_when_not_identical */);
version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_); version_->script_cache_map()->NotifyStartedCaching(url_, resource_id_);
did_notify_started_ = true; did_notify_started_ = true;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment