summaryrefslogtreecommitdiffstats
path: root/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/content/browser/service_worker/service_worker_dispatcher_host.cc')
-rw-r--r--chromium/content/browser/service_worker/service_worker_dispatcher_host.cc380
1 files changed, 319 insertions, 61 deletions
diff --git a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
index 76e7ff746ae..964a393f8eb 100644
--- a/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
+++ b/chromium/content/browser/service_worker/service_worker_dispatcher_host.cc
@@ -4,18 +4,26 @@
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
+#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
+#include "content/browser/message_port_message_filter.h"
+#include "content/browser/message_port_service.h"
#include "content/browser/service_worker/embedded_worker_registry.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_context_wrapper.h"
-#include "content/browser/service_worker/service_worker_provider_host.h"
-#include "content/common/service_worker_messages.h"
+#include "content/browser/service_worker/service_worker_handle.h"
+#include "content/browser/service_worker/service_worker_registration.h"
+#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 "ipc/ipc_message_macros.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerError.h"
#include "url/gurl.h"
using blink::WebServiceWorkerError;
+namespace content {
+
namespace {
const char kDisabledErrorMessage[] =
@@ -23,19 +31,43 @@ const char kDisabledErrorMessage[] =
const char kDomainMismatchErrorMessage[] =
"Scope and scripts do not have the same origin";
-} // namespace
+const uint32 kFilteredMessageClasses[] = {
+ ServiceWorkerMsgStart,
+ EmbeddedWorkerMsgStart,
+};
-namespace content {
+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 document_url.GetOrigin() == pattern.GetOrigin() &&
+ document_url.GetOrigin() == script_url.GetOrigin();
+}
+
+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();
+}
+
+} // namespace
ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost(
- int render_process_id)
- : render_process_id_(render_process_id) {
+ int render_process_id,
+ MessagePortMessageFilter* message_port_message_filter)
+ : BrowserMessageFilter(kFilteredMessageClasses,
+ arraysize(kFilteredMessageClasses)),
+ render_process_id_(render_process_id),
+ message_port_message_filter_(message_port_message_filter),
+ channel_ready_(false) {
}
ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() {
- if (context_) {
- context_->RemoveAllProviderHostsForProcess(render_process_id_);
- context_->embedded_worker_registry()->RemoveChildProcessSender(
+ if (GetContext()) {
+ GetContext()->RemoveAllProviderHostsForProcess(render_process_id_);
+ GetContext()->embedded_worker_registry()->RemoveChildProcessSender(
render_process_id_);
}
}
@@ -46,27 +78,32 @@ void ServiceWorkerDispatcherHost::Init(
BrowserThread::PostTask(
BrowserThread::IO, FROM_HERE,
base::Bind(&ServiceWorkerDispatcherHost::Init,
- this, make_scoped_refptr(context_wrapper)));
- return;
+ this, make_scoped_refptr(context_wrapper)));
+ return;
}
- context_ = context_wrapper->context()->AsWeakPtr();
- context_->embedded_worker_registry()->AddChildProcessSender(
+ context_wrapper_ = context_wrapper;
+ GetContext()->embedded_worker_registry()->AddChildProcessSender(
render_process_id_, this);
}
+void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) {
+ BrowserMessageFilter::OnFilterAdded(sender);
+ channel_ready_ = true;
+ std::vector<IPC::Message*> messages;
+ pending_messages_.release(&messages);
+ for (size_t i = 0; i < messages.size(); ++i) {
+ BrowserMessageFilter::Send(messages[i]);
+ }
+}
+
void ServiceWorkerDispatcherHost::OnDestruct() const {
BrowserThread::DeleteOnIOThread::Destruct(this);
}
bool ServiceWorkerDispatcherHost::OnMessageReceived(
- const IPC::Message& message,
- bool* message_was_ok) {
- if (IPC_MESSAGE_CLASS(message) != ServiceWorkerMsgStart)
- return false;
-
+ const IPC::Message& message) {
bool handled = true;
- IPC_BEGIN_MESSAGE_MAP_EX(
- ServiceWorkerDispatcherHost, message, *message_was_ok)
+ IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker,
OnRegisterServiceWorker)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker,
@@ -75,41 +112,100 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
OnProviderCreated)
IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed,
OnProviderDestroyed)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId,
+ OnSetHostedVersionId)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker,
+ OnPostMessageToWorker)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded,
+ OnWorkerScriptLoaded)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed,
+ OnWorkerScriptLoadFailed)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted,
+ OnWorkerStarted)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped,
+ OnWorkerStopped)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportException,
+ OnReportException)
+ IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_ReportConsoleMessage,
+ OnReportConsoleMessage)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
+ OnIncrementServiceWorkerRefCount)
+ IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
+ OnDecrementServiceWorkerRefCount)
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
+ if (!handled && GetContext()) {
+ handled =
+ GetContext()->embedded_worker_registry()->OnMessageReceived(message);
+ if (!handled)
+ BadMessageReceived();
+ }
+
return handled;
}
+bool ServiceWorkerDispatcherHost::Send(IPC::Message* message) {
+ if (channel_ready_) {
+ BrowserMessageFilter::Send(message);
+ // Don't bother passing through Send()'s result: it's not reliable.
+ return true;
+ }
+
+ pending_messages_.push_back(message);
+ return true;
+}
+
+void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
+ scoped_ptr<ServiceWorkerHandle> handle) {
+ int handle_id = handle->handle_id();
+ handles_.AddWithID(handle.release(), handle_id);
+}
+
void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
- int32 thread_id,
- int32 request_id,
+ int thread_id,
+ int request_id,
+ int provider_id,
const GURL& pattern,
const GURL& script_url) {
- if (!context_ || !context_->IsEnabled()) {
+ if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- WebServiceWorkerError::DisabledError,
- ASCIIToUTF16(kDisabledErrorMessage)));
+ WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
- // TODO(alecflett): This check is insufficient for release. Add a
- // ServiceWorker-specific policy query in
- // ChildProcessSecurityImpl. See http://crbug.com/311631.
- if (pattern.GetOrigin() != script_url.GetOrigin()) {
+ ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
+ render_process_id_, provider_id);
+ if (!provider_host) {
+ BadMessageReceived();
+ return;
+ }
+ if (!provider_host->IsContextAlive()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- WebServiceWorkerError::SecurityError,
- ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
- context_->RegisterServiceWorker(
+ if (!CanRegisterServiceWorker(
+ provider_host->document_url(), pattern, script_url)) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ return;
+ }
+ GetContext()->RegisterServiceWorker(
pattern,
script_url,
+ render_process_id_,
+ provider_host,
base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete,
this,
thread_id,
@@ -117,22 +213,44 @@ void ServiceWorkerDispatcherHost::OnRegisterServiceWorker(
}
void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
- int32 thread_id,
- int32 request_id,
+ int thread_id,
+ int request_id,
+ int provider_id,
const GURL& pattern) {
- // TODO(alecflett): This check is insufficient for release. Add a
- // ServiceWorker-specific policy query in
- // ChildProcessSecurityImpl. See http://crbug.com/311631.
- if (!context_ || !context_->IsEnabled()) {
+ if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled()) {
Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
thread_id,
request_id,
- blink::WebServiceWorkerError::DisabledError,
- ASCIIToUTF16(kDisabledErrorMessage)));
+ blink::WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
return;
}
- context_->UnregisterServiceWorker(
+ ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost(
+ render_process_id_, provider_id);
+ if (!provider_host) {
+ BadMessageReceived();
+ return;
+ }
+ if (!provider_host->IsContextAlive()) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ blink::WebServiceWorkerError::ErrorTypeDisabled,
+ base::ASCIIToUTF16(kDisabledErrorMessage)));
+ return;
+ }
+
+ if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) {
+ Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError(
+ thread_id,
+ request_id,
+ WebServiceWorkerError::ErrorTypeSecurity,
+ base::ASCIIToUTF16(kDomainMismatchErrorMessage)));
+ return;
+ }
+
+ GetContext()->UnregisterServiceWorker(
pattern,
base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete,
this,
@@ -140,47 +258,183 @@ void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker(
request_id));
}
+void ServiceWorkerDispatcherHost::OnPostMessageToWorker(
+ int handle_id,
+ const base::string16& message,
+ const std::vector<int>& sent_message_port_ids) {
+ if (!GetContext() || !ServiceWorkerUtils::IsFeatureEnabled())
+ return;
+
+ ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
+ if (!handle) {
+ BadMessageReceived();
+ return;
+ }
+
+ std::vector<int> new_routing_ids;
+ message_port_message_filter_->UpdateMessagePortsWithNewRoutes(
+ sent_message_port_ids, &new_routing_ids);
+ handle->version()->SendMessage(
+ ServiceWorkerMsg_MessageToWorker(message,
+ sent_message_port_ids,
+ new_routing_ids),
+ base::Bind(&ServiceWorkerUtils::NoOpStatusCallback));
+}
+
void ServiceWorkerDispatcherHost::OnProviderCreated(int provider_id) {
- if (!context_)
+ if (!GetContext())
return;
- if (context_->GetProviderHost(render_process_id_, provider_id)) {
+ if (GetContext()->GetProviderHost(render_process_id_, provider_id)) {
BadMessageReceived();
return;
}
scoped_ptr<ServiceWorkerProviderHost> provider_host(
- new ServiceWorkerProviderHost(render_process_id_, provider_id));
- context_->AddProviderHost(provider_host.Pass());
+ new ServiceWorkerProviderHost(
+ render_process_id_, provider_id, GetContext()->AsWeakPtr(), this));
+ GetContext()->AddProviderHost(provider_host.Pass());
}
void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) {
- if (!context_)
+ if (!GetContext())
return;
- if (!context_->GetProviderHost(render_process_id_, provider_id)) {
+ if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) {
BadMessageReceived();
return;
}
- context_->RemoveProviderHost(render_process_id_, provider_id);
+ GetContext()->RemoveProviderHost(render_process_id_, provider_id);
+}
+
+void ServiceWorkerDispatcherHost::OnSetHostedVersionId(
+ int provider_id, int64 version_id) {
+ if (!GetContext())
+ return;
+ ServiceWorkerProviderHost* provider_host =
+ GetContext()->GetProviderHost(render_process_id_, provider_id);
+ if (!provider_host) {
+ BadMessageReceived();
+ return;
+ }
+ if (!provider_host->IsContextAlive())
+ return;
+ if (!provider_host->SetHostedVersionId(version_id))
+ BadMessageReceived();
}
void ServiceWorkerDispatcherHost::RegistrationComplete(
- int32 thread_id,
- int32 request_id,
- ServiceWorkerRegistrationStatus status,
- int64 registration_id) {
- if (status != REGISTRATION_OK) {
+ int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status,
+ int64 registration_id,
+ int64 version_id) {
+ if (!GetContext())
+ return;
+
+ if (status != SERVICE_WORKER_OK) {
SendRegistrationError(thread_id, request_id, status);
return;
}
+ ServiceWorkerVersion* version = GetContext()->GetLiveVersion(version_id);
+ DCHECK(version);
+ DCHECK_EQ(registration_id, version->registration_id());
+ scoped_ptr<ServiceWorkerHandle> handle =
+ ServiceWorkerHandle::Create(GetContext()->AsWeakPtr(),
+ this, thread_id, version);
Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
- thread_id, request_id, registration_id));
+ thread_id, request_id, handle->GetObjectInfo()));
+ RegisterServiceWorkerHandle(handle.Pass());
+}
+
+// TODO(nhiroki): These message handlers that take |embedded_worker_id| as an
+// input should check if the worker refers to the live context. If the context
+// was deleted, handle the messege gracefully (http://crbug.com/371675).
+void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(int embedded_worker_id) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnWorkerScriptLoaded(
+ render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed(
+ int embedded_worker_id) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnWorkerScriptLoadFailed(
+ render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerStarted(
+ int thread_id, int embedded_worker_id) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnWorkerStarted(
+ render_process_id_, thread_id, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnWorkerStopped(
+ render_process_id_, embedded_worker_id);
+}
+
+void ServiceWorkerDispatcherHost::OnReportException(
+ int embedded_worker_id,
+ const base::string16& error_message,
+ int line_number,
+ int column_number,
+ const GURL& source_url) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnReportException(
+ embedded_worker_id,
+ error_message,
+ line_number,
+ column_number,
+ source_url);
+}
+
+void ServiceWorkerDispatcherHost::OnReportConsoleMessage(
+ int embedded_worker_id,
+ const EmbeddedWorkerHostMsg_ReportConsoleMessage_Params& params) {
+ if (!GetContext())
+ return;
+ GetContext()->embedded_worker_registry()->OnReportConsoleMessage(
+ embedded_worker_id,
+ params.source_identifier,
+ params.message_level,
+ params.message,
+ params.line_number,
+ params.source_url);
+}
+
+void ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount(
+ int handle_id) {
+ ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
+ if (!handle) {
+ BadMessageReceived();
+ return;
+ }
+ handle->IncrementRefCount();
+}
+
+void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
+ int handle_id) {
+ ServiceWorkerHandle* handle = handles_.Lookup(handle_id);
+ if (!handle) {
+ BadMessageReceived();
+ return;
+ }
+ handle->DecrementRefCount();
+ if (handle->HasNoRefCount())
+ handles_.Remove(handle_id);
}
void ServiceWorkerDispatcherHost::UnregistrationComplete(
- int32 thread_id,
- int32 request_id,
- ServiceWorkerRegistrationStatus status) {
- if (status != REGISTRATION_OK) {
+ int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status) {
+ if (status != SERVICE_WORKER_OK) {
SendRegistrationError(thread_id, request_id, status);
return;
}
@@ -189,9 +443,9 @@ void ServiceWorkerDispatcherHost::UnregistrationComplete(
}
void ServiceWorkerDispatcherHost::SendRegistrationError(
- int32 thread_id,
- int32 request_id,
- ServiceWorkerRegistrationStatus status) {
+ int thread_id,
+ int request_id,
+ ServiceWorkerStatusCode status) {
base::string16 error_message;
blink::WebServiceWorkerError::ErrorType error_type;
GetServiceWorkerRegistrationStatusResponse(
@@ -200,4 +454,8 @@ void ServiceWorkerDispatcherHost::SendRegistrationError(
thread_id, request_id, error_type, error_message));
}
+ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() {
+ return context_wrapper_->context();
+}
+
} // namespace content