Commit a0b7787a authored by Kinuko Yasuda's avatar Kinuko Yasuda Committed by Commit Bot

SW Servicification: Hook ScriptURLLoader only for script installation

Add some more code from ServiceWorkerContextRequestHandler to
ScriptURLLoaderFactory.  Also added small cleanup around IsInstalled.

BUG=715640

patch from issue 2953763002 at patchset 1 (http://crrev.com/2953763002#ps1)

Change-Id: Ib0b578378a957e911bf7a36b2929d2723e0b35f7
Reviewed-on: https://chromium-review.googlesource.com/544720Reviewed-by: default avatarMatt Falkenhagen <falken@chromium.org>
Commit-Queue: Kinuko Yasuda <kinuko@chromium.org>
Cr-Commit-Position: refs/heads/master@{#481842}
parent a84d39ad
......@@ -21,26 +21,6 @@
namespace content {
namespace {
bool IsInstalled(const ServiceWorkerVersion* version) {
switch (version->status()) {
case ServiceWorkerVersion::NEW:
case ServiceWorkerVersion::INSTALLING:
return false;
case ServiceWorkerVersion::INSTALLED:
case ServiceWorkerVersion::ACTIVATING:
case ServiceWorkerVersion::ACTIVATED:
return true;
case ServiceWorkerVersion::REDUNDANT:
return false;
}
NOTREACHED();
return false;
}
} // namespace
ServiceWorkerContextRequestHandler::ServiceWorkerContextRequestHandler(
base::WeakPtr<ServiceWorkerContextCore> context,
base::WeakPtr<ServiceWorkerProviderHost> provider_host,
......@@ -110,7 +90,8 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJob(
MaybeCreateJobImpl(request, network_delegate, &status);
const bool is_main_script = resource_type_ == RESOURCE_TYPE_SERVICE_WORKER;
ServiceWorkerMetrics::RecordContextRequestHandlerStatus(
status, IsInstalled(version_.get()), is_main_script);
status, ServiceWorkerVersion::IsInstalled(version_->status()),
is_main_script);
if (job)
return job;
......@@ -170,7 +151,7 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
int resource_id =
version_->script_cache_map()->LookupResourceId(request->url());
if (resource_id != kInvalidServiceWorkerResourceId) {
if (IsInstalled(version_.get())) {
if (ServiceWorkerVersion::IsInstalled(version_->status())) {
// An installed worker is loading a stored script.
if (is_main_script)
version_->embedded_worker()->OnURLJobCreatedForMainScript();
......@@ -186,7 +167,7 @@ net::URLRequestJob* ServiceWorkerContextRequestHandler::MaybeCreateJobImpl(
}
// An installed worker is importing a non-stored script.
if (IsInstalled(version_.get())) {
if (ServiceWorkerVersion::IsInstalled(version_->status())) {
DCHECK(!is_main_script);
*out_status = CreateJobStatus::ERROR_UNINSTALLED_SCRIPT_IMPORT;
return nullptr;
......
......@@ -100,13 +100,11 @@ void RemoveProviderHost(base::WeakPtr<ServiceWorkerContextCore> context,
context->RemoveProviderHost(process_id, provider_id);
}
// Used by a Service Worker for script loading (for all script loading for now,
// but to be used only during installation once script streaming lands).
// For now this is just a proxy loader for the network loader.
// Used by a Service Worker for script loading only during the installation
// time. For now this is just a proxy loader for the network loader.
// Eventually this should replace the existing URLRequestJob-based request
// interception for script loading, namely ServiceWorkerWriteToCacheJob.
// TODO(kinuko): Implement this. Hook up the existing code in
// ServiceWorkerContextRequestHandler.
// TODO(kinuko): Implement this.
class ScriptURLLoader : public mojom::URLLoader, public mojom::URLLoaderClient {
public:
ScriptURLLoader(
......@@ -226,6 +224,16 @@ class ScriptURLLoaderFactory : public mojom::URLLoaderFactory {
mojom::URLLoaderClientPtr client,
const net::MutableNetworkTrafficAnnotationTag&
traffic_annotation) override {
if (!ShouldHandleScriptRequest(resource_request)) {
// If the request should not be handled by ScriptURLLoader, just
// fallback to the network.
// TODO(kinuko): Record the reason like what we do with netlog in
// ServiceWorkerContextRequestHandler.
loader_factory_getter_->GetNetworkFactory()->get()->CreateLoaderAndStart(
std::move(request), routing_id, request_id, options, resource_request,
std::move(client), traffic_annotation);
return;
}
mojo::MakeStrongAssociatedBinding(
base::MakeUnique<ScriptURLLoader>(
routing_id, request_id, options, resource_request,
......@@ -242,6 +250,53 @@ class ScriptURLLoaderFactory : public mojom::URLLoaderFactory {
}
private:
bool ShouldHandleScriptRequest(const ResourceRequest& resource_request) {
if (!context_ || !provider_host_)
return false;
// We only use the script cache for main script loading and
// importScripts(), even if a cached script is xhr'd, we don't
// retrieve it from the script cache.
if (resource_request.resource_type != RESOURCE_TYPE_SERVICE_WORKER &&
resource_request.resource_type != RESOURCE_TYPE_SCRIPT) {
// TODO: Record bad message, we shouldn't come here for other
// request types.
return false;
}
scoped_refptr<ServiceWorkerVersion> version =
provider_host_->running_hosted_version();
// This could happen if browser-side has set the status to redundant but
// the worker has not yet stopped. The worker is already doomed so just
// reject the request. Handle it specially here because otherwise it'd be
// unclear whether "REDUNDANT" should count as installed or not installed
// when making decisions about how to handle the request and logging UMA.
if (!version || version->status() == ServiceWorkerVersion::REDUNDANT)
return false;
// TODO: Make sure we don't handle the redirected request.
// For installed worker we fallback to the network for now.
// TODO: Make sure we don't come here for installed worker once
// script streaming is enabled.
if (ServiceWorkerVersion::IsInstalled(version->status()))
return false;
// TODO: Make sure we come here only for new / unknown scripts
// once script streaming manager in the renderer side stops sending
// resource requests for the known script URLs, i.e. add DCHECK for
// version->script_cache_map()->LookupResourceId(url) ==
// kInvalidServiceWorkerResourceId.
//
// Currently this could be false for the installing worker that imports
// the same script twice (e.g. importScripts('dupe.js');
// importScripts('dupe.js');).
// Request should be served by ScriptURLLoader.
return true;
}
base::WeakPtr<ServiceWorkerContextCore> context_;
base::WeakPtr<ServiceWorkerProviderHost> provider_host_;
base::WeakPtr<storage::BlobStorageContext> blob_storage_context_;
......
......@@ -135,21 +135,6 @@ void ClearTick(base::TimeTicks* time) {
*time = base::TimeTicks();
}
bool IsInstalled(ServiceWorkerVersion::Status status) {
switch (status) {
case ServiceWorkerVersion::NEW:
case ServiceWorkerVersion::INSTALLING:
case ServiceWorkerVersion::REDUNDANT:
return false;
case ServiceWorkerVersion::INSTALLED:
case ServiceWorkerVersion::ACTIVATING:
case ServiceWorkerVersion::ACTIVATED:
return true;
}
NOTREACHED() << "Unexpected status: " << status;
return false;
}
std::string VersionStatusToString(ServiceWorkerVersion::Status status) {
switch (status) {
case ServiceWorkerVersion::NEW:
......@@ -1076,6 +1061,21 @@ void ServiceWorkerVersion::CountFeature(uint32_t feature) {
provider_host_by_uuid.second->CountFeature(feature);
}
bool ServiceWorkerVersion::IsInstalled(ServiceWorkerVersion::Status status) {
switch (status) {
case ServiceWorkerVersion::NEW:
case ServiceWorkerVersion::INSTALLING:
case ServiceWorkerVersion::REDUNDANT:
return false;
case ServiceWorkerVersion::INSTALLED:
case ServiceWorkerVersion::ACTIVATING:
case ServiceWorkerVersion::ACTIVATED:
return true;
}
NOTREACHED() << "Unexpected status: " << status;
return false;
}
void ServiceWorkerVersion::OnOpenNewTab(int request_id, const GURL& url) {
OnOpenWindow(request_id, url, WindowOpenDisposition::NEW_FOREGROUND_TAB);
}
......
......@@ -403,6 +403,8 @@ class CONTENT_EXPORT ServiceWorkerVersion
}
const std::set<uint32_t>& used_features() const { return used_features_; }
static bool IsInstalled(ServiceWorkerVersion::Status status);
private:
friend class base::RefCounted<ServiceWorkerVersion>;
friend class ServiceWorkerReadFromCacheJobTest;
......
......@@ -75,6 +75,8 @@
#include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextClient.h"
#include "third_party/WebKit/public/web/modules/serviceworker/WebServiceWorkerContextProxy.h"
using blink::WebURLRequest;
namespace content {
namespace {
......@@ -93,21 +95,30 @@ class WebServiceWorkerNetworkProviderImpl
// Blink calls this method for each request starting with the main script,
// we tag them with the provider id.
void WillSendRequest(blink::WebURLRequest& request) override {
void WillSendRequest(WebURLRequest& request) override {
std::unique_ptr<RequestExtraData> extra_data(new RequestExtraData);
extra_data->set_service_worker_provider_id(provider_->provider_id());
extra_data->set_originated_from_service_worker(true);
// Service workers are only available in secure contexts, so all requests
// are initiated in a secure context.
extra_data->set_initiated_in_secure_context(true);
extra_data->set_url_loader_factory_override(
provider_->script_loader_factory());
if (IsScriptRequest(request)) {
extra_data->set_url_loader_factory_override(
provider_->script_loader_factory());
}
request.SetExtraData(extra_data.release());
}
int GetProviderID() const override { return provider_->provider_id(); }
private:
static bool IsScriptRequest(const WebURLRequest& request) {
auto request_context = request.GetRequestContext();
return request_context == WebURLRequest::kRequestContextServiceWorker ||
request_context == WebURLRequest::kRequestContextScript ||
request_context == WebURLRequest::kRequestContextImport;
}
std::unique_ptr<ServiceWorkerNetworkProvider> provider_;
};
......@@ -139,31 +150,28 @@ ServiceWorkerStatusCode EventResultToStatus(
return SERVICE_WORKER_ERROR_FAILED;
}
blink::WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode(
WebURLRequest::FetchRequestMode GetBlinkFetchRequestMode(
FetchRequestMode mode) {
return static_cast<blink::WebURLRequest::FetchRequestMode>(mode);
return static_cast<WebURLRequest::FetchRequestMode>(mode);
}
blink::WebURLRequest::FetchCredentialsMode GetBlinkFetchCredentialsMode(
WebURLRequest::FetchCredentialsMode GetBlinkFetchCredentialsMode(
FetchCredentialsMode credentials_mode) {
return static_cast<blink::WebURLRequest::FetchCredentialsMode>(
credentials_mode);
return static_cast<WebURLRequest::FetchCredentialsMode>(credentials_mode);
}
blink::WebURLRequest::FetchRedirectMode GetBlinkFetchRedirectMode(
WebURLRequest::FetchRedirectMode GetBlinkFetchRedirectMode(
FetchRedirectMode redirect_mode) {
return static_cast<blink::WebURLRequest::FetchRedirectMode>(redirect_mode);
return static_cast<WebURLRequest::FetchRedirectMode>(redirect_mode);
}
blink::WebURLRequest::RequestContext GetBlinkRequestContext(
WebURLRequest::RequestContext GetBlinkRequestContext(
RequestContextType request_context_type) {
return static_cast<blink::WebURLRequest::RequestContext>(
request_context_type);
return static_cast<WebURLRequest::RequestContext>(request_context_type);
}
blink::WebURLRequest::FrameType GetBlinkFrameType(
RequestContextFrameType frame_type) {
return static_cast<blink::WebURLRequest::FrameType>(frame_type);
WebURLRequest::FrameType GetBlinkFrameType(RequestContextFrameType frame_type) {
return static_cast<WebURLRequest::FrameType>(frame_type);
}
blink::WebServiceWorkerClientInfo
......
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