Skip to content
This repository has been archived by the owner on Apr 3, 2020. It is now read-only.

Commit

Permalink
Merge to M41 branch 2272: Allow SW registration only if it's secure A…
Browse files Browse the repository at this point in the history
…ND it's HTTP or HTTPS

BUG=453982
TEST=tested manually
TEST=content_unittests:ServiceWorkerDispatcherHostTest.Register_FileSystem*

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

Cr-Commit-Position: refs/heads/master@{#314143}
(cherry picked from commit 22394d8)

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

Cr-Commit-Position: refs/branch-heads/2272@{#186}
Cr-Branched-From: 827a380-refs/heads/master@{#310958}
  • Loading branch information
Penny MacNeil committed Feb 2, 2015
1 parent 6b8b695 commit 909dea0
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 40 deletions.
36 changes: 29 additions & 7 deletions content/browser/service_worker/service_worker_dispatcher_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,8 @@ namespace {

const char kNoDocumentURLErrorMessage[] =
"No URL is associated with the caller's document.";
const char kDisallowedURLErrorMessage[] =
"The URL is not supported.";
const char kShutdownErrorMessage[] =
"The Service Worker system has shutdown.";
const char kUserDeniedPermissionMessage[] =
Expand All @@ -52,7 +54,8 @@ bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) {
// consistent with Blink's
// SecurityOrigin::canAccessFeatureRequiringSecureOrigin.
bool OriginCanAccessServiceWorkers(const GURL& url) {
return url.SchemeIsSecure() || net::IsLocalhost(url.host());
return url.SchemeIsHTTPOrHTTPS() &&
(url.SchemeIsSecure() || net::IsLocalhost(url.host()));
}

bool CanRegisterServiceWorker(const GURL& document_url,
Expand All @@ -62,23 +65,27 @@ bool CanRegisterServiceWorker(const GURL& document_url,
DCHECK(pattern.is_valid());
DCHECK(script_url.is_valid());
return AllOriginsMatch(document_url, pattern, script_url) &&
OriginCanAccessServiceWorkers(document_url);
OriginCanAccessServiceWorkers(document_url) &&
OriginCanAccessServiceWorkers(pattern) &&
OriginCanAccessServiceWorkers(script_url);
}

bool CanUnregisterServiceWorker(const GURL& document_url,
const GURL& pattern) {
DCHECK(document_url.is_valid());
DCHECK(pattern.is_valid());
return document_url.GetOrigin() == pattern.GetOrigin() &&
OriginCanAccessServiceWorkers(document_url);
OriginCanAccessServiceWorkers(document_url) &&
OriginCanAccessServiceWorkers(pattern);
}

bool CanGetRegistration(const GURL& document_url,
const GURL& given_document_url) {
DCHECK(document_url.is_valid());
DCHECK(given_document_url.is_valid());
return document_url.GetOrigin() == given_document_url.GetOrigin() &&
OriginCanAccessServiceWorkers(document_url);
OriginCanAccessServiceWorkers(document_url) &&
OriginCanAccessServiceWorkers(given_document_url);
}

} // namespace
Expand Down Expand Up @@ -296,7 +303,12 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(

if (!CanRegisterServiceWorker(
provider_host->document_url(), pattern, script_url)) {
BadMessageReceived();
// TODO(kinuko): Change this back to BadMessageReceived() once we start
// to check these in the renderer too. (http://crbug.com/453982)
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
base::ASCIIToUTF16(kServiceWorkerRegisterErrorPrefix) +
base::ASCIIToUTF16(kDisallowedURLErrorMessage)));
return;
}

Expand Down Expand Up @@ -383,7 +395,12 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
}

if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
BadMessageReceived();
// TODO(kinuko): Change this back to BadMessageReceived() once we start
// to check these in the renderer too. (http://crbug.com/453982)
Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError(
thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
base::ASCIIToUTF16(kServiceWorkerUnregisterErrorPrefix) +
base::ASCIIToUTF16(kDisallowedURLErrorMessage)));
return;
}

Expand Down Expand Up @@ -456,7 +473,12 @@ void ServiceWorkerDispatcherHost::OnGetRegistration(
}

