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) {
ServiceWorkerCacheWriter::ServiceWorkerCacheWriter(
std::unique_ptr<ServiceWorkerResponseReader> compare_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),
io_pending_(false),
comparing_(false),
did_replace_(false),
pause_when_not_identical_(pause_when_not_identical),
compare_reader_(std::move(compare_reader)),
copy_reader_(std::move(copy_reader)),
writer_(std::move(writer)),
......@@ -185,6 +186,12 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
// STATE_WRITE_HEADERS_FOR_PASSTHROUGH_DONE is excluded because that write
// is done by MaybeWriteHeaders.
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_DATA_FOR_COPY_DONE ||
state_ == STATE_WRITE_HEADERS_FOR_COPY_DONE ||
......@@ -192,7 +199,6 @@ net::Error ServiceWorkerCacheWriter::MaybeWriteData(
state_ == STATE_WRITE_DATA_FOR_PASSTHROUGH_DONE)
<< "Unexpected state: " << state_;
}
return result >= 0 ? net::OK : static_cast<net::Error>(result);
}
......@@ -260,7 +266,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
if (result == 0 && len_to_write_ != 0) {
comparing_ = false;
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
......@@ -272,7 +279,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
// over, then start writing network data back after the changed point.
comparing_ = false;
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;
......@@ -295,7 +303,8 @@ int ServiceWorkerCacheWriter::DoReadDataForCompareDone(int result) {
if (len_to_read_ == 0 && bytes_compared_ + compare_offset_ < cached_length_) {
comparing_ = false;
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_;
......@@ -492,10 +501,14 @@ void ServiceWorkerCacheWriter::AsyncDoLoop(int result) {
// later invocation of AsyncDoLoop.
if (result != net::ERR_IO_PENDING) {
OnWriteCompleteCallback callback = std::move(pending_callback_);
pending_callback_.Reset();
net::Error error = result >= 0 ? net::OK : static_cast<net::Error>(result);
io_pending_ = false;
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 {
// The |compare_reader| may be null, in which case this instance will
// unconditionally write back data supplied to |MaybeWriteHeaders| and
// |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(
std::unique_ptr<ServiceWorkerResponseReader> compare_reader,
std::unique_ptr<ServiceWorkerResponseReader> copy_reader,
std::unique_ptr<ServiceWorkerResponseWriter> writer);
std::unique_ptr<ServiceWorkerResponseWriter> writer,
bool pause_when_not_identical);
~ServiceWorkerCacheWriter();
......@@ -73,6 +79,7 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Returns a count of bytes written back to the cache.
size_t bytes_written() const { return bytes_written_; }
bool did_replace() const { return did_replace_; }
bool data_not_identical() const { return data_not_identical_; }
private:
// States for the state machine.
......@@ -219,7 +226,14 @@ class CONTENT_EXPORT ServiceWorkerCacheWriter {
// Count of bytes written back to |writer_|.
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> copy_reader_;
......
......@@ -115,7 +115,8 @@ ServiceWorkerNewScriptLoader::ServiceWorkerNewScriptLoader(
}
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
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_,
cache_resource_id);
......
......@@ -112,7 +112,8 @@ void ServiceWorkerWriteToCacheJob::StartAsync() {
}
cache_writer_ = std::make_unique<ServiceWorkerCacheWriter>(
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_);
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