| // Copyright 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/debug/trace_event.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_handle.h" |
| #include "content/browser/service_worker/service_worker_registration.h" |
| #include "content/browser/service_worker/service_worker_registration_handle.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 "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" |
| #include "url/gurl.h" |
| |
| using blink::WebServiceWorkerError; |
| |
| namespace content { |
| |
| 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 kDisabledErrorMessage[] = "The browser has disabled Service Worker."; |
| |
| const uint32 kFilteredMessageClasses[] = { |
| ServiceWorkerMsgStart, |
| EmbeddedWorkerMsgStart, |
| }; |
| |
| bool AllOriginsMatch(const GURL& url_a, const GURL& url_b, const GURL& url_c) { |
| return url_a.GetOrigin() == url_b.GetOrigin() && |
| url_a.GetOrigin() == url_c.GetOrigin(); |
| } |
| |
| // TODO(dominicc): When crbug.com/362214 is fixed use that to be |
| // consistent with Blink's |
| // SecurityOrigin::canAccessFeatureRequiringSecureOrigin. |
| bool OriginCanAccessServiceWorkers(const GURL& url) { |
| return url.SchemeIsHTTPOrHTTPS() && |
| (url.SchemeIsSecure() || net::IsLocalhost(url.host())); |
| } |
| |
| bool CanRegisterServiceWorker(const GURL& document_url, |
| const GURL& pattern, |
| const GURL& script_url) { |
| DCHECK(document_url.is_valid()); |
| DCHECK(pattern.is_valid()); |
| DCHECK(script_url.is_valid()); |
| return AllOriginsMatch(document_url, pattern, script_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(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(given_document_url); |
| } |
| |
| } // namespace |
| |
| ServiceWorkerDispatcherHost::ServiceWorkerDispatcherHost( |
| int render_process_id, |
| 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) { |
| } |
| |
| ServiceWorkerDispatcherHost::~ServiceWorkerDispatcherHost() { |
| if (GetContext()) { |
| GetContext()->RemoveAllProviderHostsForProcess(render_process_id_); |
| GetContext()->embedded_worker_registry()->RemoveChildProcessSender( |
| render_process_id_); |
| } |
| } |
| |
| void ServiceWorkerDispatcherHost::Init( |
| ServiceWorkerContextWrapper* context_wrapper) { |
| if (!BrowserThread::CurrentlyOn(BrowserThread::IO)) { |
| BrowserThread::PostTask( |
| BrowserThread::IO, FROM_HERE, |
| base::Bind(&ServiceWorkerDispatcherHost::Init, |
| this, make_scoped_refptr(context_wrapper))); |
| return; |
| } |
| |
| context_wrapper_ = context_wrapper; |
| GetContext()->embedded_worker_registry()->AddChildProcessSender( |
| render_process_id_, this); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnFilterAdded(IPC::Sender* sender) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnFilterAdded"); |
| 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::OnFilterRemoved() { |
| // Don't wait until the destructor to teardown since a new dispatcher host |
| // for this process might be created before then. |
| if (GetContext()) { |
| GetContext()->RemoveAllProviderHostsForProcess(render_process_id_); |
| GetContext()->embedded_worker_registry()->RemoveChildProcessSender( |
| render_process_id_); |
| } |
| context_wrapper_ = nullptr; |
| channel_ready_ = false; |
| } |
| |
| void ServiceWorkerDispatcherHost::OnDestruct() const { |
| BrowserThread::DeleteOnIOThread::Destruct(this); |
| } |
| |
| bool ServiceWorkerDispatcherHost::OnMessageReceived( |
| const IPC::Message& message) { |
| bool handled = true; |
| IPC_BEGIN_MESSAGE_MAP(ServiceWorkerDispatcherHost, message) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_RegisterServiceWorker, |
| OnRegisterServiceWorker) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_UnregisterServiceWorker, |
| OnUnregisterServiceWorker) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_GetRegistration, |
| OnGetRegistration) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderCreated, |
| OnProviderCreated) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_ProviderDestroyed, |
| OnProviderDestroyed) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_SetVersionId, |
| OnSetHostedVersionId) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_PostMessageToWorker, |
| OnPostMessageToWorker) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerReadyForInspection, |
| OnWorkerReadyForInspection) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoaded, |
| OnWorkerScriptLoaded) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptLoadFailed, |
| OnWorkerScriptLoadFailed) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerScriptEvaluated, |
| OnWorkerScriptEvaluated) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStarted, |
| OnWorkerStarted) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_WorkerStopped, |
| OnWorkerStopped) |
| IPC_MESSAGE_HANDLER(EmbeddedWorkerHostMsg_DidPauseAfterDownload, |
| OnPausedAfterDownload) |
| 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_HANDLER(ServiceWorkerHostMsg_IncrementRegistrationRefCount, |
| OnIncrementRegistrationRefCount) |
| IPC_MESSAGE_HANDLER(ServiceWorkerHostMsg_DecrementRegistrationRefCount, |
| OnDecrementRegistrationRefCount) |
| 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; |
| } |
| |
| ServiceWorkerRegistrationHandle* |
| ServiceWorkerDispatcherHost::GetOrCreateRegistrationHandle( |
| int provider_id, |
| ServiceWorkerRegistration* registration) { |
| ServiceWorkerRegistrationHandle* handle = |
| FindRegistrationHandle(provider_id, registration->id()); |
| if (handle) { |
| handle->IncrementRefCount(); |
| return handle; |
| } |
| |
| scoped_ptr<ServiceWorkerRegistrationHandle> new_handle( |
| new ServiceWorkerRegistrationHandle( |
| GetContext()->AsWeakPtr(), this, provider_id, registration)); |
| handle = new_handle.get(); |
| RegisterServiceWorkerRegistrationHandle(new_handle.Pass()); |
| return handle; |
| } |
| |
| void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle( |
| scoped_ptr<ServiceWorkerHandle> handle) { |
| int handle_id = handle->handle_id(); |
| handles_.AddWithID(handle.release(), handle_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::RegisterServiceWorkerRegistrationHandle( |
| scoped_ptr<ServiceWorkerRegistrationHandle> handle) { |
| int handle_id = handle->handle_id(); |
| registration_handles_.AddWithID(handle.release(), handle_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnRegisterServiceWorker( |
| int thread_id, |
| int request_id, |
| int provider_id, |
| const GURL& pattern, |
| const GURL& script_url) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnRegisterServiceWorker"); |
| if (!GetContext()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( |
| thread_id, |
| request_id, |
| WebServiceWorkerError::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| if (!pattern.is_valid() || !script_url.is_valid()) { |
| BadMessageReceived(); |
| return; |
| } |
| |
| 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::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| |
| // TODO(ksakamoto): Currently, document_url is empty if the document is in an |
| // IFRAME using frame.contentDocument.write(...). We can remove this check |
| // once crbug.com/439697 is fixed. |
| if (provider_host->document_url().is_empty()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( |
| thread_id, |
| request_id, |
| WebServiceWorkerError::ErrorTypeSecurity, |
| base::ASCIIToUTF16(kNoDocumentURLErrorMessage))); |
| return; |
| } |
| |
| if (!CanRegisterServiceWorker( |
| provider_host->document_url(), pattern, script_url)) { |
| // 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; |
| } |
| |
| std::string error_message; |
| if (!ServiceWorkerUtils::IsPathRestrictionSatisfied( |
| pattern, script_url, &error_message)) { |
| Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( |
| thread_id, |
| request_id, |
| WebServiceWorkerError::ErrorTypeSecurity, |
| base::UTF8ToUTF16(error_message))); |
| 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, |
| "Pattern", pattern.spec(), |
| "Script URL", script_url.spec()); |
| GetContext()->RegisterServiceWorker( |
| pattern, |
| script_url, |
| provider_host, |
| base::Bind(&ServiceWorkerDispatcherHost::RegistrationComplete, |
| this, |
| thread_id, |
| provider_id, |
| request_id)); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnUnregisterServiceWorker( |
| int thread_id, |
| int request_id, |
| int provider_id, |
| const GURL& pattern) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnUnregisterServiceWorker"); |
| if (!GetContext()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError( |
| thread_id, |
| request_id, |
| blink::WebServiceWorkerError::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| if (!pattern.is_valid()) { |
| BadMessageReceived(); |
| return; |
| } |
| |
| ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost( |
| render_process_id_, provider_id); |
| if (!provider_host) { |
| BadMessageReceived(); |
| return; |
| } |
| if (!provider_host->IsContextAlive()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError( |
| thread_id, |
| request_id, |
| blink::WebServiceWorkerError::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| |
| // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed. |
| if (provider_host->document_url().is_empty()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError( |
| thread_id, |
| request_id, |
| WebServiceWorkerError::ErrorTypeSecurity, |
| base::ASCIIToUTF16(kNoDocumentURLErrorMessage))); |
| return; |
| } |
| |
| if (!CanUnregisterServiceWorker(provider_host->document_url(), pattern)) { |
| // 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; |
| } |
| |
| 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", |
| request_id, |
| "Pattern", pattern.spec()); |
| GetContext()->UnregisterServiceWorker( |
| pattern, |
| base::Bind(&ServiceWorkerDispatcherHost::UnregistrationComplete, |
| this, |
| thread_id, |
| request_id)); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnGetRegistration( |
| int thread_id, |
| int request_id, |
| int provider_id, |
| const GURL& document_url) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnGetRegistration"); |
| if (!GetContext()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError( |
| thread_id, |
| request_id, |
| blink::WebServiceWorkerError::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| if (!document_url.is_valid()) { |
| BadMessageReceived(); |
| return; |
| } |
| |
| ServiceWorkerProviderHost* provider_host = GetContext()->GetProviderHost( |
| render_process_id_, provider_id); |
| if (!provider_host) { |
| BadMessageReceived(); |
| return; |
| } |
| if (!provider_host->IsContextAlive()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError( |
| thread_id, |
| request_id, |
| blink::WebServiceWorkerError::ErrorTypeAbort, |
| base::ASCIIToUTF16(kShutdownErrorMessage))); |
| return; |
| } |
| |
| // TODO(ksakamoto): This check can be removed once crbug.com/439697 is fixed. |
| if (provider_host->document_url().is_empty()) { |
| Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError( |
| thread_id, |
| request_id, |
| WebServiceWorkerError::ErrorTypeSecurity, |
| base::ASCIIToUTF16(kNoDocumentURLErrorMessage))); |
| return; |
| } |
| |
| if (!CanGetRegistration(provider_host->document_url(), document_url)) { |
| // 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; |
| } |
| |
| 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); |
| return; |
| } |
| |
| TRACE_EVENT_ASYNC_BEGIN1( |
| "ServiceWorker", |
| "ServiceWorkerDispatcherHost::GetRegistration", |
| request_id, |
| "Document URL", document_url.spec()); |
| |
| GetContext()->storage()->FindRegistrationForDocument( |
| document_url, |
| base::Bind(&ServiceWorkerDispatcherHost::GetRegistrationComplete, |
| this, |
| thread_id, |
| provider_id, |
| request_id)); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnPostMessageToWorker( |
| int handle_id, |
| const base::string16& message, |
| const std::vector<int>& sent_message_port_ids) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnPostMessageToWorker"); |
| if (!GetContext()) |
| 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) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnProviderCreated"); |
| if (!GetContext()) |
| return; |
| if (GetContext()->GetProviderHost(render_process_id_, provider_id)) { |
| BadMessageReceived(); |
| return; |
| } |
| scoped_ptr<ServiceWorkerProviderHost> provider_host( |
| new ServiceWorkerProviderHost( |
| render_process_id_, provider_id, GetContext()->AsWeakPtr(), this)); |
| GetContext()->AddProviderHost(provider_host.Pass()); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnProviderDestroyed(int provider_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnProviderDestroyed"); |
| if (!GetContext()) |
| return; |
| if (!GetContext()->GetProviderHost(render_process_id_, provider_id)) { |
| BadMessageReceived(); |
| return; |
| } |
| GetContext()->RemoveProviderHost(render_process_id_, provider_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnSetHostedVersionId( |
| int provider_id, int64 version_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnSetHostedVersionId"); |
| 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(); |
| } |
| |
| ServiceWorkerRegistrationHandle* |
| ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id, |
| int64 registration_id) { |
| for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator |
| iter(®istration_handles_); |
| !iter.IsAtEnd(); |
| iter.Advance()) { |
| ServiceWorkerRegistrationHandle* handle = iter.GetCurrentValue(); |
| DCHECK(handle); |
| if (handle->provider_id() == provider_id && handle->registration() && |
| handle->registration()->id() == registration_id) { |
| return handle; |
| } |
| } |
| return NULL; |
| } |
| |
| void ServiceWorkerDispatcherHost::GetRegistrationObjectInfoAndVersionAttributes( |
| int provider_id, |
| ServiceWorkerRegistration* registration, |
| ServiceWorkerRegistrationObjectInfo* info, |
| ServiceWorkerVersionAttributes* attrs) { |
| ServiceWorkerRegistrationHandle* handle = |
| GetOrCreateRegistrationHandle(provider_id, registration); |
| *info = handle->GetObjectInfo(); |
| |
| attrs->installing = handle->CreateServiceWorkerHandleAndPass( |
| registration->installing_version()); |
| attrs->waiting = handle->CreateServiceWorkerHandleAndPass( |
| registration->waiting_version()); |
| attrs->active = handle->CreateServiceWorkerHandleAndPass( |
| registration->active_version()); |
| } |
| |
| void ServiceWorkerDispatcherHost::RegistrationComplete( |
| int thread_id, |
| int provider_id, |
| int request_id, |
| ServiceWorkerStatusCode status, |
| int64 registration_id) { |
| if (!GetContext()) |
| return; |
| |
| if (status != SERVICE_WORKER_OK) { |
| SendRegistrationError(thread_id, request_id, status); |
| return; |
| } |
| |
| ServiceWorkerRegistration* registration = |
| GetContext()->GetLiveRegistration(registration_id); |
| DCHECK(registration); |
| |
| ServiceWorkerRegistrationObjectInfo info; |
| ServiceWorkerVersionAttributes attrs; |
| GetRegistrationObjectInfoAndVersionAttributes( |
| provider_id, registration, &info, &attrs); |
| |
| Send(new ServiceWorkerMsg_ServiceWorkerRegistered( |
| thread_id, request_id, info, attrs)); |
| TRACE_EVENT_ASYNC_END1("ServiceWorker", |
| "ServiceWorkerDispatcherHost::RegisterServiceWorker", |
| request_id, |
| "Registration ID", |
| registration_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerReadyForInspection( |
| int embedded_worker_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerReadyForInspection"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerReadyForInspection(render_process_id_, embedded_worker_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded( |
| int embedded_worker_id, |
| int thread_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerScriptLoaded"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerScriptLoaded( |
| render_process_id_, thread_id, embedded_worker_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed( |
| int embedded_worker_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerScriptLoadFailed"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerScriptLoadFailed(render_process_id_, embedded_worker_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated( |
| int embedded_worker_id, |
| bool success) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerScriptEvaluated"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerScriptEvaluated( |
| render_process_id_, embedded_worker_id, success); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerStarted(int embedded_worker_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerStarted"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerStarted(render_process_id_, embedded_worker_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnWorkerStopped(int embedded_worker_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnWorkerStopped"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| registry->OnWorkerStopped(render_process_id_, embedded_worker_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnPausedAfterDownload( |
| int embedded_worker_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnPausedAfterDownload"); |
| if (!GetContext()) |
| return; |
| GetContext()->embedded_worker_registry()->OnPausedAfterDownload( |
| 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) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnReportException"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| 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) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnReportConsoleMessage"); |
| if (!GetContext()) |
| return; |
| EmbeddedWorkerRegistry* registry = GetContext()->embedded_worker_registry(); |
| if (!registry->CanHandle(embedded_worker_id)) |
| return; |
| 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) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnIncrementServiceWorkerRefCount"); |
| ServiceWorkerHandle* handle = handles_.Lookup(handle_id); |
| if (!handle) { |
| BadMessageReceived(); |
| return; |
| } |
| handle->IncrementRefCount(); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount( |
| int handle_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount"); |
| ServiceWorkerHandle* handle = handles_.Lookup(handle_id); |
| if (!handle) { |
| BadMessageReceived(); |
| return; |
| } |
| handle->DecrementRefCount(); |
| if (handle->HasNoRefCount()) |
| handles_.Remove(handle_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount( |
| int registration_handle_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount"); |
| ServiceWorkerRegistrationHandle* handle = |
| registration_handles_.Lookup(registration_handle_id); |
| if (!handle) { |
| BadMessageReceived(); |
| return; |
| } |
| handle->IncrementRefCount(); |
| } |
| |
| void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount( |
| int registration_handle_id) { |
| TRACE_EVENT0("ServiceWorker", |
| "ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount"); |
| ServiceWorkerRegistrationHandle* handle = |
| registration_handles_.Lookup(registration_handle_id); |
| if (!handle) { |
| BadMessageReceived(); |
| return; |
| } |
| handle->DecrementRefCount(); |
| if (handle->HasNoRefCount()) |
| registration_handles_.Remove(registration_handle_id); |
| } |
| |
| void ServiceWorkerDispatcherHost::UnregistrationComplete( |
| int thread_id, |
| int request_id, |
| ServiceWorkerStatusCode status) { |
| if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) { |
| SendUnregistrationError(thread_id, request_id, status); |
| return; |
| } |
| const bool is_success = (status == SERVICE_WORKER_OK); |
| Send(new ServiceWorkerMsg_ServiceWorkerUnregistered(thread_id, |
| request_id, |
| is_success)); |
| TRACE_EVENT_ASYNC_END1( |
| "ServiceWorker", |
| "ServiceWorkerDispatcherHost::UnregisterServiceWorker", |
| request_id, |
| "Status", status); |
| } |
| |
| void ServiceWorkerDispatcherHost::GetRegistrationComplete( |
| int thread_id, |
| int provider_id, |
| int request_id, |
| ServiceWorkerStatusCode status, |
| const scoped_refptr<ServiceWorkerRegistration>& registration) { |
| TRACE_EVENT_ASYNC_END1("ServiceWorker", |
| "ServiceWorkerDispatcherHost::GetRegistration", |
| request_id, |
| "Registration ID", |
| registration.get() ? registration->id() |
| : kInvalidServiceWorkerRegistrationId); |
| |
| if (!GetContext()) |
| return; |
| |
| if (status != SERVICE_WORKER_OK && status != SERVICE_WORKER_ERROR_NOT_FOUND) { |
| SendGetRegistrationError(thread_id, request_id, status); |
| return; |
| } |
| |
| ServiceWorkerRegistrationObjectInfo info; |
| ServiceWorkerVersionAttributes attrs; |
| if (status == SERVICE_WORKER_OK) { |
| DCHECK(registration.get()); |
| if (!registration->is_uninstalling()) { |
| GetRegistrationObjectInfoAndVersionAttributes( |
| provider_id, registration.get(), &info, &attrs); |
| } |
| } |
| |
| Send(new ServiceWorkerMsg_DidGetRegistration( |
| thread_id, request_id, info, attrs)); |
| } |
| |
| void ServiceWorkerDispatcherHost::SendRegistrationError( |
| int thread_id, |
| int request_id, |
| ServiceWorkerStatusCode status) { |
| base::string16 error_message; |
| blink::WebServiceWorkerError::ErrorType error_type; |
| GetServiceWorkerRegistrationStatusResponse( |
| status, &error_type, &error_message); |
| Send(new ServiceWorkerMsg_ServiceWorkerRegistrationError( |
| thread_id, request_id, error_type, error_message)); |
| } |
| |
| void ServiceWorkerDispatcherHost::SendUnregistrationError( |
| int thread_id, |
| int request_id, |
| ServiceWorkerStatusCode status) { |
| base::string16 error_message; |
| blink::WebServiceWorkerError::ErrorType error_type; |
| GetServiceWorkerRegistrationStatusResponse( |
| status, &error_type, &error_message); |
| Send(new ServiceWorkerMsg_ServiceWorkerUnregistrationError( |
| thread_id, request_id, error_type, error_message)); |
| } |
| |
| void ServiceWorkerDispatcherHost::SendGetRegistrationError( |
| int thread_id, |
| int request_id, |
| ServiceWorkerStatusCode status) { |
| base::string16 error_message; |
| blink::WebServiceWorkerError::ErrorType error_type; |
| GetServiceWorkerRegistrationStatusResponse( |
| status, &error_type, &error_message); |
| Send(new ServiceWorkerMsg_ServiceWorkerGetRegistrationError( |
| thread_id, request_id, error_type, error_message)); |
| } |
| |
| ServiceWorkerContextCore* ServiceWorkerDispatcherHost::GetContext() { |
| if (!context_wrapper_.get()) |
| return nullptr; |
| return context_wrapper_->context(); |
| } |
| |
| } // namespace content |