if (!CanGetRegistration(provider_host->document_url(), document_url)) {
BadMessageReceived();
// TODO(kinuko): Change this back to BadMessageReceived() once we start
// to check these in the renderer too. (http://crbug.com/453982)
Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError(
thread_id, request_id, WebServiceWorkerError::ErrorTypeSecurity,
base::ASCIIToUTF16(kServiceWorkerGetRegistrationErrorPrefix) +
base::ASCIIToUTF16(kDisallowedURLErrorMessage)));
return;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -234,10 +234,10 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_NonSecureOriginShouldFail) {
host->SetDocumentUrl(GURL("http://www.example.com/foo"));
context()->AddProviderHost(host.Pass());

SendRegister(kProviderId,
GURL("http://www.example.com/"),
GURL("http://www.example.com/bar"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("http://www.example.com/"),
GURL("http://www.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
Expand All @@ -248,40 +248,88 @@ TEST_F(ServiceWorkerDispatcherHostTest, Register_CrossOriginShouldFail) {
context()->AddProviderHost(host.Pass());

// Script has a different host
SendRegister(kProviderId,
GURL("https://www.example.com/"),
GURL("https://foo.example.com/bar"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("https://www.example.com/"),
GURL("https://foo.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

// Scope has a different host
SendRegister(kProviderId,
GURL("https://foo.example.com/"),
GURL("https://www.example.com/bar"));
EXPECT_EQ(2, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("https://foo.example.com/"),
GURL("https://www.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

// Script has a different port
SendRegister(kProviderId,
GURL("https://www.example.com/"),
GURL("https://www.example.com:8080/bar"));
EXPECT_EQ(3, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("https://www.example.com/"),
GURL("https://www.example.com:8080/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

// Scope has a different transport
SendRegister(kProviderId,
GURL("wss://www.example.com/"),
GURL("https://www.example.com/bar"));
EXPECT_EQ(4, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("wss://www.example.com/"),
GURL("https://www.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

// Script and scope have a different host but match each other
SendRegister(kProviderId,
GURL("https://foo.example.com/"),
GURL("https://foo.example.com/bar"));
EXPECT_EQ(5, dispatcher_host_->bad_messages_received_count_);
Register(kProviderId,
GURL("https://foo.example.com/"),
GURL("https://foo.example.com/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

// Script and scope URLs are invalid
SendRegister(kProviderId,
GURL(),
GURL("h@ttps://@"));
EXPECT_EQ(6, dispatcher_host_->bad_messages_received_count_);
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
}

TEST_F(ServiceWorkerDispatcherHostTest,
Register_FileSystemDocumentShouldFail) {
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
host->SetDocumentUrl(GURL("filesystem:https://www.example.com/temporary/a"));
context()->AddProviderHost(host.Pass());

Register(kProviderId,
GURL("filesystem:https://www.example.com/temporary/"),
GURL("https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

Register(kProviderId,
GURL("https://www.example.com/temporary/"),
GURL("filesystem:https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

Register(kProviderId,
GURL("filesystem:https://www.example.com/temporary/"),
GURL("filesystem:https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest,
Register_FileSystemScriptOrScopeShouldFail) {
const int64 kProviderId = 99; // Dummy value
scoped_ptr<ServiceWorkerProviderHost> host(
CreateServiceWorkerProviderHost(kProviderId));
host->SetDocumentUrl(GURL("https://www.example.com/temporary/"));
context()->AddProviderHost(host.Pass());

Register(kProviderId,
GURL("filesystem:https://www.example.com/temporary/"),
GURL("https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

Register(kProviderId,
GURL("https://www.example.com/temporary/"),
GURL("filesystem:https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);

Register(kProviderId,
GURL("filesystem:https://www.example.com/temporary/"),
GURL("filesystem:https://www.example.com/temporary/bar"),
ServiceWorkerMsg_ServiceWorkerRegistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest, Unregister_HTTPS) {
Expand Down Expand Up @@ -316,8 +364,9 @@ TEST_F(ServiceWorkerDispatcherHostTest, Unregister_CrossOriginShouldFail) {
host->SetDocumentUrl(GURL("https://www.example.com/foo"));
context()->AddProviderHost(host.Pass());

SendUnregister(kProviderId, GURL("https://foo.example.com/"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
Unregister(kProviderId,
GURL("https://foo.example.com/"),
ServiceWorkerMsg_ServiceWorkerUnregistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest, Unregister_InvalidScopeShouldFail) {
Expand All @@ -338,8 +387,9 @@ TEST_F(ServiceWorkerDispatcherHostTest, Unregister_NonSecureOriginShouldFail) {
host->SetDocumentUrl(GURL("http://www.example.com/foo"));
context()->AddProviderHost(host.Pass());

SendUnregister(kProviderId, GURL("http://www.example.com/"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
Unregister(kProviderId,
GURL("http://www.example.com/"),
ServiceWorkerMsg_ServiceWorkerUnregistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest, EarlyContextDeletion) {
Expand Down Expand Up @@ -404,8 +454,9 @@ TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_CrossOriginShouldFail) {
host->SetDocumentUrl(GURL("https://www.example.com/foo"));
context()->AddProviderHost(host.Pass());

SendGetRegistration(kProviderId, GURL("https://foo.example.com/"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
GetRegistration(kProviderId,
GURL("https://foo.example.com/"),
ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest,
Expand All @@ -428,8 +479,9 @@ TEST_F(ServiceWorkerDispatcherHostTest,
host->SetDocumentUrl(GURL("http://www.example.com/foo"));
context()->AddProviderHost(host.Pass());

SendGetRegistration(kProviderId, GURL("http://www.example.com/"));
EXPECT_EQ(1, dispatcher_host_->bad_messages_received_count_);
GetRegistration(kProviderId,
GURL("http://www.example.com/"),
ServiceWorkerMsg_ServiceWorkerGetRegistrationError::ID);
}

TEST_F(ServiceWorkerDispatcherHostTest, GetRegistration_EarlyContextDeletion) {
Expand Down

0 comments on commit 909dea0

Please sign in to comment.