Commit 672f9b44 authored by falken's avatar falken Committed by Commit bot

Service Worker: Don't write to disk during update until proven necessary

For updates, don't write the main script to disk until a change with the
incumbent script is detected. The incumbent script is progressively
compared with as the new script is read from network. Once a change is
detected, copy everything matched up until now to disk, and from then on
write to disk as the script continues to be read from network.

BUG=457013

Review URL: https://codereview.chromium.org/1166433003

Cr-Commit-Position: refs/heads/master@{#333031}
parent 11a8a0eb
...@@ -73,13 +73,17 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob( ...@@ -73,13 +73,17 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
extra_load_flags = net::LOAD_BYPASS_CACHE; extra_load_flags = net::LOAD_BYPASS_CACHE;
} }
return new ServiceWorkerWriteToCacheJob(request, ServiceWorkerVersion* stored_version = registration->waiting_version()
network_delegate, ? registration->waiting_version()
resource_type_, : registration->active_version();
context_, int64 incumbent_response_id = kInvalidServiceWorkerResourceId;
version_.get(), if (stored_version && stored_version->script_url() == request->url()) {
extra_load_flags, incumbent_response_id =
response_id); stored_version->script_cache_map()->LookupResourceId(request->url());
}
return new ServiceWorkerWriteToCacheJob(
request, network_delegate, resource_type_, context_, version_.get(),
extra_load_flags, response_id, incumbent_response_id);
} }
int64 response_id = kInvalidServiceWorkerResponseId; int64 response_id = kInvalidServiceWorkerResponseId;
......
...@@ -228,6 +228,15 @@ class CONTENT_EXPORT ServiceWorkerProviderHost ...@@ -228,6 +228,15 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
private: private:
friend class ServiceWorkerProviderHostTest; friend class ServiceWorkerProviderHostTest;
friend class ServiceWorkerWriteToCacheJobTest; friend class ServiceWorkerWriteToCacheJobTest;
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest, Update_SameScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_SameSizeScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_TruncatedScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_ElongatedScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerWriteToCacheJobTest,
Update_EmptyScript);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest, FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateBefore24Hours); UpdateBefore24Hours);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest, FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
......
...@@ -30,18 +30,25 @@ class ServiceWorkerVersions; ...@@ -30,18 +30,25 @@ class ServiceWorkerVersions;
// request is written to the service worker script cache and piped // request is written to the service worker script cache and piped
// to the consumer of the ServiceWorkerWriteToCacheJob for delivery // to the consumer of the ServiceWorkerWriteToCacheJob for delivery
// to the renderer process housing the worker. // to the renderer process housing the worker.
//
// For updates, the main script is not written to disk until a change with the
// incumbent script is detected. The incumbent script is progressively compared
// with the new script as it is read from network. Once a change is detected,
// everything that matched is copied to disk, and from then on the script is
// written as it continues to be read from network. If the scripts were
// identical, the job fails so the worker can be discarded.
class CONTENT_EXPORT ServiceWorkerWriteToCacheJob class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
: public net::URLRequestJob, : public net::URLRequestJob,
public net::URLRequest::Delegate { public net::URLRequest::Delegate {
public: public:
ServiceWorkerWriteToCacheJob( ServiceWorkerWriteToCacheJob(net::URLRequest* request,
net::URLRequest* request, net::NetworkDelegate* network_delegate,
net::NetworkDelegate* network_delegate, ResourceType resource_type,
ResourceType resource_type, base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerContextCore> context, ServiceWorkerVersion* version,
ServiceWorkerVersion* version, int extra_load_flags,
int extra_load_flags, int64 response_id,
int64 response_id); int64 incumbent_response_id);
private: private:
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest, FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
...@@ -50,6 +57,10 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob ...@@ -50,6 +57,10 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
UpdateAfter24Hours); UpdateAfter24Hours);
FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest, FRIEND_TEST_ALL_PREFIXES(ServiceWorkerContextRequestHandlerTest,
UpdateForceBypassCache); UpdateForceBypassCache);
class NetDataConsumer;
class PassThroughConsumer;
class Comparer;
class Copier;
~ServiceWorkerWriteToCacheJob() override; ~ServiceWorkerWriteToCacheJob() override;
...@@ -70,14 +81,18 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob ...@@ -70,14 +81,18 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
// write data to the disk cache. // write data to the disk cache.
void InitNetRequest(int extra_load_flags); void InitNetRequest(int extra_load_flags);
void StartNetRequest(); void StartNetRequest();
net::URLRequestStatus ReadNetData( net::URLRequestStatus ReadNetData(net::IOBuffer* buf,
net::IOBuffer* buf, int buf_size,
int buf_size, int* bytes_read);
int *bytes_read);
void WriteHeadersToCache(); void CommitHeadersAndNotifyHeadersComplete();
void OnWriteHeadersComplete(int result); void WriteHeaders(const base::Closure& callback);
void WriteDataToCache(int bytes_to_write); void OnWriteHeadersComplete(const base::Closure& callback, int result);
void OnWriteDataComplete(int result); void WriteData(net::IOBuffer* buf,
int amount_to_write,
const base::Callback<void(int result)>& callback);
void OnWriteDataComplete(const base::Callback<void(int result)>& callback,
int result);
// net::URLRequest::Delegate overrides that observe the net request. // net::URLRequest::Delegate overrides that observe the net request.
void OnReceivedRedirect(net::URLRequest* request, void OnReceivedRedirect(net::URLRequest* request,
...@@ -97,19 +112,32 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob ...@@ -97,19 +112,32 @@ class CONTENT_EXPORT ServiceWorkerWriteToCacheJob
bool CheckPathRestriction(net::URLRequest* request); bool CheckPathRestriction(net::URLRequest* request);
void SetPendingIO();
void ClearPendingIO();
void OnPassThroughComplete();
void OnCompareComplete(int bytes_matched, bool is_equal);
void CopyIncumbent(int bytes_to_copy);
void OnCopyComplete(ServiceWorkerStatusCode status);
void HandleNetData(int bytes_read);
void AsyncNotifyDoneHelper(const net::URLRequestStatus& status, void AsyncNotifyDoneHelper(const net::URLRequestStatus& status,
const std::string& status_message); const std::string& status_message);
void NotifyFinishedCaching(net::URLRequestStatus status,
const std::string& status_message);
ResourceType resource_type_; // Differentiate main script and imports ResourceType resource_type_; // Differentiate main script and imports
scoped_refptr<net::IOBuffer> io_buffer_; scoped_refptr<net::IOBuffer> io_buffer_;
scoped_refptr<HttpResponseInfoIOBuffer> info_buffer_; int io_buffer_bytes_;
base::WeakPtr<ServiceWorkerContextCore> context_; base::WeakPtr<ServiceWorkerContextCore> context_;
GURL url_; GURL url_;
int64 response_id_; int64 response_id_;
int64 incumbent_response_id_;
scoped_ptr<net::URLRequest> net_request_; scoped_ptr<net::URLRequest> net_request_;
scoped_ptr<net::HttpResponseInfo> http_info_; scoped_ptr<net::HttpResponseInfo> http_info_;
scoped_ptr<ServiceWorkerResponseWriter> writer_; scoped_ptr<ServiceWorkerResponseWriter> writer_;
scoped_refptr<ServiceWorkerVersion> version_; scoped_refptr<ServiceWorkerVersion> version_;
scoped_ptr<NetDataConsumer> consumer_;
bool has_been_killed_; bool has_been_killed_;
bool did_notify_started_; bool did_notify_started_;
bool did_notify_finished_; bool did_notify_finished_;
......
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