Service worker registration error support

This patch introduces use of WebServiceWorkerError as a means to propagate an
error from the browser to the renderer, and further reflect this error via
WebCallbacks into Blink

BUG=285976
R=jam@chromium.org, michaeln@chromium.org, tsepez@chromium.org
TBR=abarth

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

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@233438 0039d316-1c4b-4281-b951-d872f2087c98
parent 1913f753
......@@ -38,6 +38,7 @@ include_rules = [
"+third_party/WebKit/public/platform/WebIDBTypes.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
"+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebString.h",
"+third_party/WebKit/public/platform/WebVibration.h",
"+third_party/WebKit/public/web/WebAXEnums.h",
......
......@@ -4,7 +4,9 @@
#include "content/browser/service_worker/service_worker_context.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "content/public/common/content_switches.h"
#include "webkit/browser/quota/quota_manager.h"
namespace content {
......@@ -20,6 +22,11 @@ ServiceWorkerContext::ServiceWorkerContext(
path_ = path.Append(kServiceWorkerDirectory);
}
bool ServiceWorkerContext::IsEnabled() {
return CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker);
}
ServiceWorkerContext::~ServiceWorkerContext() {}
} // namespace content
......@@ -7,6 +7,7 @@
#include "base/files/file_path.h"
#include "base/memory/ref_counted.h"
#include "content/common/content_export.h"
namespace base {
class FilePath;
......@@ -23,7 +24,7 @@ namespace content {
// - persistent storage of pattern -> service worker scripts
// - initialization and initial installation of service workers
// - dispatching of non-fetch events to service workers
class ServiceWorkerContext
class CONTENT_EXPORT ServiceWorkerContext
: public base::RefCountedThreadSafe<ServiceWorkerContext> {
public:
// This is owned by the StoragePartition, which will supply it with
......@@ -31,12 +32,16 @@ class ServiceWorkerContext
ServiceWorkerContext(const base::FilePath& path,
quota::QuotaManagerProxy* quota_manager_proxy);
bool IsEnabled();
private:
friend class base::RefCountedThreadSafe<ServiceWorkerContext>;
~ServiceWorkerContext();
scoped_refptr<quota::QuotaManagerProxy> quota_manager_proxy_;
base::FilePath path_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerContext);
};
} // namespace content
......
......@@ -4,11 +4,15 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/service_worker/service_worker_context.h"
#include "content/common/service_worker_messages.h"
#include "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
using WebKit::WebServiceWorkerError;
namespace content {
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
......@@ -17,6 +21,11 @@ ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {}
namespace {
const char kDomainMismatchErrorMessage[] =
"Scope and scripts do not have the same origin";
}
bool ServiceWorkerDispatcherHost::OnMessageReceived(const IPC::Message& message,
bool* message_was_ok) {
if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart)
......@@ -47,13 +56,26 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
int32 request_id,
const GURL& scope,
const GURL& script_url) {
// TODO(alecflett): add a ServiceWorker-specific policy query in
// ChildProcessSecurityImpl. See http://crbug.com/311631.
if (!context_->IsEnabled()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
WebKit::WebServiceWorkerError::DisabledError,
ASCIIToUTF16("ServiceWorker is disabled")));
return;
}
// TODO(alecflett): Throw an error for origin mismatch, rather than
// just returning.
if (scope.GetOrigin() != script_url.GetOrigin())
// TODO(alecflett): This check is insufficient for release. Add a
// ServiceWorker-specific policy query in
// ChildProcessSecurityImpl. See http://crbug.com/311631.
if (scope.GetOrigin() != script_url.GetOrigin()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
WebKit::WebServiceWorkerError::SecurityError,
ASCIIToUTF16(kDomainMismatchErrorMessage)));
return;
}
Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
thread_id, request_id, NextWorkerId()));
......@@ -62,8 +84,17 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(int32 thread_id,
int32 request_id,
const GURL& scope) {
// TODO(alecflett): add a ServiceWorker-specific policy query in
// TODO(alecflett): This check is insufficient for release. Add a
// ServiceWorker-specific policy query in
// ChildProcessSecurityImpl. See http://crbug.com/311631.
if (!context_->IsEnabled()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
WebServiceWorkerError::DisabledError,
ASCIIToUTF16("ServiceWorker is disabled")));
return;
}
Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, request_id));
}
......
......@@ -13,7 +13,7 @@ namespace content {
class ServiceWorkerContext;
class ServiceWorkerDispatcherHost : public BrowserMessageFilter {
class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
public:
ServiceWorkerDispatcherHost(int render_process_id,
ServiceWorkerContext* context);
......
// Copyright (c) 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "base/command_line.h"
#include "base/files/file_path.h"
#include "content/browser/service_worker/service_worker_context.h"
#include "content/common/service_worker_messages.h"
#include "content/public/common/content_switches.h"
#include "testing/gtest/include/gtest/gtest.h"
using base::MessageLoop;
namespace content {
class ServiceWorkerDispatcherHostTest : public testing::Test {
protected:
virtual void SetUp() {
context_ = new ServiceWorkerContext(base::FilePath(), NULL);
}
virtual void TearDown() {
DCHECK(context_->HasOneRef());
context_ = NULL;
}
scoped_refptr<ServiceWorkerContext> context_;
};
namespace {
static const int kRenderProcessId = 1;
class TestingServiceWorkerDispatcherHost : public ServiceWorkerDispatcherHost {
public:
TestingServiceWorkerDispatcherHost(int process_id,
ServiceWorkerContext* context)
: ServiceWorkerDispatcherHost(process_id, context) {}
virtual bool Send(IPC::Message* message) OVERRIDE {
sent_messages_.push_back(message);
return true;
}
ScopedVector<IPC::Message> sent_messages_;
protected:
virtual ~TestingServiceWorkerDispatcherHost() {}
};
} // namespace
TEST_F(ServiceWorkerDispatcherHostTest, DisabledCausesError) {
DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker));
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(kRenderProcessId, context_);
bool handled;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, GURL(), GURL()),
&handled);
DCHECK(handled);
// TODO(alecflett): Pump the message loop when this becomes async.
DCHECK_EQ(1UL, dispatcher_host->sent_messages_.size());
DCHECK_EQ(
static_cast<uint32>(ServiceWorkerMsg_ServiceWorkerRegistrationError::ID),
dispatcher_host->sent_messages_[0]->type());
}
TEST_F(ServiceWorkerDispatcherHostTest, Enabled) {
DCHECK(!CommandLine::ForCurrentProcess()->HasSwitch(
switches::kEnableServiceWorker));
CommandLine::ForCurrentProcess()->AppendSwitch(
switches::kEnableServiceWorker);
scoped_refptr<TestingServiceWorkerDispatcherHost> dispatcher_host =
new TestingServiceWorkerDispatcherHost(kRenderProcessId, context_);
bool handled;
dispatcher_host->OnMessageReceived(
ServiceWorkerHostMsg_RegisterServiceWorker(-1, -1, GURL(), GURL()),
&handled);
DCHECK(handled);
// TODO(alecflett): Pump the message loop when this becomes async.
DCHECK_EQ(1UL, dispatcher_host->sent_messages_.size());
DCHECK_EQ(static_cast<uint32>(ServiceWorkerMsg_ServiceWorkerRegistered::ID),
dispatcher_host->sent_messages_[0]->type());
}
} // namespace content
......@@ -11,6 +11,7 @@
#include "content/common/service_worker_messages.h"
#include "third_party/WebKit/public/web/WebSecurityOrigin.h"
using WebKit::WebServiceWorkerError;
using WebKit::WebServiceWorkerProvider;
using base::ThreadLocalPointer;
using webkit_glue::WorkerTaskRunner;
......@@ -44,10 +45,11 @@ ServiceWorkerDispatcher::~ServiceWorkerDispatcher() {
void ServiceWorkerDispatcher::OnMessageReceived(const IPC::Message& msg) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcher, msg)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered,
OnServiceWorkerRegistered)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistered, OnRegistered)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerUnregistered,
OnServiceWorkerUnregistered)
OnUnregistered)
IPC_MESSAGE_HANDLER(ServiceWorkerMsg_ServiceWorkerRegistrationError,
OnRegistrationError)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
DCHECK(handled) << "Unhandled message:" << msg.type();
......@@ -92,7 +94,7 @@ ServiceWorkerDispatcher* ServiceWorkerDispatcher::ThreadSpecificInstance(
return dispatcher;
}
void ServiceWorkerDispatcher::OnServiceWorkerRegistered(
void ServiceWorkerDispatcher::OnRegistered(
int32 thread_id,
int32 request_id,
int64 service_worker_id) {
......@@ -114,8 +116,9 @@ void ServiceWorkerDispatcher::OnServiceWorkerRegistered(
pending_callbacks_.Remove(request_id);
}
void ServiceWorkerDispatcher::OnServiceWorkerUnregistered(int32 thread_id,
int32 request_id) {
void ServiceWorkerDispatcher::OnUnregistered(
int32 thread_id,
int32 request_id) {
WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
pending_callbacks_.Lookup(request_id);
DCHECK(callbacks);
......@@ -126,6 +129,23 @@ void ServiceWorkerDispatcher::OnServiceWorkerUnregistered(int32 thread_id,
pending_callbacks_.Remove(request_id);
}
void ServiceWorkerDispatcher::OnRegistrationError(
int32 thread_id,
int32 request_id,
WebServiceWorkerError::ErrorType error_type,
const string16& message) {
WebServiceWorkerProvider::WebServiceWorkerCallbacks* callbacks =
pending_callbacks_.Lookup(request_id);
DCHECK(callbacks);
if (!callbacks)
return;
scoped_ptr<WebServiceWorkerError> error(
new WebServiceWorkerError(error_type, message));
callbacks->onError(error.release());
pending_callbacks_.Remove(request_id);
}
void ServiceWorkerDispatcher::OnWorkerRunLoopStopped() { delete this; }
} // namespace content
......@@ -8,6 +8,7 @@
#include "base/id_map.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerProvider.h"
#include "webkit/child/worker_task_runner.h"
......@@ -57,11 +58,14 @@ class ServiceWorkerDispatcher : public webkit_glue::WorkerTaskRunner::Observer {
virtual void OnWorkerRunLoopStopped() OVERRIDE;
// The asynchronous success response to RegisterServiceWorker.
void OnServiceWorkerRegistered(int32 thread_id,
int32 request_id,
int64 service_worker_id);
void OnRegistered(int32 thread_id, int32 request_id, int64 service_worker_id);
// The asynchronous success response to UregisterServiceWorker.
void OnServiceWorkerUnregistered(int32 thread_id, int32 request_id);
void OnUnregistered(int32 thread_id,
int32 request_id);
void OnRegistrationError(int32 thread_id,
int32 request_id,
WebKit::WebServiceWorkerError::ErrorType error_type,
const string16& message);
IDMap<WebKit::WebServiceWorkerProvider::WebServiceWorkerCallbacks,
IDMapOwnPointer> pending_callbacks_;
......
......@@ -26,6 +26,7 @@ include_rules = [
"+third_party/WebKit/public/platform/WebIDBTypes.h",
"+third_party/WebKit/public/platform/WebReferrerPolicy.h",
"+third_party/WebKit/public/platform/WebScreenInfo.h",
"+third_party/WebKit/public/platform/WebServiceWorkerError.h",
"+third_party/WebKit/public/platform/WebStorageArea.h",
"+third_party/WebKit/public/platform/WebString.h",
"+third_party/WebKit/public/platform/linux/WebFontFamily.h",
......
......@@ -7,10 +7,16 @@
#include "base/strings/string16.h"
#include "ipc/ipc_message_macros.h"
#include "ipc/ipc_param_traits.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
#undef IPC_MESSAGE_EXPORT
#define IPC_MESSAGE_EXPORT CONTENT_EXPORT
#define IPC_MESSAGE_START ServiceWorkerMsgStart
IPC_ENUM_TRAITS(WebKit::WebServiceWorkerError::ErrorType)
// Messages sent from the child process to the browser.
IPC_MESSAGE_CONTROL4(ServiceWorkerHostMsg_RegisterServiceWorker,
......@@ -36,3 +42,11 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerRegistered,
IPC_MESSAGE_CONTROL2(ServiceWorkerMsg_ServiceWorkerUnregistered,
int32 /* thread_id */,
int32 /* request_id */)
// Sent when any kind of registration error occurs during a
// RegisterServiceWorker / UnregisterServiceWorker handler above.
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerRegistrationError,
int32 /* thread_id */,
int32 /* request_id */,
WebKit::WebServiceWorkerError::ErrorType /* code */,
string16 /* message */)
......@@ -452,9 +452,10 @@
'browser/renderer_host/synthetic_gesture_controller_unittest.cc',
'browser/renderer_host/text_input_client_mac_unittest.mm',
'browser/renderer_host/web_input_event_aura_unittest.cc',
'browser/renderer_host/websocket_dispatcher_host_unittest.cc',
'browser/renderer_host/input/web_input_event_builders_gtk_unittest.cc',
'browser/renderer_host/websocket_dispatcher_host_unittest.cc',
'browser/resolve_proxy_msg_helper_unittest.cc',
'browser/service_worker/service_worker_dispatcher_host_unittest.cc',
'browser/site_instance_impl_unittest.cc',
'browser/speech/chunked_byte_buffer_unittest.cc',
'browser/speech/endpointer/endpointer_unittest.cc',
......@@ -463,8 +464,8 @@
'browser/speech/speech_recognizer_impl_unittest.cc',
'browser/ssl/ssl_host_state_unittest.cc',
'browser/startup_task_runner_unittest.cc',
'browser/storage_partition_impl_unittest.cc',
'browser/storage_partition_impl_map_unittest.cc',
'browser/storage_partition_impl_unittest.cc',
'browser/streams/stream_unittest.cc',
'browser/streams/stream_url_request_job_unittest.cc',
'browser/system_message_window_win_unittest.cc',
......
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