Commit 3dbc36e7 authored by falken's avatar falken Committed by Commit bot

Respect content settings for Service Worker registration

Add an AllowServiceWorker setting and use it when registering/unregistering
a Service Worker.

BUG=419277

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

Cr-Commit-Position: refs/heads/master@{#299127}
parent 42868761
......@@ -1460,6 +1460,16 @@ bool ChromeContentBrowserClient::AllowAppCache(
IsSettingCookieAllowed(manifest_url, first_party);
}
bool ChromeContentBrowserClient::AllowServiceWorker(
const GURL& scope,
const GURL& first_party_url,
content::ResourceContext* context) {
DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
ProfileIOData* io_data = ProfileIOData::FromResourceContext(context);
return io_data->GetCookieSettings()->
IsSettingCookieAllowed(scope, first_party_url);
}
bool ChromeContentBrowserClient::AllowGetCookie(
const GURL& url,
const GURL& first_party,
......
......@@ -123,6 +123,9 @@ class ChromeContentBrowserClient : public content::ContentBrowserClient {
virtual bool AllowAppCache(const GURL& manifest_url,
const GURL& first_party,
content::ResourceContext* context) OVERRIDE;
virtual bool AllowServiceWorker(const GURL& scope,
const GURL& first_party,
content::ResourceContext* context) OVERRIDE;
virtual bool AllowGetCookie(const GURL& url,
const GURL& first_party,
const net::CookieList& cookie_list,
......
......@@ -838,8 +838,8 @@ void RenderProcessHostImpl::CreateMessageFilters() {
AddFilter(message_port_message_filter_.get());
scoped_refptr<ServiceWorkerDispatcherHost> service_worker_filter =
new ServiceWorkerDispatcherHost(GetID(),
message_port_message_filter_.get());
new ServiceWorkerDispatcherHost(
GetID(), message_port_message_filter_.get(), resource_context);
service_worker_filter->Init(
storage_partition_impl_->GetServiceWorkerContext());
AddFilter(service_worker_filter.get());
......
......@@ -94,7 +94,7 @@ net::URLRequestJob* ServiceWorkerControlleeRequestHandler::MaybeCreateJob(
frame_type_,
body_);
if (is_main_resource_load_)
PrepareForMainResource(request->url());
PrepareForMainResource(request);
else
PrepareForSubResource();
......@@ -131,7 +131,7 @@ void ServiceWorkerControlleeRequestHandler::GetExtraResponseInfo(
}
void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
const GURL& url) {
const net::URLRequest* request) {
DCHECK(job_.get());
DCHECK(context_);
DCHECK(provider_host_);
......@@ -139,7 +139,7 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
"ServiceWorker",
"ServiceWorkerControlleeRequestHandler::PrepareForMainResource",
job_.get(),
"URL", url.spec());
"URL", request->url().spec());
// The corresponding provider_host may already have associated a registration
// in redirect case, unassociate it now.
provider_host_->DisassociateRegistration();
......@@ -148,8 +148,9 @@ void ServiceWorkerControlleeRequestHandler::PrepareForMainResource(
// registration while we're finding an existing registration.
provider_host_->SetAllowAssociation(false);
GURL stripped_url = net::SimplifyUrlForRequest(url);
GURL stripped_url = net::SimplifyUrlForRequest(request->url());
provider_host_->SetDocumentUrl(stripped_url);
provider_host_->SetTopmostFrameUrl(request->first_party_for_cookies());
context_->storage()->FindRegistrationForDocument(
stripped_url,
base::Bind(&self::DidLookupRegistrationForMainResource,
......
......@@ -60,7 +60,7 @@ class CONTENT_EXPORT ServiceWorkerControlleeRequestHandler
typedef ServiceWorkerControlleeRequestHandler self;
// For main resource case.
void PrepareForMainResource(const GURL& url);
void PrepareForMainResource(const net::URLRequest* request);
void DidLookupRegistrationForMainResource(
ServiceWorkerStatusCode status,
const scoped_refptr<ServiceWorkerRegistration>& registration);
......
......@@ -18,6 +18,8 @@
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/browser/content_browser_client.h"
#include "content/public/common/content_client.h"
#include "ipc/ipc_message_macros.h"
#include "net/base/net_util.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
......@@ -31,6 +33,7 @@ namespace {
const char kShutdownErrorMessage[] =
"The Service Worker system has shutdown.";
const char kDisabledErrorMessage[] = "The browser has disabled Service Worker.";
const uint32 kFilteredMessageClasses[] = {
ServiceWorkerMsgStart,
......@@ -52,24 +55,18 @@ bool OriginCanAccessServiceWorkers(const GURL& url) {
bool CanRegisterServiceWorker(const GURL& document_url,
const GURL& pattern,
const GURL& script_url) {
// TODO: Respect Chrome's content settings, if we add a setting for
// controlling whether Service Worker is allowed.
return AllOriginsMatch(document_url, pattern, script_url) &&
OriginCanAccessServiceWorkers(document_url);
}
bool CanUnregisterServiceWorker(const GURL& document_url,
const GURL& pattern) {
// TODO: Respect Chrome's content settings, if we add a setting for
// controlling whether Service Worker is allowed.
return document_url.GetOrigin() == pattern.GetOrigin() &&
OriginCanAccessServiceWorkers(document_url);
}
bool CanGetRegistration(const GURL& document_url,
const GURL& given_document_url) {
// TODO: Respect Chrome's content settings, if we add a setting for
// controlling whether Service Worker is allowed.
return document_url.GetOrigin() == given_document_url.GetOrigin() &&
OriginCanAccessServiceWorkers(document_url);
}
......@@ -78,11 +75,13 @@ bool CanGetRegistration(const GURL& document_url,
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
int render_process_id,
MessagePortMessageFilter* message_port_message_filter)
MessagePortMessageFilter* message_port_message_filter,
ResourceContext* resource_context)
: BrowserMessageFilter(kFilteredMessageClasses,
arraysize(kFilteredMessageClasses)),
render_process_id_(render_process_id),
message_port_message_filter_(message_port_message_filter),
resource_context_(resource_context),
channel_ready_(false) {
}
......@@ -258,6 +257,17 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
BadMessageReceived();
return;
}
if (!GetContentClient()->browser()->AllowServiceWorker(
pattern, provider_host->topmost_frame_url(), resource_context_)) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
WebServiceWorkerError::ErrorTypeDisabled,
base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
TRACE_EVENT_ASYNC_BEGIN2("ServiceWorker",
"ServiceWorkerDispatcherHost::RegisterServiceWorker",
request_id,
......@@ -310,6 +320,16 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
return;
}
if (!GetContentClient()->browser()->AllowServiceWorker(
pattern, provider_host->topmost_frame_url(), resource_context_)) {
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
thread_id,
request_id,
WebServiceWorkerError::ErrorTypeDisabled,
base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
TRACE_EVENT_ASYNC_BEGIN1(
"ServiceWorker",
"ServiceWorkerDispatcherHost::UnregisterServiceWorker",
......@@ -359,6 +379,18 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
return;
}
if (!GetContentClient()->browser()->AllowServiceWorker(
provider_host->document_url(),
provider_host->topmost_frame_url(),
resource_context_)) {
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
thread_id,
request_id,
WebServiceWorkerError::ErrorTypeDisabled,
base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
DCHECK_CURRENTLY_ON(BrowserThread::IO);
if (GetContext()->storage()->IsDisabled()) {
SendGetRegistrationError(thread_id, request_id, SERVICE_WORKER_ERROR_ABORT);
......
......@@ -19,6 +19,7 @@ struct EmbeddedWorkerHostMsg_ReportConsoleMessage_Params;
namespace content {
class MessagePortMessageFilter;
class ResourceContext;
class ServiceWorkerContextCore;
class ServiceWorkerContextWrapper;
class ServiceWorkerHandle;
......@@ -32,7 +33,8 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
public:
ServiceWorkerDispatcherHost(
int render_process_id,
MessagePortMessageFilter* message_port_message_filter);
MessagePortMessageFilter* message_port_message_filter,
ResourceContext* resource_context);
void Init(ServiceWorkerContextWrapper* context_wrapper);
......@@ -158,6 +160,7 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
int render_process_id_;
MessagePortMessageFilter* const message_port_message_filter_;
ResourceContext* resource_context_;
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
IDMap<ServiceWorkerHandle, IDMapOwnPointer> handles_;
......
......@@ -16,7 +16,9 @@
#include "content/common/service_worker/embedded_worker_messages.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/public/common/content_switches.h"
#include "content/public/test/mock_resource_context.h"
#include "content/public/test/test_browser_thread_bundle.h"
#include "content/test/test_content_browser_client.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace content {
......@@ -28,8 +30,9 @@ class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
TestingServiceWorkerDispatcherHost(
int process_id,
ServiceWorkerContextWrapper* context_wrapper,
ResourceContext* resource_context,
EmbeddedWorkerTestHelper* helper)
: ServiceWorkerDispatcherHost(process_id, NULL),
: ServiceWorkerDispatcherHost(process_id, NULL, resource_context),
bad_messages_received_count_(0),
helper_(helper) {
Init(context_wrapper);
......@@ -60,7 +63,7 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
virtual void SetUp() {
helper_.reset(new EmbeddedWorkerTestHelper(kRenderProcessId));
dispatcher_host_ = new TestingServiceWorkerDispatcherHost(
kRenderProcessId, context_wrapper(), helper_.get());
kRenderProcessId, context_wrapper(), &resource_context_, helper_.get());
}
virtual void TearDown() {
......@@ -120,10 +123,47 @@ class ServiceWorkerDispatcherHostTest : public testing::Test {
}
TestBrowserThreadBundle browser_thread_bundle_;
content::MockResourceContext resource_context_;
scoped_ptr<EmbeddedWorkerTestHelper> helper_;
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host_;
};
class ServiceWorkerTestContentBrowserClient : public TestContentBrowserClient {
public:
ServiceWorkerTestContentBrowserClient() {}
virtual bool AllowServiceWorker(const GURL& scope,
const GURL& first_party,
content::ResourceContext* context) OVERRIDE {
return false;
}
};
TEST_F(ServiceWorkerDispatcherHostTest,
Register_ContentSettingsDisallowsServiceWorker) {
ServiceWorkerTestContentBrowserClient test_browser_client;
ContentBrowserClient* old_browser_client =
SetBrowserClientForTesting(&test_browser_client);
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
kRenderProcessId, kProviderId, context()->AsWeakPtr(), NULL));
host->SetDocumentUrl(GURL("https://www.example.com/foo"));
context()->AddProviderHost(host.Pass());
Register(kProviderId,
GURL("https://www.example.com/"),
GURL("https://www.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
Unregister(kProviderId,
GURL("https://www.example.com/"),
ServiceWorkerMsg_ServiceWorkerUnregistrationError::ID);
GetRegistration(kProviderId,
GURL("https://www.example.com/"),
ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
SetBrowserClientForTesting(old_browser_client);
}
TEST_F(ServiceWorkerDispatcherHostTest, Register_HTTPS) {
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(new ServiceWorkerProviderHost(
......
......@@ -60,6 +60,10 @@ void ServiceWorkerProviderHost::SetDocumentUrl(const GURL& url) {
document_url_ = url;
}
void ServiceWorkerProviderHost::SetTopmostFrameUrl(const GURL& url) {
topmost_frame_url_ = url;
}
void ServiceWorkerProviderHost::SetControllerVersionAttribute(
ServiceWorkerVersion* version) {
if (version == controlling_version_.get())
......
......@@ -83,6 +83,9 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
void SetDocumentUrl(const GURL& url);
const GURL& document_url() const { return document_url_; }
void SetTopmostFrameUrl(const GURL& url);
const GURL& topmost_frame_url() const { return topmost_frame_url_; }
// Associates to |registration| to listen for its version change events.
void AssociateRegistration(ServiceWorkerRegistration* registration);
......@@ -151,6 +154,7 @@ class CONTENT_EXPORT ServiceWorkerProviderHost
const int process_id_;
const int provider_id_;
GURL document_url_;
GURL topmost_frame_url_;
std::vector<GURL> associated_patterns_;
scoped_refptr<ServiceWorkerRegistration> associated_registration_;
......
......@@ -82,8 +82,10 @@ void ServiceWorkerRequestHandler::InitializeHandler(
return;
if (skip_service_worker) {
if (ServiceWorkerUtils::IsMainResourceType(resource_type))
if (ServiceWorkerUtils::IsMainResourceType(resource_type)) {
provider_host->SetDocumentUrl(net::SimplifyUrlForRequest(request->url()));
provider_host->SetTopmostFrameUrl(request->first_party_for_cookies());
}
return;
}
......
......@@ -116,6 +116,13 @@ bool ContentBrowserClient::AllowAppCache(const GURL& manifest_url,
return true;
}
bool ContentBrowserClient::AllowServiceWorker(
const GURL& scope,
const GURL& document_url,
content::ResourceContext* context) {
return true;
}
bool ContentBrowserClient::AllowGetCookie(const GURL& url,
const GURL& first_party,
const net::CookieList& cookie_list,
......
......@@ -273,6 +273,13 @@ class CONTENT_EXPORT ContentBrowserClient {
const GURL& first_party,
ResourceContext* context);
// Allow the embedder to control if a Service Worker can be associated
// with the given scope.
// This is called on the IO thread.
virtual bool AllowServiceWorker(const GURL& scope,
const GURL& first_party,
content::ResourceContext* context);
// Allow the embedder to control if the given cookie can be read.
// This is called on the IO thread.
virtual bool AllowGetCookie(const GURL& url,
......
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