Commit 61752d1c authored by nhiroki@chromium.org's avatar nhiroki@chromium.org

ServiceWorker: Implement updatefound event and version attributes (Chromium)

Changes in the renderer side:
* Implementing WebServiceWorkerRegistrationImpl in order to handle 'updatefound'
event and version attributes.
* Adding ServiceWorkerRegistrationHandleReference which is responsible for
incrementing/decrementing the refcount of ServiceWorkerRegistration in the
browser-side (in the same way as ServiceWorkerHandleRefernce).

Changes in the browser side:
* Adding ServiceWorkerRegistrationHandle which manages the refcount of
ServiceWorkerRegistration and listens to its version change events.
This is managed by ServiceWorkerDispatcherHost.

Changes in the wiring part:
* Adding new IPC messages for refcount operations.
* Changing Registered and SetVersionAttributes messages to carry the
registration handle id.


BUG=384119, 396400
TEST=content_unittests --gtest_filter=ServiceWorker*
TEST=run_webkit_tests.py --debug http/tests/serviceworker
TEST=https://codereview.chromium.org/466723002/ (layout tests for ServiceWorkerRegistration)
NOTRY=true

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

Cr-Commit-Position: refs/heads/master@{#289415}
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@289415 0039d316-1c4b-4281-b951-d872f2087c98
parent cf1a3fbd
......@@ -102,6 +102,7 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
embedded_worker_registry_(EmbeddedWorkerRegistry::Create(AsWeakPtr())),
job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
next_handle_id_(0),
next_registration_handle_id_(0),
observer_list_(observer_list) {
}
......@@ -120,6 +121,7 @@ ServiceWorkerContextCore::ServiceWorkerContextCore(
old_context->embedded_worker_registry())),
job_coordinator_(new ServiceWorkerJobCoordinator(AsWeakPtr())),
next_handle_id_(0),
next_registration_handle_id_(0),
observer_list_(old_context->observer_list_) {
}
......@@ -317,6 +319,10 @@ int ServiceWorkerContextCore::GetNewServiceWorkerHandleId() {
return next_handle_id_++;
}
int ServiceWorkerContextCore::GetNewRegistrationHandleId() {
return next_registration_handle_id_++;
}
void ServiceWorkerContextCore::ScheduleDeleteAndStartOver() const {
storage_->Disable();
base::MessageLoop::current()->PostTask(
......
......@@ -168,8 +168,9 @@ class CONTENT_EXPORT ServiceWorkerContextCore
std::vector<ServiceWorkerRegistrationInfo> GetAllLiveRegistrationInfo();
std::vector<ServiceWorkerVersionInfo> GetAllLiveVersionInfo();
// Returns new context-local unique ID for ServiceWorkerHandle.
// Returns new context-local unique ID.
int GetNewServiceWorkerHandleId();
int GetNewRegistrationHandleId();
void ScheduleDeleteAndStartOver() const;
......@@ -216,6 +217,7 @@ class CONTENT_EXPORT ServiceWorkerContextCore
std::map<int64, ServiceWorkerRegistration*> live_registrations_;
std::map<int64, ServiceWorkerVersion*> live_versions_;
int next_handle_id_;
int next_registration_handle_id_;
scoped_refptr<ObserverListThreadSafe<ServiceWorkerContextObserver> >
observer_list_;
......
......@@ -13,6 +13,7 @@
#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"
......@@ -135,6 +136,10 @@ bool ServiceWorkerDispatcherHost::OnMessageReceived(
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()
......@@ -165,6 +170,12 @@ void ServiceWorkerDispatcherHost::RegisterServiceWorkerHandle(
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,
......@@ -331,6 +342,23 @@ ServiceWorkerHandle* ServiceWorkerDispatcherHost::FindHandle(int provider_id,
return NULL;
}
ServiceWorkerRegistrationHandle*
ServiceWorkerDispatcherHost::FindRegistrationHandle(int provider_id,
int64 registration_id) {
for (IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer>::iterator
iter(&registration_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::RegistrationComplete(
int thread_id,
int provider_id,
......@@ -350,6 +378,7 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
DCHECK(version);
DCHECK_EQ(registration_id, version->registration_id());
ServiceWorkerObjectInfo info;
ServiceWorkerHandle* handle = FindHandle(provider_id, version_id);
if (handle) {
DCHECK_EQ(thread_id, handle->thread_id());
......@@ -361,8 +390,27 @@ void ServiceWorkerDispatcherHost::RegistrationComplete(
info = new_handle->GetObjectInfo();
RegisterServiceWorkerHandle(new_handle.Pass());
}
ServiceWorkerRegistration* registration =
GetContext()->GetLiveRegistration(registration_id);
DCHECK(registration);
ServiceWorkerRegistrationHandle* registration_handle =
FindRegistrationHandle(provider_id, registration_id);
int registration_handle_id = kInvalidServiceWorkerRegistrationHandleId;
if (registration_handle) {
registration_handle->IncrementRefCount();
registration_handle_id = registration_handle->handle_id();
} else {
scoped_ptr<ServiceWorkerRegistrationHandle> new_handle(
new ServiceWorkerRegistrationHandle(
GetContext()->AsWeakPtr(), this, provider_id, registration));
registration_handle_id = new_handle->handle_id();
RegisterServiceWorkerRegistrationHandle(new_handle.Pass());
}
Send(new ServiceWorkerMsg_ServiceWorkerRegistered(
thread_id, request_id, info));
thread_id, request_id, registration_handle_id, info));
}
void ServiceWorkerDispatcherHost::OnWorkerScriptLoaded(int embedded_worker_id) {
......@@ -467,6 +515,30 @@ void ServiceWorkerDispatcherHost::OnDecrementServiceWorkerRefCount(
handles_.Remove(handle_id);
}
void ServiceWorkerDispatcherHost::OnIncrementRegistrationRefCount(
int registration_handle_id) {
ServiceWorkerRegistrationHandle* handle =
registration_handles_.Lookup(registration_handle_id);
if (!handle) {
BadMessageReceived();
return;
}
handle->IncrementRefCount();
}
void ServiceWorkerDispatcherHost::OnDecrementRegistrationRefCount(
int registration_handle_id) {
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,
......
......@@ -24,6 +24,7 @@ class ServiceWorkerContextWrapper;
class ServiceWorkerHandle;
class ServiceWorkerProviderHost;
class ServiceWorkerRegistration;
class ServiceWorkerRegistrationHandle;
class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
public:
......@@ -47,6 +48,8 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
virtual bool Send(IPC::Message* message) OVERRIDE;
void RegisterServiceWorkerHandle(scoped_ptr<ServiceWorkerHandle> handle);
void RegisterServiceWorkerRegistrationHandle(
scoped_ptr<ServiceWorkerRegistrationHandle> handle);
MessagePortMessageFilter* message_port_message_filter() {
return message_port_message_filter_;
......@@ -92,12 +95,19 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
const std::vector<int>& sent_message_port_ids);
void OnIncrementServiceWorkerRefCount(int handle_id);
void OnDecrementServiceWorkerRefCount(int handle_id);
void OnIncrementRegistrationRefCount(int registration_handle_id);
void OnDecrementRegistrationRefCount(int registration_handle_id);
void OnPostMessageToWorker(int handle_id,
const base::string16& message,
const std::vector<int>& sent_message_port_ids);
void OnServiceWorkerObjectDestroyed(int handle_id);
ServiceWorkerHandle* FindHandle(int provider_id, int64 version_id);
ServiceWorkerHandle* FindHandle(
int provider_id,
int64 version_id);
ServiceWorkerRegistrationHandle* FindRegistrationHandle(
int provider_id,
int64 registration_id);
// Callbacks from ServiceWorkerContextCore
void RegistrationComplete(int thread_id,
......@@ -122,6 +132,7 @@ class CONTENT_EXPORT ServiceWorkerDispatcherHost : public BrowserMessageFilter {
scoped_refptr<ServiceWorkerContextWrapper> context_wrapper_;
IDMap<ServiceWorkerHandle, IDMapOwnPointer> handles_;
IDMap<ServiceWorkerRegistrationHandle, IDMapOwnPointer> registration_handles_;
bool channel_ready_; // True after BrowserMessageFilter::sender_ != NULL.
ScopedVector<IPC::Message> pending_messages_;
......
......@@ -11,6 +11,7 @@
#include "content/browser/service_worker/service_worker_controllee_request_handler.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/browser/service_worker/service_worker_registration_handle.h"
#include "content/browser/service_worker/service_worker_utils.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_messages.h"
......@@ -99,7 +100,11 @@ void ServiceWorkerProviderHost::SetVersionAttributes(
attributes.active = CreateHandleAndPass(active_version);
dispatcher_host_->Send(new ServiceWorkerMsg_SetVersionAttributes(
kDocumentMainThreadId, provider_id(), mask.changed(), attributes));
kDocumentMainThreadId,
provider_id(),
kInvalidServiceWorkerRegistrationHandleId,
mask.changed(),
attributes));
}
void ServiceWorkerProviderHost::SetVersionAttributesInternal(
......
// Copyright 2014 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_registration_handle.h"
#include "content/browser/service_worker/service_worker_context_core.h"
#include "content/browser/service_worker/service_worker_dispatcher_host.h"
#include "content/browser/service_worker/service_worker_handle.h"
#include "content/common/service_worker/service_worker_messages.h"
namespace content {
static const int kDocumentMainThreadId = 0;
ServiceWorkerRegistrationHandle::ServiceWorkerRegistrationHandle(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerDispatcherHost* dispatcher_host,
int provider_id,
ServiceWorkerRegistration* registration)
: context_(context),
dispatcher_host_(dispatcher_host),
provider_id_(provider_id),
handle_id_(context ? context->GetNewRegistrationHandleId()
: kInvalidServiceWorkerRegistrationHandleId),
ref_count_(1),
registration_(registration) {
DCHECK(registration_);
SetVersionAttributes(registration->installing_version(),
registration->waiting_version(),
registration->active_version());
registration_->AddListener(this);
}
ServiceWorkerRegistrationHandle::~ServiceWorkerRegistrationHandle() {
registration_->RemoveListener(this);
}
void ServiceWorkerRegistrationHandle::IncrementRefCount() {
DCHECK_GT(ref_count_, 0);
++ref_count_;
}
void ServiceWorkerRegistrationHandle::DecrementRefCount() {
DCHECK_GT(ref_count_, 0);
--ref_count_;
}
void ServiceWorkerRegistrationHandle::OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
ChangedVersionAttributesMask changed_mask,
const ServiceWorkerRegistrationInfo& info) {
DCHECK_EQ(registration->id(), registration_->id());
SetVersionAttributes(registration->installing_version(),
registration->waiting_version(),
registration->active_version());
}
void ServiceWorkerRegistrationHandle::OnRegistrationFailed(
ServiceWorkerRegistration* registration) {
DCHECK_EQ(registration->id(), registration_->id());
ClearVersionAttributes();
registration_->RemoveListener(this);
registration_ = NULL;
}
void ServiceWorkerRegistrationHandle::SetVersionAttributes(
ServiceWorkerVersion* installing_version,
ServiceWorkerVersion* waiting_version,
ServiceWorkerVersion* active_version) {
ChangedVersionAttributesMask mask;
if (installing_version != installing_version_) {
installing_version_ = installing_version;
mask.add(ChangedVersionAttributesMask::INSTALLING_VERSION);
}
if (waiting_version != waiting_version_) {
waiting_version_ = waiting_version;
mask.add(ChangedVersionAttributesMask::WAITING_VERSION);
}
if (active_version != active_version_) {
active_version_ = active_version;
mask.add(ChangedVersionAttributesMask::ACTIVE_VERSION);
}
if (!dispatcher_host_)
return; // Could be NULL in some tests.
if (!mask.changed())
return;
ServiceWorkerVersionAttributes attributes;
if (mask.installing_changed()) {
attributes.installing =
CreateServiceWorkerHandleAndPass(installing_version);
}
if (mask.waiting_changed()) {
attributes.waiting =
CreateServiceWorkerHandleAndPass(waiting_version);
}
if (mask.active_changed()) {
attributes.active =
CreateServiceWorkerHandleAndPass(active_version);
}
dispatcher_host_->Send(new ServiceWorkerMsg_SetVersionAttributes(
kDocumentMainThreadId, provider_id_, handle_id_,
mask.changed(), attributes));
}
void ServiceWorkerRegistrationHandle::ClearVersionAttributes() {
SetVersionAttributes(NULL, NULL, NULL);
}
ServiceWorkerObjectInfo
ServiceWorkerRegistrationHandle::CreateServiceWorkerHandleAndPass(
ServiceWorkerVersion* version) {
ServiceWorkerObjectInfo info;
if (context_ && version) {
scoped_ptr<ServiceWorkerHandle> handle =
ServiceWorkerHandle::Create(context_,
dispatcher_host_,
kDocumentMainThreadId,
provider_id_,
version);
info = handle->GetObjectInfo();
dispatcher_host_->RegisterServiceWorkerHandle(handle.Pass());
}
return info;
}
} // namespace content
// Copyright 2014 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.
#ifndef CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
#define CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/memory/weak_ptr.h"
#include "content/browser/service_worker/service_worker_registration.h"
#include "content/browser/service_worker/service_worker_version.h"
#include "content/common/service_worker/service_worker_types.h"
namespace content {
class ServiceWorkerContextCore;
class ServiceWorkerDispatcherHost;
class ServiceWorkerVersion;
// Roughly Corresponds to one ServiceWorkerRegistration object in the renderer
// process (WebServiceWorkerRegistrationImpl).
// Has references to the corresponding ServiceWorkerRegistration and
// ServiceWorkerVersions (therefore they're guaranteed to be alive while this
// handle is around).
class ServiceWorkerRegistrationHandle
: public ServiceWorkerRegistration::Listener {
public:
ServiceWorkerRegistrationHandle(
base::WeakPtr<ServiceWorkerContextCore> context,
ServiceWorkerDispatcherHost* dispatcher_host,
int provider_id,
ServiceWorkerRegistration* registration);
virtual ~ServiceWorkerRegistrationHandle();
bool HasNoRefCount() const { return ref_count_ <= 0; }
void IncrementRefCount();
void DecrementRefCount();
int provider_id() const { return provider_id_; }
int handle_id() const { return handle_id_; }
ServiceWorkerRegistration* registration() { return registration_.get(); }
private:
// ServiceWorkerRegistration::Listener overrides.
virtual void OnVersionAttributesChanged(
ServiceWorkerRegistration* registration,
ChangedVersionAttributesMask changed_mask,
const ServiceWorkerRegistrationInfo& info) OVERRIDE;
virtual void OnRegistrationFailed(
ServiceWorkerRegistration* registration) OVERRIDE;
// Sets the corresponding version field to the given version or if the given
// version is NULL, clears the field.
void SetVersionAttributes(
ServiceWorkerVersion* installing_version,
ServiceWorkerVersion* waiting_version,
ServiceWorkerVersion* active_version);
// Clears all version fields.
void ClearVersionAttributes();
ServiceWorkerObjectInfo CreateServiceWorkerHandleAndPass(
ServiceWorkerVersion* version);
base::WeakPtr<ServiceWorkerContextCore> context_;
ServiceWorkerDispatcherHost* dispatcher_host_;
const int provider_id_;
const int handle_id_;
int ref_count_; // Created with 1.
scoped_refptr<ServiceWorkerRegistration> registration_;
scoped_refptr<ServiceWorkerVersion> installing_version_;
scoped_refptr<ServiceWorkerVersion> waiting_version_;
scoped_refptr<ServiceWorkerVersion> active_version_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandle);
};
} // namespace content
#endif // CONTENT_BROWSER_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_H_
......@@ -10,6 +10,7 @@
#include "content/child/child_thread.h"
#include "content/child/service_worker/service_worker_handle_reference.h"
#include "content/child/service_worker/service_worker_provider_context.h"
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/service_worker/web_service_worker_impl.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/thread_safe_sender.h"
......@@ -202,9 +203,43 @@ WebServiceWorkerImpl* ServiceWorkerDispatcher::GetServiceWorker(
return new WebServiceWorkerImpl(handle_ref.Pass(), thread_safe_sender_);
}
WebServiceWorkerRegistrationImpl*
ServiceWorkerDispatcher::GetServiceWorkerRegistration(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
bool adopt_handle) {
if (registration_handle_id == kInvalidServiceWorkerRegistrationHandleId)
return NULL;
RegistrationObjectMap::iterator existing_registration =
registrations_.find(registration_handle_id);
if (existing_registration != registrations_.end()) {
if (adopt_handle) {
// We are instructed to adopt a handle but we already have one, so
// adopt and destroy a handle ref.
ServiceWorkerRegistrationHandleReference::Adopt(
registration_handle_id, info, thread_safe_sender_);
}
return existing_registration->second;
}
scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref =
adopt_handle
? ServiceWorkerRegistrationHandleReference::Adopt(
registration_handle_id, info, thread_safe_sender_)
: ServiceWorkerRegistrationHandleReference::Create(
registration_handle_id, info, thread_safe_sender_);
// WebServiceWorkerRegistrationImpl constructor calls
// AddServiceWorkerRegistration.
return new WebServiceWorkerRegistrationImpl(handle_ref.Pass());
}
void ServiceWorkerDispatcher::OnRegistered(
int thread_id,
int request_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
WebServiceWorkerRegistrationCallbacks* callbacks =
pending_callbacks_.Lookup(request_id);
......@@ -214,8 +249,14 @@ void ServiceWorkerDispatcher::OnRegistered(
#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
callbacks->onSuccess(GetServiceWorker(info, true));
// We should adopt and destroy an unused handle ref.
ServiceWorkerRegistrationHandleReference::Adopt(
registration_handle_id, info, thread_safe_sender_);
#else
callbacks->onSuccess(new WebServiceWorkerRegistrationImpl(info));
callbacks->onSuccess(GetServiceWorkerRegistration(
registration_handle_id, info, true));
// We should adopt and destroy an unused handle ref.
ServiceWorkerHandleReference::Adopt(info, thread_safe_sender_);
#endif
pending_callbacks_.Remove(request_id);
}
......@@ -266,19 +307,30 @@ void ServiceWorkerDispatcher::OnServiceWorkerStateChanged(
void ServiceWorkerDispatcher::OnSetVersionAttributes(
int thread_id,
int provider_id,
int registration_handle_id,
int changed_mask,
const ServiceWorkerVersionAttributes& attributes) {
ChangedVersionAttributesMask mask(changed_mask);
if (mask.installing_changed())
SetInstallingServiceWorker(provider_id, attributes.installing);
if (mask.waiting_changed())
SetWaitingServiceWorker(provider_id, attributes.waiting);
if (mask.active_changed())
SetActiveServiceWorker(provider_id, attributes.active);
if (mask.installing_changed()) {
SetInstallingServiceWorker(provider_id,
registration_handle_id,
attributes.installing);
}
if (mask.waiting_changed()) {
SetWaitingServiceWorker(provider_id,
registration_handle_id,
attributes.waiting);
}
if (mask.active_changed()) {
SetActiveServiceWorker(provider_id,
registration_handle_id,
attributes.active);
}
}
void ServiceWorkerDispatcher::SetInstallingServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
if (provider != provider_contexts_.end()) {
......@@ -296,15 +348,26 @@ void ServiceWorkerDispatcher::SetInstallingServiceWorker(
worker_to_provider_[info.handle_id] = provider->second;
}
#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
ScriptClientMap::iterator found = script_clients_.find(provider_id);
if (found != script_clients_.end()) {
// Populate the .installing field with the new worker object.
found->second->setInstalling(GetServiceWorker(info, false));
}
#else
RegistrationObjectMap::iterator found =
registrations_.find(registration_handle_id);
if (found != registrations_.end()) {
found->second->setInstalling(GetServiceWorker(info, false));
if (info.handle_id != kInvalidServiceWorkerHandleId)
found->second->OnUpdateFound();
}
#endif
}
void ServiceWorkerDispatcher::SetWaitingServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
if (provider != provider_contexts_.end()) {
......@@ -322,15 +385,23 @@ void ServiceWorkerDispatcher::SetWaitingServiceWorker(
worker_to_provider_[info.handle_id] = provider->second;
}
#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
ScriptClientMap::iterator found = script_clients_.find(provider_id);
if (found != script_clients_.end()) {
// Populate the .waiting field with the new worker object.
found->second->setWaiting(GetServiceWorker(info, false));
}
#else
RegistrationObjectMap::iterator found =
registrations_.find(registration_handle_id);
if (found != registrations_.end())
found->second->setWaiting(GetServiceWorker(info, false));
#endif
}
void ServiceWorkerDispatcher::SetActiveServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
ProviderContextMap::iterator provider = provider_contexts_.find(provider_id);
if (provider != provider_contexts_.end()) {
......@@ -348,11 +419,18 @@ void ServiceWorkerDispatcher::SetActiveServiceWorker(
worker_to_provider_[info.handle_id] = provider->second;
}
#ifdef DISABLE_SERVICE_WORKER_REGISTRATION
ScriptClientMap::iterator found = script_clients_.find(provider_id);
if (found != script_clients_.end()) {
// Populate the .active field with the new worker object.
found->second->setActive(GetServiceWorker(info, false));
}
#else
RegistrationObjectMap::iterator found =
registrations_.find(registration_handle_id);
if (found != registrations_.end())
found->second->setActive(GetServiceWorker(info, false));
#endif
}
void ServiceWorkerDispatcher::OnSetControllerServiceWorker(
......@@ -413,4 +491,17 @@ void ServiceWorkerDispatcher::RemoveServiceWorker(int handle_id) {
service_workers_.erase(handle_id);
}
void ServiceWorkerDispatcher::AddServiceWorkerRegistration(
int registration_handle_id,
WebServiceWorkerRegistrationImpl* registration) {
DCHECK(!ContainsKey(registrations_, registration_handle_id));
registrations_[registration_handle_id] = registration;
}
void ServiceWorkerDispatcher::RemoveServiceWorkerRegistration(
int registration_handle_id) {
DCHECK(ContainsKey(registrations_, registration_handle_id));
registrations_.erase(registration_handle_id);
}
} // namespace content
......@@ -32,6 +32,7 @@ class ServiceWorkerMessageFilter;
class ServiceWorkerProviderContext;
class ThreadSafeSender;
class WebServiceWorkerImpl;
class WebServiceWorkerRegistrationImpl;
struct ServiceWorkerObjectInfo;
struct ServiceWorkerVersionAttributes;
......@@ -87,8 +88,19 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
// WebServiceWorkerImpl, in which case ownership is transferred to
// the caller who must bounce it to a method that will associate it
// with a WebCore::ServiceWorker.
WebServiceWorkerImpl* GetServiceWorker(const ServiceWorkerObjectInfo&,
bool adopt_handle);
WebServiceWorkerImpl* GetServiceWorker(
const ServiceWorkerObjectInfo& info,
bool adopt_handle);
// If an existing WebServiceWorkerRegistrationImpl exists for the
// registration, it is returned; otherwise a WebServiceWorkerRegistrationImpl
// is created and its ownership is transferred to the caller. If
// |adopt_handle| is true, a ServiceWorkerRegistrationHandleReference will be
// adopted for the specified registration.
WebServiceWorkerRegistrationImpl* GetServiceWorkerRegistration(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
bool adopt_handle);
// |thread_safe_sender| needs to be passed in because if the call leads to
// construction it will be needed.
......@@ -106,14 +118,18 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
typedef std::map<int, ServiceWorkerProviderContext*> ProviderContextMap;
typedef std::map<int, WebServiceWorkerImpl*> WorkerObjectMap;
typedef std::map<int, ServiceWorkerProviderContext*> WorkerToProviderMap;
typedef std::map<int, WebServiceWorkerRegistrationImpl*>
RegistrationObjectMap;
friend class WebServiceWorkerImpl;
friend class WebServiceWorkerRegistrationImpl;
// WorkerTaskRunner::Observer implementation.
virtual void OnWorkerRunLoopStopped() OVERRIDE;
void OnRegistered(int thread_id,
int request_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info);
void OnUnregistered(int thread_id,
int request_id);
......@@ -126,6 +142,7 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
blink::WebServiceWorkerState state);
void OnSetVersionAttributes(int thread_id,
int provider_id,
int registration_handle_id,
int changed_mask,
const ServiceWorkerVersionAttributes& attributes);
void OnSetControllerServiceWorker(int thread_id,
......@@ -139,22 +156,33 @@ class ServiceWorkerDispatcher : public WorkerTaskRunner::Observer {
void SetInstallingServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info);
void SetWaitingServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info);
void SetActiveServiceWorker(
int provider_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info);
// Keeps map from handle_id to ServiceWorker object.
void AddServiceWorker(int handle_id, WebServiceWorkerImpl* worker);
void RemoveServiceWorker(int handle_id);
// Keeps map from registration_handle_id to ServiceWorkerRegistration object.
void AddServiceWorkerRegistration(
int registration_handle_id,
WebServiceWorkerRegistrationImpl* registration);
void RemoveServiceWorkerRegistration(
int registration_handle_id);
CallbackMap pending_callbacks_;
ScriptClientMap script_clients_;
ProviderContextMap provider_contexts_;
WorkerObjectMap service_workers_;
RegistrationObjectMap registrations_;
// A map for ServiceWorkers that are associated to a particular document
// (e.g. as .current).
......
......@@ -19,7 +19,7 @@ namespace {
// Sends a ServiceWorkerObjectDestroyed message to the browser so it can delete
// the ServiceWorker handle.
void SendServiceWorkerObjectDestroyed(
scoped_refptr<ThreadSafeSender> sender,
ThreadSafeSender* sender,
int handle_id) {
if (handle_id == kInvalidServiceWorkerHandleId)
return;
......@@ -27,6 +27,15 @@ void SendServiceWorkerObjectDestroyed(
new ServiceWorkerHostMsg_DecrementServiceWorkerRefCount(handle_id));
}
void SendRegistrationObjectDestroyed(
ThreadSafeSender* sender,
int handle_id) {
if (handle_id == kInvalidServiceWorkerRegistrationHandleId)
return;
sender->Send(
new ServiceWorkerHostMsg_DecrementRegistrationRefCount(handle_id));
}
} // namespace
ServiceWorkerMessageFilter::ServiceWorkerMessageFilter(ThreadSafeSender* sender)
......@@ -72,13 +81,16 @@ void ServiceWorkerMessageFilter::OnStaleMessageReceived(
void ServiceWorkerMessageFilter::OnStaleRegistered(
int thread_id,
int request_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info) {
SendServiceWorkerObjectDestroyed(thread_safe_sender_, info.handle_id);
SendRegistrationObjectDestroyed(thread_safe_sender_, registration_handle_id);
}
void ServiceWorkerMessageFilter::OnStaleSetVersionAttributes(
int thread_id,
int provider_id,
int registration_handle_id,
int changed_mask,
const ServiceWorkerVersionAttributes& attributes) {
SendServiceWorkerObjectDestroyed(thread_safe_sender_,
......@@ -87,6 +99,7 @@ void ServiceWorkerMessageFilter::OnStaleSetVersionAttributes(
attributes.waiting.handle_id);
SendServiceWorkerObjectDestroyed(thread_safe_sender_,
attributes.active.handle_id);
SendRegistrationObjectDestroyed(thread_safe_sender_, registration_handle_id);
}
void ServiceWorkerMessageFilter::OnStaleSetControllerServiceWorker(
......
......@@ -37,10 +37,12 @@ class CONTENT_EXPORT ServiceWorkerMessageFilter
void OnStaleRegistered(
int thread_id,
int request_id,
int registration_handle_id,
const ServiceWorkerObjectInfo& info);
void OnStaleSetVersionAttributes(
int thread_id,
int provider_id,
int registration_handle_id,
int changed_mask,
const ServiceWorkerVersionAttributes& attributes);
void OnStaleSetControllerServiceWorker(
......
// Copyright 2014 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/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/child/thread_safe_sender.h"
#include "content/common/service_worker/service_worker_messages.h"
#include "content/common/service_worker/service_worker_types.h"
namespace content {
scoped_ptr<ServiceWorkerRegistrationHandleReference>
ServiceWorkerRegistrationHandleReference::Create(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender) {
return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
registration_handle_id, info, sender, true));
}
scoped_ptr<ServiceWorkerRegistrationHandleReference>
ServiceWorkerRegistrationHandleReference::Adopt(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender) {
return make_scoped_ptr(new ServiceWorkerRegistrationHandleReference(
registration_handle_id, info, sender, false));
}
ServiceWorkerRegistrationHandleReference::
ServiceWorkerRegistrationHandleReference(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender,
bool increment_ref_in_ctor)
: handle_id_(registration_handle_id),
scope_(info.scope),
sender_(sender) {
DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId, handle_id_);
DCHECK(sender_);
if (increment_ref_in_ctor)
return;
sender_->Send(
new ServiceWorkerHostMsg_IncrementRegistrationRefCount(handle_id_));
}
ServiceWorkerRegistrationHandleReference::
~ServiceWorkerRegistrationHandleReference() {
sender_->Send(
new ServiceWorkerHostMsg_DecrementRegistrationRefCount(handle_id_));
}
} // namespace content
// Copyright 2014 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.
#ifndef CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
#define CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "url/gurl.h"
namespace content {
class ThreadSafeSender;
struct ServiceWorkerObjectInfo;
class ServiceWorkerRegistrationHandleReference {
public:
// Creates a new ServiceWorkerRegistrationHandleReference and increments
// ref-count.
static scoped_ptr<ServiceWorkerRegistrationHandleReference> Create(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender);
// Creates a new ServiceWorkerRegistrationHandleReference by adopting a
// ref-count.
static scoped_ptr<ServiceWorkerRegistrationHandleReference> Adopt(
int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender);
~ServiceWorkerRegistrationHandleReference();
int handle_id() const { return handle_id_; }
GURL scope() const { return scope_; }
private:
ServiceWorkerRegistrationHandleReference(int registration_handle_id,
const ServiceWorkerObjectInfo& info,
ThreadSafeSender* sender,
bool increment_ref_in_ctor);
const int handle_id_;
const GURL scope_;
scoped_refptr<ThreadSafeSender> sender_;
DISALLOW_COPY_AND_ASSIGN(ServiceWorkerRegistrationHandleReference);
};
} // namespace content
#endif // CONTENT_CHILD_SERVICE_WORKER_SERVICE_WORKER_REGISTRATION_HANDLE_REFERENCE_H_
......@@ -4,20 +4,63 @@
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/service_worker/service_worker_dispatcher.h"
#include "content/child/service_worker/service_worker_registration_handle_reference.h"
#include "content/common/service_worker/service_worker_types.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerRegistrationProxy.h"
namespace content {
WebServiceWorkerRegistrationImpl::WebServiceWorkerRegistrationImpl(
const ServiceWorkerObjectInfo& info)
: scope_(info.scope) {
scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref)
: handle_ref_(handle_ref.Pass()),
proxy_(NULL) {
DCHECK(handle_ref_);
DCHECK_NE(kInvalidServiceWorkerRegistrationHandleId,
handle_ref_->handle_id());
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
DCHECK(dispatcher);
dispatcher->AddServiceWorkerRegistration(handle_ref_->handle_id(), this);
}
WebServiceWorkerRegistrationImpl::~WebServiceWorkerRegistrationImpl() {
ServiceWorkerDispatcher* dispatcher =
ServiceWorkerDispatcher::GetThreadSpecificInstance();
if (dispatcher)
dispatcher->RemoveServiceWorkerRegistration(handle_ref_->handle_id());
}
void WebServiceWorkerRegistrationImpl::OnUpdateFound() {
DCHECK(proxy_);
proxy_->dispatchUpdateFoundEvent();
}
void WebServiceWorkerRegistrationImpl::setProxy(
blink::WebServiceWorkerRegistrationProxy* proxy) {
proxy_ = proxy;
}
void WebServiceWorkerRegistrationImpl::setInstalling(
blink::WebServiceWorker* service_worker) {
DCHECK(proxy_);
proxy_->setInstalling(service_worker);
}
void WebServiceWorkerRegistrationImpl::setWaiting(
blink::WebServiceWorker* service_worker) {
DCHECK(proxy_);
proxy_->setWaiting(service_worker);
}
void WebServiceWorkerRegistrationImpl::setActive(
blink::WebServiceWorker* service_worker) {
DCHECK(proxy_);
proxy_->setActive(service_worker);
}
blink::WebURL WebServiceWorkerRegistrationImpl::scope() const {
return scope_;
return handle_ref_->scope();
}
} // namespace content
......@@ -8,21 +8,36 @@
#include "base/compiler_specific.h"
#include "third_party/WebKit/public/platform/WebServiceWorkerRegistration.h"
namespace blink {
class WebServiceWorker;
class WebServiceWorkerRegistrationProxy;
}
namespace content {
class ServiceWorkerRegistrationHandleReference;
class ThreadSafeSender;
struct ServiceWorkerObjectInfo;
class WebServiceWorkerRegistrationImpl
: NON_EXPORTED_BASE(public blink::WebServiceWorkerRegistration) {
public:
explicit WebServiceWorkerRegistrationImpl(
const ServiceWorkerObjectInfo& info);
scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref);
virtual ~WebServiceWorkerRegistrationImpl();
void OnUpdateFound();
virtual void setProxy(blink::WebServiceWorkerRegistrationProxy* proxy);
virtual void setInstalling(blink::WebServiceWorker* service_worker);
virtual void setWaiting(blink::WebServiceWorker* service_worker);
virtual void setActive(blink::WebServiceWorker* service_worker);
virtual blink::WebURL scope() const;
private:
const GURL scope_;
scoped_ptr<ServiceWorkerRegistrationHandleReference> handle_ref_;
blink::WebServiceWorkerRegistrationProxy* proxy_;
DISALLOW_COPY_AND_ASSIGN(WebServiceWorkerRegistrationImpl);
};
......
......@@ -102,8 +102,16 @@ IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_ProviderDestroyed,
// counting in the browser side. The ServiceWorker object is created
// with ref-count==1 initially.
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_IncrementServiceWorkerRefCount,
int /* handle_id */)
int /* registration_handle_id */)
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementServiceWorkerRefCount,
int /* registration_handle_id */)
// Increments and decrements the ServiceWorkerRegistration object's reference
// counting in the browser side. The registration object is created with
// ref-count==1 initially.
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_IncrementRegistrationRefCount,
int /* handle_id */)
IPC_MESSAGE_CONTROL1(ServiceWorkerHostMsg_DecrementRegistrationRefCount,
int /* handle_id */)
// Informs the browser that |provider_id| is associated
......@@ -170,9 +178,10 @@ IPC_MESSAGE_ROUTED1(ServiceWorkerHostMsg_CacheStorageKeys,
// on the correct thread.
// Response to ServiceWorkerMsg_RegisterServiceWorker.
IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerRegistered,
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_ServiceWorkerRegistered,
int /* thread_id */,
int /* request_id */,
int /* registration_handle_id */,
content::ServiceWorkerObjectInfo)
// Response to ServiceWorkerMsg_UnregisterServiceWorker.
......@@ -195,9 +204,10 @@ IPC_MESSAGE_CONTROL3(ServiceWorkerMsg_ServiceWorkerStateChanged,
blink::WebServiceWorkerState)
// Tells the child process to set service workers for the given provider.
IPC_MESSAGE_CONTROL4(ServiceWorkerMsg_SetVersionAttributes,
IPC_MESSAGE_CONTROL5(ServiceWorkerMsg_SetVersionAttributes,
int /* thread_id */,
int /* provider_id */,
int /* registration_handle_id */,
int /* changed_mask */,
content::ServiceWorkerVersionAttributes)
......
......@@ -25,6 +25,7 @@ static const int kInvalidServiceWorkerRequestId = -1;
// Constants for invalid identifiers.
static const int kInvalidServiceWorkerHandleId = -1;
static const int kInvalidServiceWorkerRegistrationHandleId = -1;
static const int kInvalidServiceWorkerProviderId = -1;
static const int64 kInvalidServiceWorkerRegistrationId = -1;
static const int64 kInvalidServiceWorkerVersionId = -1;
......
......@@ -1170,6 +1170,8 @@
'browser/service_worker/service_worker_register_job.h',
'browser/service_worker/service_worker_registration.cc',
'browser/service_worker/service_worker_registration.h',
'browser/service_worker/service_worker_registration_handle.cc',
'browser/service_worker/service_worker_registration_handle.h',
'browser/service_worker/service_worker_registration_status.cc',
'browser/service_worker/service_worker_registration_status.h',
'browser/service_worker/service_worker_request_handler.cc',
......
......@@ -165,6 +165,8 @@
'child/service_worker/service_worker_network_provider.h',
'child/service_worker/service_worker_provider_context.cc',
'child/service_worker/service_worker_provider_context.h',
'child/service_worker/service_worker_registration_handle_reference.cc',
'child/service_worker/service_worker_registration_handle_reference.h',
'child/service_worker/web_service_worker_impl.cc',
'child/service_worker/web_service_worker_impl.h',
'child/service_worker/web_service_worker_provider_impl.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