Commit c9505ef0 authored by iclelland's avatar iclelland Committed by Commit bot

[Background Sync] Add renderer code to interface between JS API and back-end service

This patch introduces a BackgroundSyncProvider for use by the Blink
BackgroundSync module, as well as a proxy object which is used when calling the
provider from off of the main thread. The code in BlinkPlatformImpl will
dispatch to the appropriate object depending on the running thread.

This patch depends on the Mojo service definitions in
https://codereview.chromium.org/1106193002

BUG=479251

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

Cr-Commit-Position: refs/heads/master@{#329417}
parent ecb5ce9e
// Copyright 2015 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/background_sync/background_sync_provider.h"
#include "base/bind.h"
#include "base/memory/scoped_ptr.h"
#include "content/child/background_sync/background_sync_type_converters.h"
#include "content/child/service_worker/web_service_worker_registration_impl.h"
#include "content/child/worker_task_runner.h"
#include "content/public/common/service_registry.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncError.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncRegistration.h"
namespace content {
namespace {
// Returns the id of the given |service_worker_registration|, which
// is only available on the implementation of the interface.
int64 GetServiceWorkerRegistrationId(
blink::WebServiceWorkerRegistration* service_worker_registration) {
return static_cast<WebServiceWorkerRegistrationImpl*>(
service_worker_registration)->registration_id();
}
} // namespace
BackgroundSyncProvider::BackgroundSyncProvider(
ServiceRegistry* service_registry)
: service_registry_(service_registry) {
DCHECK(service_registry);
}
BackgroundSyncProvider::~BackgroundSyncProvider() {
}
void BackgroundSyncProvider::registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks) {
DCHECK(options);
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64 service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
scoped_ptr<const blink::WebSyncRegistration> optionsPtr(options);
scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacksPtr(callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->Register(
mojo::ConvertTo<SyncRegistrationPtr>(*(optionsPtr.get())),
service_worker_registration_id,
base::Bind(&BackgroundSyncProvider::RegisterCallback,
base::Unretained(this), base::Passed(callbacksPtr.Pass())));
}
void BackgroundSyncProvider::unregisterBackgroundSync(
blink::WebSyncRegistration::Periodicity periodicity,
int64_t id,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncUnregistrationCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64 service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacksPtr(callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->Unregister(
mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity), id, tag.utf8(),
service_worker_registration_id,
base::Bind(&BackgroundSyncProvider::UnregisterCallback,
base::Unretained(this), base::Passed(callbacksPtr.Pass())));
}
void BackgroundSyncProvider::getRegistration(
blink::WebSyncRegistration::Periodicity periodicity,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64 service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacksPtr(callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->GetRegistration(
mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity), tag.utf8(),
service_worker_registration_id,
base::Bind(&BackgroundSyncProvider::RegisterCallback,
base::Unretained(this), base::Passed(callbacksPtr.Pass())));
}
void BackgroundSyncProvider::getRegistrations(
blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
int64 service_worker_registration_id =
GetServiceWorkerRegistrationId(service_worker_registration);
scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacksPtr(callbacks);
// base::Unretained is safe here, as the mojo channel will be deleted (and
// will wipe its callbacks) before 'this' is deleted.
GetBackgroundSyncServicePtr()->GetRegistrations(
mojo::ConvertTo<BackgroundSyncPeriodicity>(periodicity),
service_worker_registration_id,
base::Bind(&BackgroundSyncProvider::GetRegistrationsCallback,
base::Unretained(this), base::Passed(callbacksPtr.Pass())));
}
void BackgroundSyncProvider::RegisterCallback(
scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
const SyncRegistrationPtr& options) {
// TODO(iclelland): Pass through the various errors from the manager to here
// and handle them appropriately.
scoped_ptr<blink::WebSyncRegistration> result;
if (!options.is_null())
result = mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(options);
callbacks->onSuccess(result.release());
}
void BackgroundSyncProvider::UnregisterCallback(
scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacks,
bool success) {
// TODO(iclelland): Pass through the various errors from the manager to here
// and handle them appropriately.
if (success) {
callbacks->onSuccess(new bool(success));
} else {
callbacks->onError(
new blink::WebSyncError(blink::WebSyncError::ErrorTypeUnknown,
"Sync registration does not exist"));
}
}
void BackgroundSyncProvider::GetRegistrationsCallback(
scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
const mojo::Array<SyncRegistrationPtr>& registrations) {
// TODO(iclelland): Pass through the various errors from the manager to here
// and handle them appropriately.
blink::WebVector<blink::WebSyncRegistration*>* results =
new blink::WebVector<blink::WebSyncRegistration*>(registrations.size());
for (size_t i = 0; i < registrations.size(); ++i) {
(*results)[i] = mojo::ConvertTo<scoped_ptr<blink::WebSyncRegistration>>(
registrations[i]).release();
}
callbacks->onSuccess(results);
}
BackgroundSyncServicePtr&
BackgroundSyncProvider::GetBackgroundSyncServicePtr() {
if (!background_sync_service_.get())
service_registry_->ConnectToRemoteService(&background_sync_service_);
return background_sync_service_;
}
} // namespace content
// Copyright 2015 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_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_H_
#define CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_H_
#include <string>
#include "base/memory/scoped_ptr.h"
#include "content/child/worker_task_runner.h"
#include "content/common/background_sync_service.mojom.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h"
namespace content {
class ServiceRegistry;
// The BackgroundSyncProvider is called by the SyncManager and SyncRegistration
// objects (and their Periodic counterparts) and communicates with the
// BackgroundSyncManager object in the browser process. This class is
// instantiated on the main thread by BlinkPlatformImpl, and its methods can be
// called directly from the main thread.
class BackgroundSyncProvider : public blink::WebSyncProvider {
public:
explicit BackgroundSyncProvider(ServiceRegistry* service_registry);
~BackgroundSyncProvider() override;
// blink::WebSyncProvider implementation
void registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks);
void unregisterBackgroundSync(
blink::WebSyncRegistration::Periodicity periodicity,
int64_t id,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncUnregistrationCallbacks* callbacks);
void getRegistration(
blink::WebSyncRegistration::Periodicity,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks);
void getRegistrations(
blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks);
private:
// Callback handlers
void RegisterCallback(
scoped_ptr<blink::WebSyncRegistrationCallbacks> callbacks,
const SyncRegistrationPtr& options);
void UnregisterCallback(
scoped_ptr<blink::WebSyncUnregistrationCallbacks> callbacks,
bool success);
void GetRegistrationsCallback(
scoped_ptr<blink::WebSyncGetRegistrationsCallbacks> callbacks,
const mojo::Array<SyncRegistrationPtr>& registrations);
// Helper method that returns an initialized BackgroundSyncServicePtr.
BackgroundSyncServicePtr& GetBackgroundSyncServicePtr();
ServiceRegistry* service_registry_;
BackgroundSyncServicePtr background_sync_service_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncProvider);
};
} // namespace content
#endif // CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_H_
// Copyright 2015 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/background_sync/background_sync_provider_thread_proxy.h"
#include "base/bind.h"
#include "base/bind_helpers.h"
#include "base/lazy_instance.h"
#include "base/location.h"
#include "base/memory/scoped_ptr.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_local.h"
#include "content/child/background_sync/background_sync_provider.h"
using base::LazyInstance;
using base::ThreadLocalPointer;
namespace content {
namespace {
// CallbackThreadAdapter<S,T> is a wrapper for WebCallbacks<S,T> which
// switches to a specific thread before calling the wrapped callback's
// onSuccess or onError methods.
//
// Takes ownership of the WebCallbacks object which it wraps.
template <typename S, typename T>
class CallbackThreadAdapter : public blink::WebCallbacks<S, T> {
public:
CallbackThreadAdapter(scoped_ptr<blink::WebCallbacks<S, T>> callbacks,
int worker_thread_id)
: worker_thread_id_(worker_thread_id) {
callbacks_.reset(callbacks.release());
}
virtual void onSuccess(S* results) {
// If the worker thread has been destroyed, then this task will be
// silently discarded.
WorkerTaskRunner::Instance()->PostTask(
worker_thread_id_,
base::Bind(&blink::WebCallbacks<S, T>::onSuccess,
base::Unretained(callbacks_.get()), results));
}
virtual void onError(T* error) {
// If the worker thread has been destroyed, then this task will be
// silently discarded.
WorkerTaskRunner::Instance()->PostTask(
worker_thread_id_,
base::Bind(&blink::WebCallbacks<S, T>::onError,
base::Unretained(callbacks_.get()), error));
}
private:
scoped_ptr<blink::WebCallbacks<S, T>> callbacks_;
int worker_thread_id_;
};
LazyInstance<ThreadLocalPointer<BackgroundSyncProviderThreadProxy>>::Leaky
g_sync_provider_tls = LAZY_INSTANCE_INITIALIZER;
} // anonymous namespace
BackgroundSyncProviderThreadProxy*
BackgroundSyncProviderThreadProxy::GetThreadInstance(
base::SingleThreadTaskRunner* main_thread_task_runner,
BackgroundSyncProvider* sync_provider) {
if (g_sync_provider_tls.Pointer()->Get())
return g_sync_provider_tls.Pointer()->Get();
BackgroundSyncProviderThreadProxy* instance =
new BackgroundSyncProviderThreadProxy(main_thread_task_runner,
sync_provider);
DCHECK(WorkerTaskRunner::Instance()->CurrentWorkerId());
WorkerTaskRunner::Instance()->AddStopObserver(instance);
return instance;
}
void BackgroundSyncProviderThreadProxy::registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks) {
DCHECK(options);
DCHECK(service_worker_registration);
DCHECK(callbacks);
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&BackgroundSyncProvider::registerBackgroundSync,
base::Unretained(sync_provider_), options,
service_worker_registration,
new CallbackThreadAdapter<blink::WebSyncRegistration,
blink::WebSyncError>(
make_scoped_ptr(callbacks),
WorkerTaskRunner::Instance()->CurrentWorkerId())));
}
void BackgroundSyncProviderThreadProxy::unregisterBackgroundSync(
blink::WebSyncRegistration::Periodicity periodicity,
int64_t id,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncUnregistrationCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&BackgroundSyncProvider::unregisterBackgroundSync,
base::Unretained(sync_provider_), periodicity, id, tag,
service_worker_registration,
new CallbackThreadAdapter<bool, blink::WebSyncError>(
make_scoped_ptr(callbacks),
WorkerTaskRunner::Instance()->CurrentWorkerId())));
}
void BackgroundSyncProviderThreadProxy::getRegistration(
blink::WebSyncRegistration::Periodicity periodicity,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&BackgroundSyncProvider::getRegistration,
base::Unretained(sync_provider_), periodicity, tag,
service_worker_registration,
new CallbackThreadAdapter<blink::WebSyncRegistration,
blink::WebSyncError>(
make_scoped_ptr(callbacks),
WorkerTaskRunner::Instance()->CurrentWorkerId())));
}
void BackgroundSyncProviderThreadProxy::getRegistrations(
blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks) {
DCHECK(service_worker_registration);
DCHECK(callbacks);
main_thread_task_runner_->PostTask(
FROM_HERE,
base::Bind(&BackgroundSyncProvider::getRegistrations,
base::Unretained(sync_provider_), periodicity,
service_worker_registration,
new CallbackThreadAdapter<
blink::WebVector<blink::WebSyncRegistration*>,
blink::WebSyncError>(
make_scoped_ptr(callbacks),
WorkerTaskRunner::Instance()->CurrentWorkerId())));
}
void BackgroundSyncProviderThreadProxy::OnWorkerRunLoopStopped() {
delete this;
}
BackgroundSyncProviderThreadProxy::BackgroundSyncProviderThreadProxy(
base::SingleThreadTaskRunner* main_thread_task_runner,
BackgroundSyncProvider* sync_provider)
: main_thread_task_runner_(main_thread_task_runner),
sync_provider_(sync_provider) {
g_sync_provider_tls.Pointer()->Set(this);
}
BackgroundSyncProviderThreadProxy::~BackgroundSyncProviderThreadProxy() {
g_sync_provider_tls.Pointer()->Set(nullptr);
}
} // namespace content
// Copyright 2015 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_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_THREAD_PROXY_H_
#define CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_THREAD_PROXY_H_
#include "base/macros.h"
#include "content/child/worker_task_runner.h"
#include "third_party/WebKit/public/platform/modules/background_sync/WebSyncProvider.h"
namespace base {
class SingleThreadTaskRunner;
}
namespace content {
class BackgroundSyncProvider;
// BackgroundSyncProviderThreadProxy is a proxy to the BackgroundSyncProvider
// for callers running on a different thread than the main thread. There is one
// instance per worker thread.
//
// This class handles all of the thread switching, jumping to the main thread to
// call the WebSyncProvider methods, and wrapping the callbacks passed in with
// code to switch back to the original calling thread.
class BackgroundSyncProviderThreadProxy : public blink::WebSyncProvider,
public WorkerTaskRunner::Observer {
public:
static BackgroundSyncProviderThreadProxy* GetThreadInstance(
base::SingleThreadTaskRunner* main_thread_task_runner,
BackgroundSyncProvider* permissions_dispatcher);
// blink::WebSyncProvider implementation
void registerBackgroundSync(
const blink::WebSyncRegistration* options,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks);
void unregisterBackgroundSync(
blink::WebSyncRegistration::Periodicity periodicity,
int64_t id,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncUnregistrationCallbacks* callbacks);
void getRegistration(
blink::WebSyncRegistration::Periodicity,
const blink::WebString& tag,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncRegistrationCallbacks* callbacks);
void getRegistrations(
blink::WebSyncRegistration::Periodicity periodicity,
blink::WebServiceWorkerRegistration* service_worker_registration,
blink::WebSyncGetRegistrationsCallbacks* callbacks);
// WorkerTaskRunner::Observer implementation.
void OnWorkerRunLoopStopped() override;
private:
BackgroundSyncProviderThreadProxy(
base::SingleThreadTaskRunner* main_thread_task_runner,
BackgroundSyncProvider* sync_provider);
virtual ~BackgroundSyncProviderThreadProxy();
scoped_refptr<base::SingleThreadTaskRunner> main_thread_task_runner_;
// This belongs to the renderer main thread, (created by BlinkPlatformImpl)
// and so should outlive the BackgroundSyncProviderThreadProxy, which is
// created for a worker thread.
BackgroundSyncProvider* sync_provider_;
DISALLOW_COPY_AND_ASSIGN(BackgroundSyncProviderThreadProxy);
};
} // namespace content
#endif // CONTENT_CHILD_BACKGROUND_SYNC_BACKGROUND_SYNC_PROVIDER_THREAD_PROXY_H_
......@@ -33,6 +33,8 @@
#include "components/scheduler/child/webthread_impl_for_worker_scheduler.h"
#include "content/app/resources/grit/content_resources.h"
#include "content/app/strings/grit/content_strings.h"
#include "content/child/background_sync/background_sync_provider.h"
#include "content/child/background_sync/background_sync_provider_thread_proxy.h"
#include "content/child/bluetooth/web_bluetooth_impl.h"
#include "content/child/child_thread_impl.h"
#include "content/child/content_child_helpers.h"
......@@ -455,6 +457,8 @@ void BlinkPlatformImpl::InternalInit() {
push_dispatcher_ = ChildThreadImpl::current()->push_dispatcher();
permission_client_.reset(new PermissionDispatcher(
ChildThreadImpl::current()->service_registry()));
sync_provider_.reset(new BackgroundSyncProvider(
ChildThreadImpl::current()->service_registry()));
}
if (main_thread_task_runner_.get()) {
......@@ -1200,6 +1204,17 @@ blink::WebPermissionClient* BlinkPlatformImpl::permissionClient() {
main_thread_task_runner_.get(), permission_client_.get());
}
blink::WebSyncProvider* BlinkPlatformImpl::backgroundSyncProvider() {
if (!sync_provider_.get())
return nullptr;
if (IsMainThread())
return sync_provider_.get();
return BackgroundSyncProviderThreadProxy::GetThreadInstance(
main_thread_task_runner_.get(), sync_provider_.get());
}
WebThemeEngine* BlinkPlatformImpl::themeEngine() {
return &native_theme_engine_;
}
......
......@@ -33,6 +33,7 @@ class MessageLoop;
}
namespace content {
class BackgroundSyncProvider;
class FlingCurveConfiguration;
class NotificationDispatcher;
class PermissionDispatcher;
......@@ -167,6 +168,7 @@ class CONTENT_EXPORT BlinkPlatformImpl
virtual blink::WebPushProvider* pushProvider();
virtual blink::WebNavigatorConnectProvider* navigatorConnectProvider();
virtual blink::WebPermissionClient* permissionClient();
virtual blink::WebSyncProvider* backgroundSyncProvider();
void SuspendSharedTimer();
void ResumeSharedTimer();
......@@ -210,6 +212,7 @@ class CONTENT_EXPORT BlinkPlatformImpl
scoped_refptr<NotificationDispatcher> notification_dispatcher_;
scoped_refptr<PushDispatcher> push_dispatcher_;
scoped_ptr<PermissionDispatcher> permission_client_;
scoped_ptr<BackgroundSyncProvider> sync_provider_;
};
} // namespace content
......
......@@ -42,6 +42,10 @@
'child/appcache/web_application_cache_host_impl.cc',
'child/appcache/web_application_cache_host_impl.h',
'child/assert_matching_enums.cc',
'child/background_sync/background_sync_provider_thread_proxy.cc',
'child/background_sync/background_sync_provider_thread_proxy.h',
'child/background_sync/background_sync_provider.cc',
'child/background_sync/background_sync_provider.h',
'child/background_sync/background_sync_type_converters.cc',
'child/background_sync/background_sync_type_converters.h',
'child/blink_platform_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