Skip to content

Instantly share code, notes, and snippets.

@ferjm
Created March 17, 2016 11:10
Show Gist options
  • Save ferjm/b42d34638ccaf40fddb4 to your computer and use it in GitHub Desktop.
Save ferjm/b42d34638ccaf40fddb4 to your computer and use it in GitHub Desktop.
diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf
--- a/dom/bindings/Bindings.conf
+++ b/dom/bindings/Bindings.conf
@@ -1264,16 +1264,22 @@ DOMInterfaces = {
'SVGUnitTypes' : {
'concrete': False,
},
'SVGZoomAndPan' : {
'concrete': False,
},
+'SyncEvent': {
+ 'headerFile': 'mozilla/dom/ServiceWorkerEvents.h',
+ 'nativeType': 'mozilla::dom::workers::SyncEvent',
+ 'workers': True
+},
+
'Text': {
# Total hack to allow binding code to realize that nsTextNode can
# in fact be cast to Text.
'headerFile': 'nsTextNode.h',
},
'TextDecoder': {
'wrapperCache': False
diff --git a/dom/interfaces/base/nsIServiceWorkerManager.idl b/dom/interfaces/base/nsIServiceWorkerManager.idl
--- a/dom/interfaces/base/nsIServiceWorkerManager.idl
+++ b/dom/interfaces/base/nsIServiceWorkerManager.idl
@@ -72,17 +72,17 @@ interface nsIServiceWorkerRegistrationIn
[scriptable, uuid(9e523e7c-ad6f-4df0-8077-c74aebbc679d)]
interface nsIServiceWorkerManagerListener : nsISupports
{
void onRegister(in nsIServiceWorkerRegistrationInfo aInfo);
void onUnregister(in nsIServiceWorkerRegistrationInfo aInfo);
};
-[scriptable, builtinclass, uuid(7404c8e8-4d47-4449-8ed1-47d1261d4e33)]
+[scriptable, builtinclass, uuid(0577039d-c34e-4f01-afb4-a423ae650e54)]
interface nsIServiceWorkerManager : nsISupports
{
/**
* Registers a ServiceWorker with script loaded from `aScriptURI` to act as
* the ServiceWorker for aScope. Requires a valid entry settings object on
* the stack. This means you must call this from content code 'within'
* a window.
*
@@ -186,19 +186,23 @@ interface nsIServiceWorkerManager : nsIS
in AString aData,
in AString aBehavior);
[optional_argc] void sendPushEvent(in ACString aOriginAttributes,
in ACString aScope,
[optional] in uint32_t aDataLength,
[optional, array, size_is(aDataLength)] in uint8_t aDataBytes);
void sendPushSubscriptionChangeEvent(in ACString aOriginAttributes,
in ACString scope);
-
void addListener(in nsIServiceWorkerManagerListener aListener);
void removeListener(in nsIServiceWorkerManagerListener aListener);
bool shouldReportToWindow(in mozIDOMWindowProxy aWindow, in ACString aScope);
+
+ void sendSyncEvent(in ACString aOriginAttributes,
+ in ACString scope,
+ in AString aTag,
+ in boolean aLastChance);
};
%{ C++
#define SERVICEWORKERMANAGER_CONTRACTID "@mozilla.org/serviceworkers/manager;1"
%}
diff --git a/dom/moz.build b/dom/moz.build
--- a/dom/moz.build
+++ b/dom/moz.build
@@ -2,124 +2,125 @@
# vim: set filetype=python:
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
JAR_MANIFESTS += ['jar.mn']
interfaces = [
+ 'apps',
'base',
'canvas',
'core',
+ 'css',
+ 'events',
+ 'gamepad',
+ 'geolocation',
'html',
- 'events',
+ 'json',
+ 'notification',
+ 'offline',
+ 'permission',
+ 'range',
+ 'security',
'settings',
+ 'smil',
+ 'storage',
'stylesheets',
+ 'svg',
'sidebar',
- 'css',
'traversal',
- 'range',
'xbl',
'xpath',
- 'xul',
- 'security',
- 'storage',
- 'json',
- 'offline',
- 'geolocation',
- 'notification',
- 'permission',
- 'svg',
- 'smil',
- 'apps',
- 'gamepad',
+ 'xul'
]
if not CONFIG['MOZ_SIMPLEPUSH']:
interfaces += ['push']
DIRS += ['interfaces/' + i for i in interfaces]
DIRS += [
+ 'activities',
+ 'alarm',
'animation',
'apps',
+ 'archivereader',
+ 'asmjscache',
+ 'audiochannel',
'base',
+ 'battery',
+ 'bindings',
'bluetooth',
- 'activities',
- 'archivereader',
- 'requestsync',
- 'bindings',
- 'battery',
+ 'broadcastchannel',
'browser-element',
'cache',
+ 'camera',
'canvas',
'cellbroadcast',
'contacts',
'crypto',
- 'phonenumberutils',
- 'alarm',
'datastore',
'devicestorage',
'encoding',
'events',
'fetch',
'filehandle',
'filesystem',
'fmradio',
'geolocation',
'html',
'icc',
+ 'indexedDB',
+ 'inputmethod',
'inputport',
+ 'ipc',
'json',
'jsurl',
- 'asmjscache',
+ 'locales',
+ 'manifest',
'mathml',
'media',
+ 'messagechannel',
'messages',
'mobileconnection',
+ 'mobilemessage',
+ 'network',
+ 'newapps',
'notification',
'offline',
+ 'permission',
+ 'phonenumberutils',
+ 'plugins/base',
+ 'plugins/ipc',
'power',
+ 'promise',
'quota',
+ 'requestsync',
+ 'resourcestats',
'security',
'settings',
'storage',
'svg',
- 'mobilemessage',
+ 'sync',
+ 'system',
'time',
- 'locales',
- 'network',
- 'permission',
- 'plugins/base',
- 'plugins/ipc',
- 'indexedDB',
- 'system',
- 'ipc',
'workers',
- 'camera',
- 'audiochannel',
- 'broadcastchannel',
- 'messagechannel',
- 'promise',
'smil',
'telephony',
'tv',
+ 'u2f',
'voicemail',
- 'inputmethod',
+ 'vr',
'webidl',
'xbl',
'xml',
'xslt',
- 'xul',
- 'resourcestats',
- 'manifest',
- 'vr',
- 'newapps',
- 'u2f',
+ 'xul'
]
if CONFIG['OS_ARCH'] == 'WINNT':
DIRS += ['plugins/ipc/hangui']
if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk':
DIRS += [
'speakermanager',
@@ -146,20 +147,20 @@ if CONFIG['MOZ_SIMPLEPUSH']:
else:
DIRS += ['push']
if CONFIG['MOZ_SECUREELEMENT']:
DIRS += ['secureelement']
if CONFIG['MOZ_B2G']:
DIRS += [
+ 'engineeringmode',
'downloads',
'identity',
- 'mobileid',
- 'engineeringmode'
+ 'mobileid'
]
DIRS += ['presentation']
TEST_DIRS += [
'tests',
'imptests',
]
diff --git a/dom/sync/PSyncManager.ipdl b/dom/sync/PSyncManager.ipdl
new file mode 100644
--- /dev/null
+++ b/dom/sync/PSyncManager.ipdl
@@ -0,0 +1,28 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include protocol PBackground;
+
+include SyncIPCTypes;
+
+using struct nsID from "nsID.h";
+
+namespace mozilla {
+namespace dom {
+
+protocol PSyncManager
+{
+ manager PBackground;
+
+parent: // child -> parent messages
+ async Request(nsID aRequestId, SyncOp aOp);
+ async Shutdown();
+
+child: // parent -> child messages
+ async Response(nsID requestId, SyncOpResponse aResponse);
+ async __delete__();
+};
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/sync/SyncIPCTypes.ipdlh b/dom/sync/SyncIPCTypes.ipdlh
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncIPCTypes.ipdlh
@@ -0,0 +1,57 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+include PBackgroundSharedTypes;
+
+namespace mozilla {
+namespace dom {
+
+struct SyncRegisterArgs
+{
+ nsString mScope;
+ nsString mTag;
+};
+
+struct SyncGetTagsArgs
+{
+};
+
+union SyncOpArgs
+{
+ SyncRegisterArgs;
+ SyncGetTagsArgs;
+};
+
+struct SyncOp
+{
+ PrincipalInfo mPrincipal;
+ SyncOpArgs mArgs;
+};
+
+struct SyncRegisterResponse
+{
+ bool mSuccess;
+};
+
+struct SyncGetTagsResponse
+{
+ nsString[] mTags;
+};
+
+struct SyncOpError
+{
+ uint32_t mCode;
+};
+
+union SyncOpResponse
+{
+ SyncRegisterResponse;
+ SyncGetTagsResponse;
+ SyncOpError;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+
diff --git a/dom/sync/SyncManager.cpp b/dom/sync/SyncManager.cpp
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManager.cpp
@@ -0,0 +1,411 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SyncManager.h"
+#include "SyncManagerChild.h"
+
+#include "mozilla/dom/Promise.h"
+#include "mozilla/dom/PromiseWorkerProxy.h"
+#include "mozilla/dom/SyncIPCTypes.h"
+#include "mozilla/dom/SyncManagerBinding.h"
+#include "mozilla/ipc/BackgroundChild.h"
+#include "mozilla/ipc/BackgroundUtils.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+#include "mozilla/Preferences.h"
+#include "mozilla/unused.h"
+#include "nsIGlobalObject.h"
+#include "nsISupportsPrimitives.h"
+#include "WorkerPrivate.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+using namespace workers;
+
+// Helpers
+
+class SyncOpRunnable final : public nsICancelableRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ SyncOpRunnable(Promise* aPromise, nsAutoPtr<SyncOp>& aOp)
+ : mPromise(aPromise)
+ , mOp(aOp)
+ {
+ MOZ_ASSERT(mPromise);
+ MOZ_ASSERT(mOp);
+ }
+
+ void SetActor(SyncManagerChild* aActor)
+ {
+ MOZ_ASSERT(!mActor);
+ MOZ_ASSERT(aActor);
+ mActor = aActor;
+ }
+
+ NS_IMETHODIMP Run() override
+ {
+ MOZ_ASSERT(mActor);
+ if (mActor->IsActorDestroyed()) {
+ return NS_OK;
+ }
+
+ return mActor->ExecuteOp(mPromise, mOp);
+ }
+
+ NS_IMETHODIMP Cancel() override
+ {
+ mActor = nullptr;
+ mPromise = nullptr;
+ mOp = nullptr;
+ return NS_OK;
+ }
+
+private:
+ ~SyncOpRunnable() {}
+
+ RefPtr<Promise> mPromise;
+ nsAutoPtr<SyncOp> mOp;
+ RefPtr<SyncManagerChild> mActor;
+};
+
+NS_IMPL_ISUPPORTS(SyncOpRunnable, nsICancelableRunnable, nsIRunnable)
+
+class TeardownRunnable final : public nsICancelableRunnable
+{
+public:
+ NS_DECL_ISUPPORTS
+
+ explicit TeardownRunnable(SyncManagerChild* aActor)
+ : mActor(aActor)
+ {
+ MOZ_ASSERT(mActor);
+ }
+
+ NS_IMETHODIMP Run() override
+ {
+ MOZ_ASSERT(mActor);
+ if (!mActor->IsActorDestroyed()) {
+ mActor->SendShutdown();
+ }
+ return NS_OK;
+ }
+
+ NS_IMETHODIMP Cancel() override
+ {
+ mActor = nullptr;
+ return NS_OK;
+ }
+
+private:
+ ~TeardownRunnable() {};
+
+ RefPtr<SyncManagerChild> mActor;
+};
+
+NS_IMPL_ISUPPORTS(TeardownRunnable, nsICancelableRunnable, nsIRunnable)
+
+class SyncManagerFeature final : public workers::WorkerFeature
+{
+ SyncManager* mManager;
+
+public:
+ explicit SyncManagerFeature(SyncManager* aManager)
+ : mManager(aManager)
+ {
+ MOZ_COUNT_CTOR(SyncManagerFeature);
+ }
+
+ virtual bool Notify(JSContext* aCtx, workers::Status aStatus) override
+ {
+ if (aStatus >= Closing) {
+ mManager->Shutdown();
+ }
+ return true;
+ }
+
+private:
+ ~SyncManagerFeature()
+ {
+ MOZ_COUNT_CTOR(SyncManagerFeature);
+ }
+};
+
+// SyncManager
+
+// static
+already_AddRefed<SyncManager>
+SyncManager::CreateOnMainThread(nsIGlobalObject* aGlobal,
+ nsIPrincipal* aPrincipal,
+ const nsAString& aScope,
+ ErrorResult& aRv)
+{
+ MOZ_ASSERT(aGlobal);
+ MOZ_ASSERT(aPrincipal);
+ MOZ_ASSERT(!aScope.IsEmpty());
+ MOZ_ASSERT(NS_IsMainThread());
+
+ PrincipalInfo principalInfo;
+ aRv = PrincipalToPrincipalInfo(aPrincipal, &principalInfo);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ RefPtr<SyncManager> ref = new SyncManager(aGlobal, principalInfo, aScope);
+
+ // Register as observeer for inner-window-destroyed.
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ aRv = obs->AddObserver(ref, "inner-window-destroyed",
+ false /* ownsWeak */);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+ }
+
+ nsCOMPtr<nsPIDOMWindowInner> window = do_QueryInterface(aGlobal);
+ MOZ_ASSERT(window);
+ MOZ_ASSERT(window->IsInnerWindow());
+ ref->mInnerID = window->WindowID();
+
+ return ref.forget();
+}
+
+// static
+already_AddRefed<SyncManager>
+SyncManager::CreateOnWorker(nsIGlobalObject* aGlobal,
+ WorkerPrivate* aWorkerPrivate,
+ const nsAString& aScope)
+{
+ MOZ_ASSERT(aWorkerPrivate);
+ MOZ_ASSERT(!aScope.IsEmpty());
+ aWorkerPrivate->AssertIsOnWorkerThread();
+
+ const PrincipalInfo& principalInfo = aWorkerPrivate->GetPrincipalInfo();
+
+ RefPtr<SyncManager> ref = new SyncManager(aGlobal, principalInfo, aScope);
+
+ ref->mWorkerFeature = new SyncManagerFeature(ref);
+ JSContext* cx = aWorkerPrivate->GetJSContext();
+ if (NS_WARN_IF(!aWorkerPrivate->AddFeature(cx, ref->mWorkerFeature))) {
+ NS_WARNING("Failed to register SyncManager worker feature");
+ ref->mWorkerFeature = nullptr;
+ return nullptr;
+ }
+
+ return ref.forget();
+}
+
+SyncManager::SyncManager(nsIGlobalObject* aGlobal,
+ const PrincipalInfo& aPrincipalInfo,
+ const nsAString& aScope)
+ : mInnerID(0)
+ , mGlobal(aGlobal)
+ , mWorkerFeature(nullptr)
+ , mShuttingDown(false)
+ , mPrincipalInfo(MakeUnique<PrincipalInfo>(aPrincipalInfo))
+ , mScope(aScope)
+{
+ // Register this component to PBackground.
+ PBackgroundChild* actor = BackgroundChild::GetForCurrentThread();
+ if (actor) {
+ ActorCreated(actor);
+ } else {
+ MOZ_ALWAYS_TRUE(BackgroundChild::GetOrCreateForCurrentThread(this));
+ }
+}
+
+SyncManager::~SyncManager()
+{
+ Shutdown();
+ MOZ_ASSERT(!mWorkerFeature);
+ MOZ_ASSERT(!mActor);
+}
+
+void
+SyncManager::Shutdown()
+{
+ if (mWorkerFeature) {
+ WorkerPrivate* workerPrivate = GetCurrentThreadWorkerPrivate();
+ workerPrivate->RemoveFeature(workerPrivate->GetJSContext(), mWorkerFeature);
+ mWorkerFeature = nullptr;
+ }
+
+ if (mActor) {
+ RefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor);
+ NS_DispatchToCurrentThread(runnable);
+ mActor = nullptr;
+ }
+
+ mPendingOperations.Clear();
+}
+
+// Bindings methods.
+
+JSObject*
+SyncManager::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
+{
+ return SyncManagerBinding::Wrap(aCx, this, aGivenProto);
+}
+
+// static
+bool
+SyncManager::PrefEnabled(JSContext* aCx, JSObject* aObj)
+{
+ using mozilla::dom::workers::WorkerPrivate;
+ using mozilla::dom::workers::GetWorkerPrivateFromContext;
+
+ // If we are on the main thread, then check the pref directly.
+ if (NS_IsMainThread()) {
+ bool enabled = false;
+ Preferences::GetBool("dom.background.sync.enabled", &enabled);
+ return enabled;
+ }
+
+ // Otherwise check the pref via the worker private helper.
+ WorkerPrivate* workerPrivate = GetWorkerPrivateFromContext(aCx);
+ if (!workerPrivate) {
+ return false;
+ }
+
+ return workerPrivate->BackgroundSyncEnabled();
+}
+
+// nsIIPCBackgroundChildCreateCallback methods.
+
+void
+SyncManager::ActorFailed()
+{
+ MOZ_CRASH("Failed to create a PBackgroundChild actor!");
+}
+
+void
+SyncManager::ActorCreated(PBackgroundChild* aActor)
+{
+ MOZ_ASSERT(aActor);
+ MOZ_ASSERT(!mActor);
+
+ if (mShuttingDown) {
+ mPendingOperations.Clear();
+ return;
+ }
+
+ PSyncManagerChild* actor = aActor->SendPSyncManagerConstructor();
+ mActor = static_cast<SyncManagerChild*>(actor);
+ MOZ_ASSERT(mActor);
+
+ // Flush pending requests.
+ for (uint32_t i = 0, len = mPendingOperations.Length(); i < len; ++i) {
+ RefPtr<SyncOpRunnable> runnable = mPendingOperations[i];
+ MOZ_ASSERT(runnable);
+ runnable->SetActor(mActor);
+ if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
+ NS_WARNING("Failed to dispatch to the current thread");
+ mPendingOperations.Clear();
+ return;
+ }
+ }
+ mPendingOperations.Clear();
+}
+
+// nsIObserver
+
+NS_IMETHODIMP
+SyncManager::Observe(nsISupports* aSubject,
+ const char* aTopic,
+ const char16_t* aData)
+{
+ MOZ_ASSERT(NS_IsMainThread());
+ MOZ_ASSERT(!strcmp(aTopic, "inner-window-destroyed"));
+
+ nsCOMPtr<nsISupportsPRUint64> wrapper = do_QueryInterface(aSubject);
+ NS_ENSURE_TRUE(wrapper, NS_ERROR_FAILURE);
+
+ uint64_t innerID;
+ nsresult rv = wrapper->GetData(&innerID);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ if (innerID != mInnerID) {
+ return NS_OK;
+ }
+
+ mShuttingDown = true;
+ nsCOMPtr<nsIObserverService> obs = mozilla::services::GetObserverService();
+ if (obs) {
+ obs->RemoveObserver(this, "inner-window-destroyed");
+ }
+
+ if (mActor) {
+ RefPtr<TeardownRunnable> runnable = new TeardownRunnable(mActor);
+ nsresult rv = NS_DispatchToCurrentThread(runnable);
+ Unused << NS_WARN_IF(NS_FAILED(rv));
+ mActor = nullptr;
+ } else {
+ mPendingOperations.Clear();
+ }
+
+ return NS_OK;
+}
+
+already_AddRefed<Promise>
+SyncManager::ExecuteOp(const SyncOpArgs& aArgs, ErrorResult& aRv)
+{
+ if (mShuttingDown) {
+ mPendingOperations.Clear();
+ return nullptr;
+ }
+
+ RefPtr<Promise> p = Promise::Create(mGlobal, aRv);
+ if (NS_WARN_IF(aRv.Failed())) {
+ return nullptr;
+ }
+
+ nsAutoPtr<SyncOp> op(new SyncOp(*mPrincipalInfo, aArgs));
+ RefPtr<SyncOpRunnable> runnable = new SyncOpRunnable(p, op);
+
+ if (mActor) {
+ runnable->SetActor(mActor);
+ if (NS_FAILED(NS_DispatchToCurrentThread(runnable))) {
+ NS_WARNING("Failed to dispatch to the current thread");
+ }
+ } else {
+ mPendingOperations.AppendElement(runnable);
+ }
+
+ return p.forget();
+}
+
+// WebIDL interface methods.
+
+already_AddRefed<Promise>
+SyncManager::Register(const nsAString& aTag, ErrorResult& aRv)
+{
+ const SyncRegisterArgs args(mScope, (nsString(aTag)));
+ return ExecuteOp(SyncOpArgs(args), aRv);
+}
+
+already_AddRefed<Promise>
+SyncManager::GetTags(ErrorResult& aRv)
+{
+ const SyncGetTagsArgs args;
+ return ExecuteOp(SyncOpArgs(args), aRv);
+}
+
+NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(SyncManager, mGlobal)
+NS_IMPL_CYCLE_COLLECTING_ADDREF(SyncManager)
+NS_IMPL_CYCLE_COLLECTING_RELEASE(SyncManager)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(SyncManager)
+ NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
+ NS_INTERFACE_MAP_ENTRY(nsIIPCBackgroundChildCreateCallback)
+ NS_INTERFACE_MAP_ENTRY(nsIObserver)
+NS_INTERFACE_MAP_END
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/sync/SyncManager.h b/dom/sync/SyncManager.h
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManager.h
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SyncManager_h
+#define mozilla_dom_SyncManager_h
+
+#include "mozilla/dom/SyncIPCTypes.h"
+
+#include "nsIIPCBackgroundChildCreateCallback.h"
+#include "nsIObserver.h"
+#include "nsIPrincipal.h"
+#include "nsWrapperCache.h"
+
+#include "mozilla/AlreadyAddRefed.h"
+#include "mozilla/dom/BindingDeclarations.h"
+#include "mozilla/ErrorResult.h"
+
+#include "nsCOMPtr.h"
+#include "jsapi.h"
+
+class nsIGlobalObject;
+
+namespace mozilla {
+
+namespace ipc {
+ class PrincipalInfo;
+} // namespace ipc
+
+namespace dom {
+
+namespace workers {
+ class WorkerFeature;
+ class WorkerPrivate;
+} // namespace workers
+
+class Promise;
+class SyncManagerChild;
+class SyncOpRunnable;
+
+class SyncManager final : public nsIIPCBackgroundChildCreateCallback
+ , public nsIObserver
+ , public nsWrapperCache
+{
+ NS_DECL_NSIIPCBACKGROUNDCHILDCREATECALLBACK
+ NS_DECL_NSIOBSERVER
+
+public:
+ NS_DECL_CYCLE_COLLECTING_ISUPPORTS
+ NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_AMBIGUOUS(
+ SyncManager, nsIIPCBackgroundChildCreateCallback)
+
+ static already_AddRefed<SyncManager>
+ CreateOnMainThread(nsIGlobalObject* aGlobal,
+ nsIPrincipal* aPrincipal,
+ const nsAString& aScope,
+ ErrorResult& aRv);
+
+ static already_AddRefed<SyncManager>
+ CreateOnWorker(nsIGlobalObject* aGlobal,
+ workers::WorkerPrivate* aWorkerPrivate,
+ const nsAString& aScope);
+
+ uint64_t mInnerID;
+
+ // Binding methods.
+
+ nsIGlobalObject*
+ GetParentObject() const
+ {
+ return mGlobal;
+ }
+
+ JSObject*
+ WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
+
+ static bool PrefEnabled(JSContext* aCx, JSObject* aObj);
+
+ // WebIDL interface methods.
+
+ already_AddRefed<Promise>
+ Register(const nsAString& aTag, ErrorResult& aRv);
+
+ already_AddRefed<Promise>
+ GetTags(ErrorResult& aRv);
+
+ void Shutdown();
+private:
+ SyncManager(nsIGlobalObject* aGlobal,
+ const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
+ const nsAString& aScope);
+
+ ~SyncManager();
+
+ already_AddRefed<Promise>
+ ExecuteOp(const SyncOpArgs& aArgs, ErrorResult& aRv);
+
+ nsCOMPtr<nsIGlobalObject> mGlobal;
+
+ nsAutoPtr<workers::WorkerFeature> mWorkerFeature;
+
+ RefPtr<SyncManagerChild> mActor;
+
+ bool mShuttingDown;
+
+ UniquePtr<mozilla::ipc::PrincipalInfo> mPrincipalInfo;
+
+ nsString mScope;
+
+ nsTArray<RefPtr<SyncOpRunnable>> mPendingOperations;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SyncManager_h
diff --git a/dom/sync/SyncManagerChild.cpp b/dom/sync/SyncManagerChild.cpp
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManagerChild.cpp
@@ -0,0 +1,129 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SyncManagerChild.h"
+
+#include "mozilla/unused.h"
+#include "mozilla/ipc/PBackgroundChild.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+struct SyncManagerChild::PendingRequest final
+{
+ explicit PendingRequest(Promise* aPromise)
+ : mPromise(aPromise)
+ {}
+
+ RefPtr<Promise> mPromise;
+};
+
+SyncManagerChild::SyncManagerChild()
+ : mActorDestroyed(false)
+{
+}
+
+SyncManagerChild::~SyncManagerChild()
+{
+}
+
+void
+SyncManagerChild::ActorDestroy(ActorDestroyReason aWhy)
+{
+ mActorDestroyed = true;
+ mPendingRequests.Clear();
+}
+
+nsresult
+SyncManagerChild::StorePendingRequest(Promise* aPromise, nsID& aID)
+{
+ nsresult rv;
+ nsCOMPtr<nsIUUIDGenerator> uuidGenerator =
+ do_GetService("@mozilla.org/uuid-generator;1", &rv);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ nsID id;
+ rv = uuidGenerator->GenerateUUIDInPlace(&id);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ PendingRequest* request = new PendingRequest(aPromise);
+ mPendingRequests.Put(id, request);
+
+ aID = id;
+
+ return NS_OK;
+}
+
+Promise*
+SyncManagerChild::GetPendingRequest(const nsID& aID)
+{
+ PendingRequest* request = mPendingRequests.Get(aID);
+ if (!request) {
+ return nullptr;
+ }
+
+ RefPtr<Promise> promise = request->mPromise;
+
+ mPendingRequests.Remove(const_cast<nsID&>(aID));
+ return promise;
+}
+
+nsresult
+SyncManagerChild::ExecuteOp(Promise* aPromise, SyncOp* aOp)
+{
+ if (mActorDestroyed) {
+ return NS_OK;
+ }
+
+ nsID requestId;
+ nsresult rv = StorePendingRequest(aPromise, requestId);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ Unused << SendRequest(requestId, *aOp);
+
+ return NS_OK;
+}
+
+bool
+SyncManagerChild::RecvResponse(const nsID& aRequestId,
+ const SyncOpResponse& aResponse)
+{
+ Promise* p = GetPendingRequest(aRequestId);
+ if (!p) {
+ return false;
+ }
+
+ switch(aResponse.type()) {
+ case SyncOpResponse::TSyncRegisterResponse:
+ {
+ p->MaybeResolve(true);
+ break;
+ }
+ case SyncOpResponse::TSyncGetTagsResponse:
+ {
+ p->MaybeResolve(aResponse.get_SyncGetTagsResponse().mTags());
+ break;
+ }
+ case SyncOpResponse::TSyncOpError:
+ {
+ p->MaybeReject(
+ static_cast<nsresult>(aResponse.get_SyncOpError().mCode()));
+ break;
+ }
+ default:
+ {
+ MOZ_CRASH("Unknown BackgroundSync response");
+ }
+ }
+ p->MaybeResolve(true);
+ return true;
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/sync/SyncManagerChild.h b/dom/sync/SyncManagerChild.h
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManagerChild.h
@@ -0,0 +1,62 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SyncManagerChild_h
+#define mozilla_dom_SyncManagerChild_h
+
+#include "SyncManager.h"
+
+#include "mozilla/dom/PSyncManagerChild.h"
+
+#include "nsID.h"
+#include "nsClassHashtable.h"
+
+namespace mozilla {
+
+namespace ipc {
+class BackgroundChildImpl;
+} // namespace ipc
+
+namespace dom {
+
+class SyncManager;
+
+class SyncManagerChild final : public PSyncManagerChild
+{
+ friend class mozilla::ipc::BackgroundChildImpl;
+
+public:
+ NS_INLINE_DECL_REFCOUNTING(SyncManagerChild)
+
+ bool IsActorDestroyed() const
+ {
+ return mActorDestroyed;
+ }
+
+ nsresult ExecuteOp(Promise* aPromise, SyncOp* aOp);
+
+ virtual bool RecvResponse(const nsID& aRequestId,
+ const SyncOpResponse& aResponse) override;
+
+private:
+ explicit SyncManagerChild();
+ ~SyncManagerChild();
+
+ virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+ nsresult StorePendingRequest(Promise* aPromise, nsID& aID);
+ Promise* GetPendingRequest(const nsID& aID);
+
+ bool mActorDestroyed;
+
+ struct PendingRequest;
+ nsClassHashtable<nsIDHashKey, PendingRequest> mPendingRequests;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SyncManagerChild_h
diff --git a/dom/sync/SyncManagerParent.cpp b/dom/sync/SyncManagerParent.cpp
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManagerParent.cpp
@@ -0,0 +1,91 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SyncManagerParent.h"
+#include "SyncService.h"
+
+#include "mozilla/unused.h"
+#include "mozilla/ipc/BackgroundParent.h"
+
+namespace mozilla {
+
+using namespace ipc;
+
+namespace dom {
+
+SyncManagerParent::SyncManagerParent()
+ : mService(SyncService::GetOrCreate())
+{
+ AssertIsOnBackgroundThread();
+ mService->RegisterActor(this);
+}
+
+SyncManagerParent::~SyncManagerParent()
+{
+ AssertIsOnBackgroundThread();
+}
+
+void SyncManagerParent::ActorDestroy(ActorDestroyReason aWhy)
+{
+ AssertIsOnBackgroundThread();
+
+ if (mService) {
+ mService->UnregisterActor(this);
+ }
+}
+
+bool SyncManagerParent::RecvRequest(const nsID& aRequestId,
+ const SyncOp& aOp)
+{
+ AssertIsOnBackgroundThread();
+
+ if (NS_WARN_IF(!mService)) {
+ return false;
+ }
+
+ switch(aOp.mArgs().type()) {
+ case SyncOpArgs::TSyncRegisterArgs:
+ {
+ // XXX this needs to be async
+ mService->Register(aOp.mPrincipal(),
+ aOp.mArgs().get_SyncRegisterArgs().mScope(),
+ aOp.mArgs().get_SyncRegisterArgs().mTag());
+ const SyncRegisterResponse response(true);
+ //const SyncOpError response(static_cast<uint32_t>(NS_ERROR_FAILURE));
+ Unused << SendResponse(aRequestId, response);
+ break;
+ }
+ case SyncOpArgs::TSyncGetTagsArgs:
+ {
+ //XXX Do GetTags.
+ nsTArray<nsString> tags;
+ const SyncGetTagsResponse response(tags);
+ Unused << SendResponse(aRequestId, response);
+ break;
+ }
+ default:
+ {
+ MOZ_CRASH("Unknown BackgroundSync request");
+ }
+ }
+ return true;
+}
+
+bool SyncManagerParent::RecvShutdown()
+{
+ AssertIsOnBackgroundThread();
+
+ if (NS_WARN_IF(!mService)) {
+ return false;
+ }
+
+ Unused << Send__delete__(this);
+
+ return true;
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/sync/SyncManagerParent.h b/dom/sync/SyncManagerParent.h
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncManagerParent.h
@@ -0,0 +1,48 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SyncManagerParent_h
+#define mozilla_dom_SyncManagerParent_h
+
+#include "mozilla/dom/PSyncManagerParent.h"
+#include "mozilla/dom/SyncIPCTypes.h"
+
+#include "nsID.h"
+
+namespace mozilla {
+
+namespace ipc {
+class BackgroundParentImpl;
+} // namespace ipc
+
+namespace dom {
+
+class SyncService;
+
+class SyncManagerParent final : public PSyncManagerParent
+{
+ friend class mozilla::ipc::BackgroundParentImpl;
+
+public:
+ virtual bool RecvRequest(const nsID& aRequestId,
+ const SyncOp& aOp) override;
+
+ virtual bool RecvShutdown() override;
+private:
+ SyncManagerParent();
+ ~SyncManagerParent();
+
+ virtual void ActorDestroy(ActorDestroyReason aWhy) override;
+
+ RefPtr<SyncService> mService;
+};
+
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SyncManagerParent_h
+
+
diff --git a/dom/sync/SyncRegistry.js b/dom/sync/SyncRegistry.js
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncRegistry.js
@@ -0,0 +1,42 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+'use strict'
+
+function debug(s) {
+ dump('DEBUG SyncRegistry: ' + s + '\n');
+}
+
+const { interfaces: Ci, utils: Cu } = Components;
+
+Cu.import('resource://gre/modules/XPCOMUtils.jsm');
+
+function SyncRegistry() {
+ debug("SyncRegistry created");
+}
+
+SyncStore.prototype = {
+ classDescription: "Background Sync registry",
+ classID: Components.ID("{c1200834-3ebb-45e2-81cf-986edeb107f6}"),
+ contractID: "@mozilla.org/dom/sync/registry;1",
+ QueryInterface: XPCOMUtils.generateQI([Ci.nsISyncStore, Ci.nsISupports]),
+
+ add() {
+ debug("add");
+ },
+
+ remove() {
+ debug("remove");
+ },
+
+ get() {
+ debug("get");
+ },
+
+ getAll() {
+ debug("getAll");
+ }
+};
+
+this.NSGetFactory = XPCOMUtils.generateNSGetFactory([SyncRegistry]);
diff --git a/dom/sync/SyncRegistry.manifest b/dom/sync/SyncRegistry.manifest
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncRegistry.manifest
@@ -0,0 +1,2 @@
+component {c1200834-3ebb-45e2-81cf-986edeb107f6} SyncRegistry.js
+contract @mozilla.org/dom/sync/registry;1 {c1200834-3ebb-45e2-81cf-986edeb107f6}
diff --git a/dom/sync/SyncService.cpp b/dom/sync/SyncService.cpp
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncService.cpp
@@ -0,0 +1,118 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "SyncService.h"
+#include "SyncManagerParent.h"
+
+namespace mozilla {
+
+namespace dom {
+
+namespace {
+ SyncService* sInstance = nullptr;
+} // namespace
+
+SyncService::SyncService()
+{
+ AssertIsOnBackgroundThread();
+
+ mRegistry = do_CreateInstance("@mozilla.org/dom/sync/registry;1");
+ MOZ_ASSERT(mRegistry);
+
+ // sInstance is a raw SyncService*.
+ MOZ_ASSERT(!sInstance);
+ sInstance = this;
+}
+
+SyncService::~SyncService()
+{
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(sInstance == this);
+ MOZ_ASSERT(mSyncManagerActors.Count() == 0);
+
+ sInstance = nullptr;
+}
+
+// static
+already_AddRefed<SyncService>
+SyncService::GetOrCreate()
+{
+ AssertIsOnBackgroundThread();
+
+ RefPtr<SyncService> instance = sInstance;
+ if (!instance) {
+ instance = new SyncService();
+ }
+ return instance.forget();
+}
+
+void
+SyncService::RegisterActor(SyncManagerParent* aParent)
+{
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aParent);
+ MOZ_ASSERT(!mSyncManagerActors.Contains(aParent));
+
+ mSyncManagerActors.PutEntry(aParent);
+}
+
+void
+SyncService::UnregisterActor(SyncManagerParent* aParent)
+{
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aParent);
+ MOZ_ASSERT(mSyncManagerActors.Contains(aParent));
+
+ mSyncManagerActors.RemoveEntry(aParent);
+}
+
+void
+SyncService::RegisterActor(workers::ServiceWorkerManagerParent* aParent)
+{
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aParent);
+ MOZ_ASSERT(!mServiceWorkerManagerActors.Contains(aParent));
+
+ mServiceWorkerManagerActors.PutEntry(aParent);
+}
+
+void
+SyncService::UnregisterActor(workers::ServiceWorkerManagerParent* aParent)
+{
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aParent);
+ MOZ_ASSERT(mServiceWorkerManagerActors.Contains(aParent));
+
+ mServiceWorkerManagerActors.RemoveEntry(aParent);
+}
+
+bool
+SyncService::Register(const PrincipalInfo& aPrincipal,
+ const nsString& aScope,
+ const nsString& aTag)
+{
+ // XXX implement me.
+
+ //XXX REMOVE ME - Sync event test.
+ for (auto iter = mServiceWorkerManagerActors.Iter(); !iter.Done(); iter.Next()) {
+ RefPtr<ServiceWorkerManagerParent> parent = iter.Get()->GetKey();
+ MOZ_ASSERT(parent);
+ Unused << parent->SendNotifySyncEvent(aPrincipal, aScope, aTag, false);
+ }
+
+ return true;
+}
+
+void
+SyncService::GetTags(const PrincipalInfo& aPrincipal,
+ const nsString& aScope,
+ nsTArray<nsString>& aTags)
+{
+ // XXX implement me.
+}
+
+} // namespace dom
+} // namespace mozilla
diff --git a/dom/sync/SyncService.h b/dom/sync/SyncService.h
new file mode 100644
--- /dev/null
+++ b/dom/sync/SyncService.h
@@ -0,0 +1,58 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#ifndef mozilla_dom_SyncService_h
+#define mozilla_dom_SyncService_h
+
+#include "nsISupportsImpl.h"
+#include "nsISyncRegistry.h"
+#include "nsHashKeys.h"
+#include "nsTHashtable.h"
+#include "ServiceWorkerManagerParent.h"
+
+namespace mozilla {
+namespace dom {
+
+namespace workers {
+class ServiceWorkerManagerParent;
+} // namespace workers
+
+class SyncManagerParent;
+
+class SyncService final
+{
+public:
+ NS_INLINE_DECL_REFCOUNTING(SyncService)
+
+ static already_AddRefed<SyncService> GetOrCreate();
+
+ void RegisterActor(SyncManagerParent* aParent);
+ void UnregisterActor(SyncManagerParent* aParent);
+
+ void RegisterActor(workers::ServiceWorkerManagerParent* aParent);
+ void UnregisterActor(workers::ServiceWorkerManagerParent* aParent);
+
+ bool Register(const PrincipalInfo& aPrincipal,
+ const nsString& aScope,
+ const nsString& aTag);
+ void GetTags(const PrincipalInfo& aPrincipal,
+ const nsString& aScope,
+ nsTArray<nsString>& aTags);
+
+private:
+ SyncService();
+ ~SyncService();
+
+ nsTHashtable<nsPtrHashKey<SyncManagerParent>> mSyncManagerActors;
+ nsTHashtable<nsPtrHashKey<workers::ServiceWorkerManagerParent>>
+ mServiceWorkerManagerActors;
+};
+
+ nsCOMPtr<nsISyncRegistry> mRegistry;
+} // namespace dom
+} // namespace mozilla
+
+#endif // mozilla_dom_SyncService_h
diff --git a/dom/sync/moz.build b/dom/sync/moz.build
new file mode 100644
--- /dev/null
+++ b/dom/sync/moz.build
@@ -0,0 +1,39 @@
+# vim: set filetype=python:
+# This Source Code Form is subject to the terms of the Mozilla Public
+# License, v. 2.0. If a copy of the MPL was not distributed with this
+# file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+EXPORTS.mozilla.dom += [
+ 'SyncManager.h'
+]
+
+UNIFIED_SOURCES += [
+ 'SyncManager.cpp',
+ 'SyncManagerChild.cpp',
+ 'SyncManagerParent.cpp',
+ 'SyncService.cpp'
+]
+
+IPDL_SOURCES += [
+ 'PSyncManager.ipdl',
+ 'SyncIPCTypes.ipdlh'
+]
+
+LOCAL_INCLUDES += [
+ '/dom/workers'
+]
+
+XPIDL_SOURCES += [
+ 'nsISyncRegistry.idl'
+]
+
+XPIDL_MODULE = 'dom_sync'
+
+EXTRA_COMPONENTS += [
+ 'SyncRegistry.js',
+ 'SyncRegistry.manifest'
+]
+
+include('/ipc/chromium/chromium-config.mozbuild')
+
+FINAL_LIBRARY = 'xul'
diff --git a/dom/sync/nsISyncRegistry.idl b/dom/sync/nsISyncRegistry.idl
new file mode 100644
--- /dev/null
+++ b/dom/sync/nsISyncRegistry.idl
@@ -0,0 +1,14 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+#include "nsISupports.idl"
+
+[scriptable, uuid(dfcc3fb2-f40d-44f9-85ea-1127be79fbe9)]
+interface nsISyncRegistry : nsISupports
+{
+ void add();
+ void remove();
+ void get();
+ void getAll();
+};
diff --git a/dom/tests/mochitest/general/test_interfaces.html b/dom/tests/mochitest/general/test_interfaces.html
--- a/dom/tests/mochitest/general/test_interfaces.html
+++ b/dom/tests/mochitest/general/test_interfaces.html
@@ -1301,16 +1301,18 @@ var interfaceNamesInGlobalScope =
"SVGUseElement",
// IMPORTANT: Do not change this list without review from a DOM peer!
"SVGViewElement",
// IMPORTANT: Do not change this list without review from a DOM peer!
"SVGZoomAndPan",
// IMPORTANT: Do not change this list without review from a DOM peer!
"SVGZoomEvent",
// IMPORTANT: Do not change this list without review from a DOM peer!
+ {name: "SyncManager", b2g: true},
+// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncManager", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncApp", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "RequestSyncTask", b2g: true, permission: ["requestsync-manager"] },
// IMPORTANT: Do not change this list without review from a DOM peer!
{name: "Telephony", b2g: true},
// IMPORTANT: Do not change this list without review from a DOM peer!
diff --git a/dom/webidl/ServiceWorkerRegistration.webidl b/dom/webidl/ServiceWorkerRegistration.webidl
--- a/dom/webidl/ServiceWorkerRegistration.webidl
+++ b/dom/webidl/ServiceWorkerRegistration.webidl
@@ -27,9 +27,11 @@ interface ServiceWorkerRegistration : Ev
attribute EventHandler onupdatefound;
};
partial interface ServiceWorkerRegistration {
#ifndef MOZ_SIMPLEPUSH
[Throws, Exposed=(Window,Worker), Func="nsContentUtils::PushEnabled"]
readonly attribute PushManager pushManager;
#endif
+ [Throws, Exposed=(Window,Worker)]
+ readonly attribute SyncManager sync;
};
diff --git a/dom/webidl/SyncEvent.webidl b/dom/webidl/SyncEvent.webidl
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SyncEvent.webidl
@@ -0,0 +1,20 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/.
+ *
+ * The origin of this IDL file is
+ * https://wicg.github.io/BackgroundSync/spec/
+ */
+
+[Constructor(DOMString type, optional SyncEventInit eventInitDict),
+ Exposed=ServiceWorker]
+interface SyncEvent : ExtendableEvent {
+ readonly attribute DOMString tag;
+ readonly attribute boolean lastChance;
+};
+
+dictionary SyncEventInit : ExtendableEventInit {
+ required DOMString tag;
+ boolean lastChance = false;
+};
diff --git a/dom/webidl/SyncManager.webidl b/dom/webidl/SyncManager.webidl
new file mode 100644
--- /dev/null
+++ b/dom/webidl/SyncManager.webidl
@@ -0,0 +1,17 @@
+/* -*- Mode: IDL; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* This Source Code Form is subject to the terms of the Mozilla Public
+* License, v. 2.0. If a copy of the MPL was not distributed with this file,
+* You can obtain one at http://mozilla.org/MPL/2.0/.
+*
+* The origin of this IDL file is
+* https://wicg.github.io/BackgroundSync/spec/
+*/
+
+[Exposed=(Window,Worker),
+ Func="mozilla::dom::SyncManager::PrefEnabled"]
+interface SyncManager {
+ [Throws]
+ Promise<void> register(DOMString tag);
+ [Throws]
+ Promise<sequence<DOMString>> getTags();
+};
diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build
--- a/dom/webidl/moz.build
+++ b/dom/webidl/moz.build
@@ -534,16 +534,18 @@ WEBIDL_FILES = [
'SVGTransformList.webidl',
'SVGTSpanElement.webidl',
'SVGUnitTypes.webidl',
'SVGURIReference.webidl',
'SVGUseElement.webidl',
'SVGViewElement.webidl',
'SVGZoomAndPan.webidl',
'SVGZoomEvent.webidl',
+ 'SyncEvent.webidl',
+ 'SyncManager.webidl',
'SystemUpdate.webidl',
'TCPServerSocket.webidl',
'TCPServerSocketEvent.webidl',
'TCPSocket.webidl',
'TCPSocketErrorEvent.webidl',
'TCPSocketEvent.webidl',
'Telephony.webidl',
'TelephonyCall.webidl',
diff --git a/dom/workers/PServiceWorkerManager.ipdl b/dom/workers/PServiceWorkerManager.ipdl
--- a/dom/workers/PServiceWorkerManager.ipdl
+++ b/dom/workers/PServiceWorkerManager.ipdl
@@ -28,18 +28,22 @@ parent:
async PropagateRemove(nsCString host);
async PropagateRemoveAll();
async Shutdown();
child:
async NotifyRegister(ServiceWorkerRegistrationData data);
- async NotifySoftUpdate(PrincipalOriginAttributes originAttributes, nsString scope);
+ async NotifySoftUpdate(PrincipalOriginAttributes originAttributes,
+ nsString scope);
async NotifyUnregister(PrincipalInfo principalInfo, nsString scope);
async NotifyRemove(nsCString host);
async NotifyRemoveAll();
-
+ async NotifySyncEvent(PrincipalInfo principalInfo,
+ nsString scope,
+ nsString tag,
+ bool lastChance);
async __delete__();
};
} // namespace dom
} // namespace mozilla
diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp
--- a/dom/workers/ServiceWorkerEvents.cpp
+++ b/dom/workers/ServiceWorkerEvents.cpp
@@ -979,17 +979,17 @@ ExtractBytesFromData(const OwningArrayBu
const ArrayBuffer& buffer = aDataInit.GetAsArrayBuffer();
return ExtractBytesFromArrayBuffer(buffer, aBytes);
} else if (aDataInit.IsUSVString()) {
return ExtractBytesFromUSVString(aDataInit.GetAsUSVString(), aBytes);
}
NS_NOTREACHED("Unexpected push message data");
return NS_ERROR_FAILURE;
}
-}
+} // namespace
PushMessageData::PushMessageData(nsISupports* aOwner,
const nsTArray<uint8_t>& aBytes)
: mOwner(aOwner), mBytes(aBytes) {}
PushMessageData::~PushMessageData()
{
}
@@ -1110,16 +1110,50 @@ NS_IMPL_RELEASE_INHERITED(PushEvent, Ext
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(PushEvent)
NS_INTERFACE_MAP_END_INHERITING(ExtendableEvent)
NS_IMPL_CYCLE_COLLECTION_INHERITED(PushEvent, ExtendableEvent, mData)
#endif /* ! MOZ_SIMPLEPUSH */
+// Background Sync
+
+SyncEvent::SyncEvent(EventTarget* aOwner)
+ : ExtendableEvent(aOwner)
+{
+}
+
+already_AddRefed<SyncEvent>
+SyncEvent::Constructor(mozilla::dom::EventTarget* aOwner,
+ const nsAString& aType,
+ const SyncEventInit& aOptions,
+ ErrorResult& aRv)
+{
+ RefPtr<SyncEvent> e = new SyncEvent(aOwner);
+ bool trusted = e->Init(aOwner);
+ e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable);
+ e->SetTrusted(trusted);
+ e->mTag = aOptions.mTag;
+ e->mLastChance = aOptions.mLastChance;
+ return e.forget();
+}
+
+NS_IMPL_ADDREF_INHERITED(SyncEvent, ExtendableEvent)
+NS_IMPL_RELEASE_INHERITED(SyncEvent, ExtendableEvent)
+
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(SyncEvent)
+NS_INTERFACE_MAP_END_INHERITING(ExtendableEvent)
+
+NS_IMPL_CYCLE_COLLECTION_CLASS(SyncEvent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(SyncEvent, ExtendableEvent)
+NS_IMPL_CYCLE_COLLECTION_UNLINK_END
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(SyncEvent, ExtendableEvent)
+NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
+
ExtendableMessageEvent::ExtendableMessageEvent(EventTarget* aOwner)
: ExtendableEvent(aOwner)
, mData(JS::UndefinedValue())
{
mozilla::HoldJSObjects(this);
}
ExtendableMessageEvent::~ExtendableMessageEvent()
diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h
--- a/dom/workers/ServiceWorkerEvents.h
+++ b/dom/workers/ServiceWorkerEvents.h
@@ -16,16 +16,18 @@
#include "mozilla/dom/workers/bindings/ServiceWorker.h"
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushEventBinding.h"
#include "mozilla/dom/PushMessageDataBinding.h"
#include "mozilla/dom/File.h"
#endif
+#include "mozilla/dom/SyncEventBinding.h"
+
#include "nsProxyRelease.h"
#include "nsContentUtils.h"
class nsIInterceptedChannel;
namespace mozilla {
namespace dom {
class Blob;
@@ -317,11 +319,60 @@ public:
void SetPorts(MessagePortList* aPorts);
void SetSource(ServiceWorkerClient* aClient);
void SetSource(ServiceWorker* aServiceWorker);
};
+class SyncEvent final : public ExtendableEvent
+{
+ nsString mTag;
+ bool mLastChance;
+
+protected:
+ explicit SyncEvent(mozilla::dom::EventTarget* aOwner);
+ ~SyncEvent() {}
+
+public:
+ NS_DECL_ISUPPORTS_INHERITED
+ NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(SyncEvent, ExtendableEvent)
+ NS_FORWARD_TO_EVENT
+
+ virtual JSObject* WrapObjectInternal(JSContext* aCx,
+ JS::Handle<JSObject*> aGivenProto) override
+ {
+ return mozilla::dom::SyncEventBinding_workers::Wrap(aCx, this, aGivenProto);
+ }
+
+ static already_AddRefed<SyncEvent>
+ Constructor(mozilla::dom::EventTarget* aOwner,
+ const nsAString& aType,
+ const SyncEventInit& aOptions,
+ ErrorResult& aRv);
+
+ static already_AddRefed<SyncEvent>
+ Constructor(const GlobalObject& aGlobal,
+ const nsAString& aType,
+ const SyncEventInit& aOptions,
+ ErrorResult& aRv)
+ {
+ nsCOMPtr<EventTarget> owner = do_QueryInterface(aGlobal.GetAsSupports());
+ return Constructor(owner, aType, aOptions, aRv);
+ }
+
+ void
+ GetTag(nsAString& aTag)
+ {
+ aTag = mTag;
+ }
+
+ bool
+ LastChance()
+ {
+ return mLastChance;
+ }
+};
+
END_WORKERS_NAMESPACE
#endif /* mozilla_dom_workers_serviceworkerevents_h__ */
diff --git a/dom/workers/ServiceWorkerManager.cpp b/dom/workers/ServiceWorkerManager.cpp
--- a/dom/workers/ServiceWorkerManager.cpp
+++ b/dom/workers/ServiceWorkerManager.cpp
@@ -5200,9 +5200,35 @@ ServiceWorkerInfo::~ServiceWorkerInfo()
static uint64_t gServiceWorkerInfoCurrentID = 0;
uint64_t
ServiceWorkerInfo::GetNextID() const
{
return ++gServiceWorkerInfoCurrentID;
}
+// Background Sync
+
+NS_IMETHODIMP
+ServiceWorkerManager::SendSyncEvent(const nsACString& aOriginAttributes,
+ const nsACString& aScope,
+ const nsAString& aTag,
+ const bool aLastChance)
+{
+ PrincipalOriginAttributes attrs;
+ if (!attrs.PopulateFromSuffix(aOriginAttributes)) {
+ return NS_ERROR_INVALID_ARG;
+ }
+
+ ServiceWorkerInfo* serviceWorker =
+ GetActiveWorkerInfoForScope(attrs, aScope);
+ if (NS_WARN_IF(!serviceWorker)) {
+ return NS_ERROR_FAILURE;
+ }
+
+ RefPtr<ServiceWorkerRegistrationInfo> registration =
+ GetRegistration(serviceWorker->GetPrincipal(), aScope);
+
+ return serviceWorker->WorkerPrivate()->SendSyncEvent(aTag, aLastChance,
+ registration);
+}
+
END_WORKERS_NAMESPACE
diff --git a/dom/workers/ServiceWorkerManagerChild.cpp b/dom/workers/ServiceWorkerManagerChild.cpp
--- a/dom/workers/ServiceWorkerManagerChild.cpp
+++ b/dom/workers/ServiceWorkerManagerChild.cpp
@@ -90,11 +90,41 @@ ServiceWorkerManagerChild::RecvNotifyRem
RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
MOZ_ASSERT(swm);
swm->RemoveAll();
return true;
}
+bool
+ServiceWorkerManagerChild::RecvNotifySyncEvent(const PrincipalInfo& aPrincipalInfo,
+ const nsString& aScope,
+ const nsString& aTag,
+ const bool& aLastChance)
+{
+ if (mShuttingDown) {
+ return true;
+ }
+
+ nsCOMPtr<nsIPrincipal> principal = PrincipalInfoToPrincipal(aPrincipalInfo);
+ if (NS_WARN_IF(!principal)) {
+ return true;
+ }
+
+ nsAutoCString originSuffix;
+ nsresult rv = principal->GetOriginSuffix(originSuffix);
+ if (NS_WARN_IF(NS_FAILED(rv))) {
+ return true;
+ }
+
+ RefPtr<ServiceWorkerManager> swm = ServiceWorkerManager::GetInstance();
+ MOZ_ASSERT(swm);
+
+ swm->SendSyncEvent(originSuffix,
+ NS_ConvertUTF16toUTF8(aScope),
+ aTag, aLastChance);
+ return true;
+}
+
} // namespace workers
} // namespace dom
} // namespace mozilla
diff --git a/dom/workers/ServiceWorkerManagerChild.h b/dom/workers/ServiceWorkerManagerChild.h
--- a/dom/workers/ServiceWorkerManagerChild.h
+++ b/dom/workers/ServiceWorkerManagerChild.h
@@ -41,16 +41,21 @@ public:
virtual bool RecvNotifyUnregister(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope) override;
virtual bool RecvNotifyRemove(const nsCString& aHost) override;
virtual bool RecvNotifyRemoveAll() override;
+ virtual bool RecvNotifySyncEvent(const PrincipalInfo& aPrincipalInfo,
+ const nsString& aScope,
+ const nsString& aTag,
+ const bool& aLastChance) override;
+
private:
ServiceWorkerManagerChild()
: mShuttingDown(false)
{}
~ServiceWorkerManagerChild() {}
bool mShuttingDown;
diff --git a/dom/workers/ServiceWorkerManagerParent.cpp b/dom/workers/ServiceWorkerManagerParent.cpp
--- a/dom/workers/ServiceWorkerManagerParent.cpp
+++ b/dom/workers/ServiceWorkerManagerParent.cpp
@@ -1,16 +1,17 @@
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "ServiceWorkerManagerParent.h"
#include "ServiceWorkerManagerService.h"
+#include "SyncService.h"
#include "mozilla/AppProcessChecker.h"
#include "mozilla/dom/ContentParent.h"
#include "mozilla/dom/ServiceWorkerRegistrar.h"
#include "mozilla/ipc/BackgroundParent.h"
#include "mozilla/ipc/BackgroundUtils.h"
#include "mozilla/unused.h"
#include "nsThreadUtils.h"
@@ -143,22 +144,24 @@ private:
PrincipalInfo mPrincipalInfo;
RefPtr<nsRunnable> mCallback;
nsCOMPtr<nsIThread> mBackgroundThread;
};
} // namespace
ServiceWorkerManagerParent::ServiceWorkerManagerParent()
- : mService(ServiceWorkerManagerService::GetOrCreate())
+ : mServiceWorkerService(ServiceWorkerManagerService::GetOrCreate())
+ , mSyncService(SyncService::GetOrCreate())
, mID(++sServiceWorkerManagerParentID)
, mActorDestroyed(false)
{
AssertIsOnBackgroundThread();
- mService->RegisterActor(this);
+ mServiceWorkerService->RegisterActor(this);
+ mSyncService->RegisterActor(this);
}
ServiceWorkerManagerParent::~ServiceWorkerManagerParent()
{
AssertIsOnBackgroundThread();
}
already_AddRefed<ContentParent>
@@ -243,89 +246,89 @@ ServiceWorkerManagerParent::RecvUnregist
}
bool
ServiceWorkerManagerParent::RecvPropagateSoftUpdate(const PrincipalOriginAttributes& aOriginAttributes,
const nsString& aScope)
{
AssertIsOnBackgroundThread();
- if (NS_WARN_IF(!mService)) {
+ if (NS_WARN_IF(!mServiceWorkerService)) {
return false;
}
- mService->PropagateSoftUpdate(mID, aOriginAttributes, aScope);
+ mServiceWorkerService->PropagateSoftUpdate(mID, aOriginAttributes, aScope);
return true;
}
bool
ServiceWorkerManagerParent::RecvPropagateUnregister(const PrincipalInfo& aPrincipalInfo,
const nsString& aScope)
{
AssertIsOnBackgroundThread();
- if (NS_WARN_IF(!mService)) {
+ if (NS_WARN_IF(!mServiceWorkerService)) {
return false;
}
- mService->PropagateUnregister(mID, aPrincipalInfo, aScope);
+ mServiceWorkerService->PropagateUnregister(mID, aPrincipalInfo, aScope);
return true;
}
bool
ServiceWorkerManagerParent::RecvPropagateRemove(const nsCString& aHost)
{
AssertIsOnBackgroundThread();
- if (NS_WARN_IF(!mService)) {
+ if (NS_WARN_IF(!mServiceWorkerService)) {
return false;
}
- mService->PropagateRemove(mID, aHost);
+ mServiceWorkerService->PropagateRemove(mID, aHost);
return true;
}
bool
ServiceWorkerManagerParent::RecvPropagateRemoveAll()
{
AssertIsOnBackgroundThread();
- if (NS_WARN_IF(!mService)) {
+ if (NS_WARN_IF(!mServiceWorkerService)) {
return false;
}
- mService->PropagateRemoveAll(mID);
+ mServiceWorkerService->PropagateRemoveAll(mID);
return true;
}
bool
ServiceWorkerManagerParent::RecvShutdown()
{
AssertIsOnBackgroundThread();
- if (NS_WARN_IF(!mService)) {
+ if (NS_WARN_IF(!mServiceWorkerService)) {
return false;
}
- mService->UnregisterActor(this);
- mService = nullptr;
+ mServiceWorkerService->UnregisterActor(this);
+ mServiceWorkerService = nullptr;
Unused << Send__delete__(this);
return true;
}
void
ServiceWorkerManagerParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsOnBackgroundThread();
mActorDestroyed = true;
- if (mService) {
- // This object is about to be released and with it, also mService will be
+ if (mServiceWorkerService) {
+ // This object is about to be released and with it, also mServiceWorkerService will be
// released too.
- mService->UnregisterActor(this);
+ mServiceWorkerService->UnregisterActor(this);
}
}
} // namespace workers
} // namespace dom
} // namespace mozilla
diff --git a/dom/workers/ServiceWorkerManagerParent.h b/dom/workers/ServiceWorkerManagerParent.h
--- a/dom/workers/ServiceWorkerManagerParent.h
+++ b/dom/workers/ServiceWorkerManagerParent.h
@@ -13,16 +13,19 @@ namespace mozilla {
class PrincipalOriginAttributes;
namespace ipc {
class BackgroundParentImpl;
} // namespace ipc
namespace dom {
+
+class SyncService;
+
namespace workers {
class ServiceWorkerManagerService;
class ServiceWorkerManagerParent final : public PServiceWorkerManagerParent
{
friend class mozilla::ipc::BackgroundParentImpl;
@@ -59,17 +62,18 @@ private:
virtual bool RecvPropagateRemove(const nsCString& aHost) override;
virtual bool RecvPropagateRemoveAll() override;
virtual bool RecvShutdown() override;
virtual void ActorDestroy(ActorDestroyReason aWhy) override;
- RefPtr<ServiceWorkerManagerService> mService;
+ RefPtr<ServiceWorkerManagerService> mServiceWorkerService;
+ RefPtr<SyncService> mSyncService;
// We use this ID in the Service in order to avoid the sending of messages to
// ourself.
uint64_t mID;
bool mActorDestroyed;
};
diff --git a/dom/workers/ServiceWorkerPrivate.cpp b/dom/workers/ServiceWorkerPrivate.cpp
--- a/dom/workers/ServiceWorkerPrivate.cpp
+++ b/dom/workers/ServiceWorkerPrivate.cpp
@@ -56,17 +56,17 @@ private:
RefPtr<ServiceWorkerPrivate> mPrivate;
};
NS_IMPL_ISUPPORTS0(KeepAliveToken)
ServiceWorkerPrivate::ServiceWorkerPrivate(ServiceWorkerInfo* aInfo)
: mInfo(aInfo)
- , mIsPushWorker(false)
+ , mIsPushOrSyncWorker(false)
, mDebuggerCount(0)
, mTokenCount(0)
{
AssertIsOnMainThread();
MOZ_ASSERT(aInfo);
mIdleWorkerTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
MOZ_ASSERT(mIdleWorkerTimer);
@@ -478,18 +478,18 @@ public:
{
MOZ_ASSERT(GetCurrentThreadWorkerPrivate() == mWorkerPrivate);
mWorkerPrivate->AssertIsOnWorkerThread();
ReportResult(aCx, false);
// Note, all WaitUntil() rejections are reported to client consoles
// by the WaitUntilHandler in ServiceWorkerEvents. This ensures that
- // errors in non-lifecycle events like FetchEvent and PushEvent are
- // reported properly.
+ // errors in non-lifecycle events like FetchEvent, PushEvent or SyncEvent
+ // are reported properly.
}
};
NS_IMPL_ISUPPORTS0(LifeCycleEventWatcher)
bool
LifecycleEventWorkerRunnable::DispatchLifecycleEvent(JSContext* aCx,
WorkerPrivate* aWorkerPrivate)
@@ -1357,16 +1357,103 @@ ServiceWorkerPrivate::SendFetchEvent(nsI
jsapi.Init();
if (NS_WARN_IF(!r->Dispatch(jsapi.cx()))) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
+namespace {
+class SendSyncEventRunnable final : public ExtendableFunctionalEventWorkerRunnable
+{
+ nsString mTag;
+ bool mLastChance;
+
+public:
+ SendSyncEventRunnable(WorkerPrivate* aWorkerPrivate,
+ KeepAliveToken* aKeepAliveToken,
+ const nsAString& aTag,
+ const bool aLastChance,
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> aRegistration)
+ : ExtendableFunctionalEventWorkerRunnable(
+ aWorkerPrivate, aKeepAliveToken, aRegistration)
+ , mTag(aTag)
+ , mLastChance(aLastChance)
+ {
+ AssertIsOnMainThread();
+ MOZ_ASSERT(aWorkerPrivate);
+ MOZ_ASSERT(aWorkerPrivate->IsServiceWorker());
+ }
+
+ bool
+ WorkerRun(JSContext* aCx, WorkerPrivate* aWorkerPrivate) override
+ {
+ MOZ_ASSERT(aWorkerPrivate);
+ GlobalObject globalObj(aCx, aWorkerPrivate->GlobalScope()->GetWrapper());
+
+ SyncEventInit sei;
+ sei.mTag = mTag;
+ sei.mLastChance = mLastChance;
+ sei.mBubbles = false;
+ sei.mCancelable = false;
+
+ ErrorResult result;
+ RefPtr<SyncEvent> event =
+ SyncEvent::Constructor(globalObj, NS_LITERAL_STRING("sync"), sei, result);
+ if (NS_WARN_IF(result.Failed())) {
+ result.SuppressException();
+ return false;
+ }
+ event->SetTrusted(true);
+
+ DispatchExtendableEventOnWorkerScope(aCx, aWorkerPrivate->GlobalScope(),
+ event, nullptr);
+
+ return true;
+ }
+};
+} // anonymous namespace
+
+nsresult
+ServiceWorkerPrivate::SendSyncEvent(const nsAString& aTag,
+ const bool aLastChance,
+ ServiceWorkerRegistrationInfo* aRegistration)
+{
+ nsresult rv = SpawnWorkerIfNeeded(SyncEvent, nullptr);
+ NS_ENSURE_SUCCESS(rv, rv);
+
+ MOZ_ASSERT(mKeepAliveToken);
+
+ nsMainThreadPtrHandle<ServiceWorkerRegistrationInfo> regInfo(
+ new nsMainThreadPtrHolder<ServiceWorkerRegistrationInfo>(aRegistration, false));
+
+
+ RefPtr<WorkerRunnable> runnable = new SendSyncEventRunnable(mWorkerPrivate,
+ mKeepAliveToken,
+ aTag,
+ aLastChance,
+ regInfo);
+
+ if (mInfo->State() == ServiceWorkerState::Activating) {
+ mPendingFunctionalEvents.AppendElement(runnable.forget());
+ return NS_OK;
+ }
+
+ MOZ_ASSERT(mInfo->State() == ServiceWorkerState::Activated);
+
+ AutoJSAPI jsapi;
+ jsapi.Init();
+ if (NS_WARN_IF(!runnable->Dispatch(jsapi.cx()))) {
+ return NS_ERROR_FAILURE;
+ }
+
+ return NS_OK;
+}
+
nsresult
ServiceWorkerPrivate::SpawnWorkerIfNeeded(WakeUpReason aWhy,
nsIRunnable* aLoadFailedRunnable,
nsILoadGroup* aLoadGroup)
{
AssertIsOnMainThread();
// XXXcatalinb: We need to have a separate load group that's linked to
@@ -1451,17 +1538,17 @@ ServiceWorkerPrivate::SpawnWorkerIfNeede
mWorkerPrivate = WorkerPrivate::Constructor(jsapi.cx(),
scriptSpec,
false, WorkerTypeService,
mInfo->Scope(), &info, error);
if (NS_WARN_IF(error.Failed())) {
return error.StealNSResult();
}
- mIsPushWorker = false;
+ mIsPushOrSyncWorker = false;
RenewKeepAliveToken(aWhy);
return NS_OK;
}
void
ServiceWorkerPrivate::StoreISupports(nsISupports* aSupports)
{
@@ -1518,17 +1605,17 @@ ServiceWorkerPrivate::NoteDeadServiceWor
mInfo = nullptr;
TerminateWorker();
}
void
ServiceWorkerPrivate::NoteStoppedControllingDocuments()
{
AssertIsOnMainThread();
- if (mIsPushWorker || mDebuggerCount) {
+ if (mIsPushOrSyncWorker || mDebuggerCount) {
return;
}
TerminateWorker();
}
void
ServiceWorkerPrivate::Activated()
@@ -1658,18 +1745,19 @@ ServiceWorkerPrivate::TerminateWorkerCal
}
void
ServiceWorkerPrivate::RenewKeepAliveToken(WakeUpReason aWhy)
{
// We should have an active worker if we're renewing the keep alive token.
MOZ_ASSERT(mWorkerPrivate);
- if (aWhy == PushEvent || aWhy == PushSubscriptionChangeEvent) {
- mIsPushWorker = true;
+ if (aWhy == PushEvent || aWhy == PushSubscriptionChangeEvent ||
+ aWhy == SyncEvent) {
+ mIsPushOrSyncWorker = true;
}
// If there is at least one debugger attached to the worker, the idle worker
// timeout was canceled when the first debugger attached to the worker. It
// should not be reset until the last debugger detaches from the worker.
if (!mDebuggerCount) {
ResetIdleTimeout();
}
diff --git a/dom/workers/ServiceWorkerPrivate.h b/dom/workers/ServiceWorkerPrivate.h
--- a/dom/workers/ServiceWorkerPrivate.h
+++ b/dom/workers/ServiceWorkerPrivate.h
@@ -101,16 +101,21 @@ public:
const nsAString& aScope);
nsresult
SendFetchEvent(nsIInterceptedChannel* aChannel,
nsILoadGroup* aLoadGroup,
const nsAString& aDocumentId,
bool aIsReload);
+ nsresult
+ SendSyncEvent(const nsAString& aTag,
+ const bool aLastChance,
+ ServiceWorkerRegistrationInfo* aRegistration);
+
void
StoreISupports(nsISupports* aSupports);
void
RemoveISupports(nsISupports* aSupports);
// This will terminate the current running worker thread and drop the
// workerPrivate reference.
@@ -141,17 +146,18 @@ public:
private:
enum WakeUpReason {
FetchEvent = 0,
PushEvent,
PushSubscriptionChangeEvent,
MessageEvent,
NotificationClickEvent,
LifeCycleEvent,
- AttachEvent
+ AttachEvent,
+ SyncEvent
};
// Timer callbacks
static void
NoteIdleWorkerCallback(nsITimer* aTimer, void* aPrivate);
static void
TerminateWorkerCallback(nsITimer* aTimer, void *aPrivate);
@@ -184,20 +190,20 @@ private:
// The WorkerPrivate object can only be closed by this class or by the
// RuntimeService class if gecko is shutting down. Closing the worker
// multiple times is OK, since the second attempt will be a no-op.
RefPtr<WorkerPrivate> mWorkerPrivate;
nsCOMPtr<nsITimer> mIdleWorkerTimer;
- // We keep track if this worker received any push events since it was last
- // woken up. The flag is reset to false every time a new WorkerPrivate
- // is created.
- bool mIsPushWorker;
+ // We keep track if this worker received any push or sync events since it
+ // was last woken up. The flag is reset to false every time a new
+ // WorkerPrivate is created.
+ bool mIsPushOrSyncWorker;
// We keep a token for |dom.serviceWorkers.idle_timeout| seconds to give the
// worker a grace period after each event.
RefPtr<KeepAliveToken> mKeepAliveToken;
uint64_t mDebuggerCount;
uint64_t mTokenCount;
diff --git a/dom/workers/ServiceWorkerRegistration.cpp b/dom/workers/ServiceWorkerRegistration.cpp
--- a/dom/workers/ServiceWorkerRegistration.cpp
+++ b/dom/workers/ServiceWorkerRegistration.cpp
@@ -27,16 +27,19 @@
#include "Workers.h"
#include "WorkerScope.h"
#ifndef MOZ_SIMPLEPUSH
#include "mozilla/dom/PushManagerBinding.h"
#include "mozilla/dom/PushManager.h"
#endif
+#include "mozilla/dom/SyncManagerBinding.h"
+#include "mozilla/dom/SyncManager.h"
+
using namespace mozilla::dom::workers;
namespace mozilla {
namespace dom {
bool
ServiceWorkerRegistrationVisible(JSContext* aCx, JSObject* aObj)
{
@@ -86,20 +89,21 @@ ServiceWorkerRegistrationBase::ServiceWo
NS_IMPL_ADDREF_INHERITED(ServiceWorkerRegistrationMainThread, ServiceWorkerRegistrationBase)
NS_IMPL_RELEASE_INHERITED(ServiceWorkerRegistrationMainThread, ServiceWorkerRegistrationBase)
NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistrationMainThread)
NS_INTERFACE_MAP_END_INHERITING(ServiceWorkerRegistrationBase)
#ifndef MOZ_SIMPLEPUSH
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistrationMainThread, ServiceWorkerRegistrationBase,
- mPushManager,
+ mPushManager, mSyncManager,
mInstallingWorker, mWaitingWorker, mActiveWorker);
#else
NS_IMPL_CYCLE_COLLECTION_INHERITED(ServiceWorkerRegistrationMainThread, ServiceWorkerRegistrationBase,
+ mSyncManager,
mInstallingWorker, mWaitingWorker, mActiveWorker);
#endif
ServiceWorkerRegistrationMainThread::ServiceWorkerRegistrationMainThread(nsPIDOMWindowInner* aWindow,
const nsAString& aScope)
: ServiceWorkerRegistrationBase(aWindow, aScope)
, mListeningForEvents(false)
{
@@ -807,16 +811,48 @@ ServiceWorkerRegistrationMainThread::Get
}
RefPtr<PushManager> ret = mPushManager;
return ret.forget();
#endif /* ! MOZ_SIMPLEPUSH */
}
+SyncManager*
+ServiceWorkerRegistrationMainThread::GetSync(ErrorResult& aRv)
+{
+ AssertIsOnMainThread();
+
+ if (!mSyncManager) {
+ nsCOMPtr<nsIGlobalObject> globalObject = do_QueryInterface(GetOwner());
+
+ if (!globalObject) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ nsCOMPtr<nsIDocument> document = GetOwner()->GetExtantDoc();
+ if (!document) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ nsCOMPtr<nsIPrincipal> principal = document->NodePrincipal();
+ if (!principal) {
+ aRv.Throw(NS_ERROR_FAILURE);
+ return nullptr;
+ }
+
+ mSyncManager = SyncManager::CreateOnMainThread(globalObject, principal,
+ mScope, aRv);
+ }
+
+ return mSyncManager;
+}
+
////////////////////////////////////////////////////
// Worker Thread implementation
class WorkerListener final : public ServiceWorkerRegistrationListener
{
// Accessed on the main thread.
WorkerPrivate* mWorkerPrivate;
nsString mScope;
bool mListeningForEvents;
@@ -931,23 +967,25 @@ NS_INTERFACE_MAP_END_INHERITING(ServiceW
// Expanded macros since we need special behaviour to release the proxy.
NS_IMPL_CYCLE_COLLECTION_CLASS(ServiceWorkerRegistrationWorkerThread)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN_INHERITED(ServiceWorkerRegistrationWorkerThread,
ServiceWorkerRegistrationBase)
#ifndef MOZ_SIMPLEPUSH
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mPushManager)
#endif
+ NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mSyncManager)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN_INHERITED(ServiceWorkerRegistrationWorkerThread,
ServiceWorkerRegistrationBase)
#ifndef MOZ_SIMPLEPUSH
NS_IMPL_CYCLE_COLLECTION_UNLINK(mPushManager)
#endif
+ NS_IMPL_CYCLE_COLLECTION_UNLINK(mSyncManager)
tmp->ReleaseListener(RegistrationIsGoingAway);
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
ServiceWorkerRegistrationWorkerThread::ServiceWorkerRegistrationWorkerThread(WorkerPrivate* aWorkerPrivate,
const nsAString& aScope)
: ServiceWorkerRegistrationBase(nullptr, aScope)
, mWorkerPrivate(aWorkerPrivate)
{
@@ -1248,10 +1286,22 @@ ServiceWorkerRegistrationWorkerThread::G
}
RefPtr<WorkerPushManager> ret = mPushManager;
return ret.forget();
#endif /* ! MOZ_SIMPLEPUSH */
}
+SyncManager*
+ServiceWorkerRegistrationWorkerThread::GetSync(ErrorResult& aRv)
+{
+ if (!mSyncManager) {
+ mSyncManager = SyncManager::CreateOnWorker(mWorkerPrivate->GlobalScope(),
+ mWorkerPrivate,
+ mScope);
+ }
+
+ return mSyncManager;
+}
+
} // dom namespace
} // mozilla namespace
diff --git a/dom/workers/ServiceWorkerRegistration.h b/dom/workers/ServiceWorkerRegistration.h
--- a/dom/workers/ServiceWorkerRegistration.h
+++ b/dom/workers/ServiceWorkerRegistration.h
@@ -17,18 +17,19 @@
class nsPIDOMWindowInner;
namespace mozilla {
namespace dom {
class Promise;
class PushManager;
+class SyncManager;
+class WorkerListener;
class WorkerPushManager;
-class WorkerListener;
namespace workers {
class ServiceWorker;
class WorkerPrivate;
} // namespace workers
bool
ServiceWorkerRegistrationVisible(JSContext* aCx, JSObject* aObj);
@@ -136,16 +137,19 @@ public:
GetWaiting() override;
already_AddRefed<workers::ServiceWorker>
GetActive() override;
already_AddRefed<PushManager>
GetPushManager(ErrorResult& aRv);
+ SyncManager*
+ GetSync(ErrorResult& aRv);
+
// DOMEventTargethelper
void DisconnectFromOwner() override
{
StopListeningForEvents();
ServiceWorkerRegistrationBase::DisconnectFromOwner();
}
// ServiceWorkerRegistrationListener
@@ -186,16 +190,18 @@ private:
// These three may change to a new worker at any time.
RefPtr<workers::ServiceWorker> mInstallingWorker;
RefPtr<workers::ServiceWorker> mWaitingWorker;
RefPtr<workers::ServiceWorker> mActiveWorker;
#ifndef MOZ_SIMPLEPUSH
RefPtr<PushManager> mPushManager;
#endif
+
+ RefPtr<SyncManager> mSyncManager;
};
class ServiceWorkerRegistrationWorkerThread final : public ServiceWorkerRegistrationBase
, public workers::WorkerFeature
{
public:
NS_DECL_ISUPPORTS_INHERITED
NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerRegistrationWorkerThread,
@@ -239,16 +245,19 @@ public:
}
bool
Notify(JSContext* aCx, workers::Status aStatus) override;
already_AddRefed<WorkerPushManager>
GetPushManager(ErrorResult& aRv);
+ SyncManager*
+ GetSync(ErrorResult& aRv);
+
private:
enum Reason
{
RegistrationIsGoingAway = 0,
WorkerIsGoingAway,
};
~ServiceWorkerRegistrationWorkerThread();
@@ -260,14 +269,16 @@ private:
ReleaseListener(Reason aReason);
workers::WorkerPrivate* mWorkerPrivate;
RefPtr<WorkerListener> mListener;
#ifndef MOZ_SIMPLEPUSH
RefPtr<WorkerPushManager> mPushManager;
#endif
+
+ RefPtr<SyncManager> mSyncManager;
};
} // namespace dom
} // namespace mozilla
#endif /* mozilla_dom_ServiceWorkerRegistration_h */
diff --git a/dom/workers/WorkerPrefs.h b/dom/workers/WorkerPrefs.h
--- a/dom/workers/WorkerPrefs.h
+++ b/dom/workers/WorkerPrefs.h
@@ -30,16 +30,17 @@ WORKER_SIMPLE_PREF("dom.performance.enab
WORKER_SIMPLE_PREF("dom.webnotifications.enabled", DOMWorkerNotificationEnabled, DOM_WORKERNOTIFICATION)
WORKER_SIMPLE_PREF("dom.webnotifications.serviceworker.enabled", DOMServiceWorkerNotificationEnabled, DOM_SERVICEWORKERNOTIFICATION)
WORKER_SIMPLE_PREF("dom.serviceWorkers.enabled", ServiceWorkersEnabled, SERVICEWORKERS_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.testing.enabled", ServiceWorkersTestingEnabled, SERVICEWORKERS_TESTING_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.interception.enabled", InterceptionEnabled, INTERCEPTION_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.interception.opaque.enabled", OpaqueInterceptionEnabled, INTERCEPTION_OPAQUE_ENABLED)
WORKER_SIMPLE_PREF("dom.serviceWorkers.openWindow.enabled", OpenWindowEnabled, OPEN_WINDOW_ENABLED)
WORKER_SIMPLE_PREF("dom.push.enabled", PushEnabled, PUSH_ENABLED)
+WORKER_SIMPLE_PREF("dom.background.sync.enabled", BackgroundSyncEnabled, BACKGROUND_SYNC_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcache.enabled", RequestCacheEnabled, REQUESTCACHE_ENABLED)
WORKER_SIMPLE_PREF("dom.requestcontext.enabled", RequestContextEnabled, REQUESTCONTEXT_ENABLED)
WORKER_SIMPLE_PREF("gfx.offscreencanvas.enabled", OffscreenCanvasEnabled, OFFSCREENCANVAS_ENABLED)
WORKER_PREF("dom.workers.latestJSVersion", JSVersionChanged)
WORKER_PREF("intl.accept_languages", PrefLanguagesChanged)
WORKER_PREF("general.appname.override", AppNameOverrideChanged)
WORKER_PREF("general.appversion.override", AppVersionOverrideChanged)
WORKER_PREF("general.platform.override", PlatformOverrideChanged)
diff --git a/dom/workers/moz.build b/dom/workers/moz.build
--- a/dom/workers/moz.build
+++ b/dom/workers/moz.build
@@ -92,16 +92,17 @@ IPDL_SOURCES += [
'PServiceWorkerManager.ipdl',
'ServiceWorkerRegistrarTypes.ipdlh',
]
LOCAL_INCLUDES += [
'../base',
'../system',
'/dom/base',
+ '/dom/sync',
'/xpcom/build',
'/xpcom/threads',
]
include('/ipc/chromium/chromium-config.mozbuild')
FINAL_LIBRARY = 'xul'
diff --git a/ipc/glue/BackgroundChildImpl.cpp b/ipc/glue/BackgroundChildImpl.cpp
--- a/ipc/glue/BackgroundChildImpl.cpp
+++ b/ipc/glue/BackgroundChildImpl.cpp
@@ -2,16 +2,17 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "BackgroundChildImpl.h"
#include "ActorsChild.h" // IndexedDB
#include "BroadcastChannelChild.h"
#include "ServiceWorkerManagerChild.h"
+#include "SyncManagerChild.h"
#include "FileDescriptorSetChild.h"
#ifdef MOZ_WEBRTC
#include "CamerasChild.h"
#endif
#include "mozilla/media/MediaChild.h"
#include "mozilla/Assertions.h"
#include "mozilla/dom/PBlobChild.h"
#include "mozilla/dom/asmjscache/AsmJSCache.h"
@@ -62,16 +63,17 @@ namespace ipc {
using mozilla::dom::UDPSocketChild;
using mozilla::net::PUDPSocketChild;
using mozilla::dom::asmjscache::PAsmJSCacheEntryChild;
using mozilla::dom::cache::PCacheChild;
using mozilla::dom::cache::PCacheStorageChild;
using mozilla::dom::cache::PCacheStreamControlChild;
using mozilla::dom::PNuwaChild;
+using mozilla::dom::SyncManagerChild;
// -----------------------------------------------------------------------------
// BackgroundChildImpl::ThreadLocal
// -----------------------------------------------------------------------------
BackgroundChildImpl::
ThreadLocal::ThreadLocal()
: mCurrentFileHandle(nullptr)
@@ -444,16 +446,36 @@ bool
BackgroundChildImpl::DeallocPQuotaChild(PQuotaChild* aActor)
{
MOZ_ASSERT(aActor);
delete aActor;
return true;
}
+// -----------------------------------------------------------------------------
+// Background Sync API
+// -----------------------------------------------------------------------------
+
+dom::PSyncManagerChild*
+BackgroundChildImpl::AllocPSyncManagerChild()
+{
+ RefPtr<SyncManagerChild> agent = new SyncManagerChild();
+ return agent.forget().take();
+}
+
+bool
+BackgroundChildImpl::DeallocPSyncManagerChild(PSyncManagerChild* aActor)
+{
+ RefPtr<SyncManagerChild> child =
+ dont_AddRef(static_cast<SyncManagerChild*>(aActor));
+ MOZ_ASSERT(child);
+ return true;
+}
+
} // namespace ipc
} // namespace mozilla
bool
TestChild::Recv__delete__(const nsCString& aTestArg)
{
MOZ_RELEASE_ASSERT(aTestArg == mTestArg,
"BackgroundTest message was corrupted!");
diff --git a/ipc/glue/BackgroundChildImpl.h b/ipc/glue/BackgroundChildImpl.h
--- a/ipc/glue/BackgroundChildImpl.h
+++ b/ipc/glue/BackgroundChildImpl.h
@@ -153,16 +153,22 @@ protected:
virtual bool
DeallocPAsmJSCacheEntryChild(PAsmJSCacheEntryChild* aActor) override;
virtual PQuotaChild*
AllocPQuotaChild() override;
virtual bool
DeallocPQuotaChild(PQuotaChild* aActor) override;
+
+ virtual PSyncManagerChild*
+ AllocPSyncManagerChild() override;
+
+ virtual bool
+ DeallocPSyncManagerChild(PSyncManagerChild* aActor) override;
};
class BackgroundChildImpl::ThreadLocal final
{
friend class nsAutoPtr<ThreadLocal>;
public:
nsAutoPtr<mozilla::dom::indexedDB::ThreadLocal> mIndexedDBThreadLocal;
diff --git a/ipc/glue/BackgroundParentImpl.cpp b/ipc/glue/BackgroundParentImpl.cpp
--- a/ipc/glue/BackgroundParentImpl.cpp
+++ b/ipc/glue/BackgroundParentImpl.cpp
@@ -32,32 +32,34 @@
#include "nsIAppsService.h"
#include "nsNetUtil.h"
#include "nsIScriptSecurityManager.h"
#include "mozilla/RefPtr.h"
#include "nsThreadUtils.h"
#include "nsTraceRefcnt.h"
#include "nsXULAppAPI.h"
#include "ServiceWorkerManagerParent.h"
+#include "SyncManagerParent.h"
#ifdef DISABLE_ASSERTS_FOR_FUZZING
#define ASSERT_UNLESS_FUZZING(...) do { } while (0)
#else
#define ASSERT_UNLESS_FUZZING(...) MOZ_ASSERT(false)
#endif
using mozilla::ipc::AssertIsOnBackgroundThread;
using mozilla::dom::asmjscache::PAsmJSCacheEntryParent;
using mozilla::dom::cache::PCacheParent;
using mozilla::dom::cache::PCacheStorageParent;
using mozilla::dom::cache::PCacheStreamControlParent;
using mozilla::dom::MessagePortParent;
using mozilla::dom::PMessagePortParent;
using mozilla::dom::PNuwaParent;
using mozilla::dom::NuwaParent;
+using mozilla::dom::SyncManagerParent;
using mozilla::dom::UDPSocketParent;
namespace {
void
AssertIsInMainProcess()
{
MOZ_ASSERT(XRE_IsParentProcess());
@@ -92,16 +94,17 @@ public:
} // namespace
namespace mozilla {
namespace ipc {
using mozilla::dom::ContentParent;
using mozilla::dom::BroadcastChannelParent;
using mozilla::dom::ServiceWorkerRegistrationData;
+using mozilla::dom::SyncManagerParent;
using mozilla::dom::workers::ServiceWorkerManagerParent;
BackgroundParentImpl::BackgroundParentImpl()
{
AssertIsInMainProcess();
AssertIsOnMainThread();
MOZ_COUNT_CTOR(mozilla::ipc::BackgroundParentImpl);
@@ -741,16 +744,36 @@ BackgroundParentImpl::DeallocPQuotaParen
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
MOZ_ASSERT(aActor);
return mozilla::dom::quota::DeallocPQuotaParent(aActor);
}
+mozilla::dom::PSyncManagerParent*
+BackgroundParentImpl::AllocPSyncManagerParent()
+{
+ AssertIsInMainProcess();
+ AssertIsOnBackgroundThread();
+
+ return new SyncManagerParent();
+}
+
+bool
+BackgroundParentImpl::DeallocPSyncManagerParent(PSyncManagerParent* aActor)
+{
+ AssertIsInMainProcess();
+ AssertIsOnBackgroundThread();
+ MOZ_ASSERT(aActor);
+
+ delete static_cast<SyncManagerParent*>(aActor);
+ return true;
+}
+
} // namespace ipc
} // namespace mozilla
void
TestParent::ActorDestroy(ActorDestroyReason aWhy)
{
AssertIsInMainProcess();
AssertIsOnBackgroundThread();
diff --git a/ipc/glue/BackgroundParentImpl.h b/ipc/glue/BackgroundParentImpl.h
--- a/ipc/glue/BackgroundParentImpl.h
+++ b/ipc/glue/BackgroundParentImpl.h
@@ -181,14 +181,20 @@ protected:
virtual bool
DeallocPAsmJSCacheEntryParent(PAsmJSCacheEntryParent* aActor) override;
virtual PQuotaParent*
AllocPQuotaParent() override;
virtual bool
DeallocPQuotaParent(PQuotaParent* aActor) override;
+
+ virtual PSyncManagerParent*
+ AllocPSyncManagerParent() override;
+
+ virtual bool
+ DeallocPSyncManagerParent(PSyncManagerParent* aActor) override;
};
} // namespace ipc
} // namespace mozilla
#endif // mozilla_ipc_backgroundparentimpl_h__
diff --git a/ipc/glue/PBackground.ipdl b/ipc/glue/PBackground.ipdl
--- a/ipc/glue/PBackground.ipdl
+++ b/ipc/glue/PBackground.ipdl
@@ -12,16 +12,17 @@ include protocol PCache;
include protocol PCacheStorage;
include protocol PCacheStreamControl;
include protocol PFileDescriptorSet;
include protocol PMessagePort;
include protocol PCameras;
include protocol PNuwa;
include protocol PQuota;
include protocol PServiceWorkerManager;
+include protocol PSyncManager;
include protocol PUDPSocket;
include protocol PVsync;
include DOMTypes;
include PBackgroundSharedTypes;
include PBackgroundIDBSharedTypes;
include "mozilla/dom/cache/IPCUtils.h";
@@ -50,16 +51,17 @@ sync protocol PBackground
manages PCacheStorage;
manages PCacheStreamControl;
manages PFileDescriptorSet;
manages PMessagePort;
manages PCameras;
manages PNuwa;
manages PQuota;
manages PServiceWorkerManager;
+ manages PSyncManager;
manages PUDPSocket;
manages PVsync;
parent:
// Only called at startup during mochitests to check the basic infrastructure.
async PBackgroundTest(nsCString testArg);
async PBackgroundIDBFactory(LoggingInfo loggingInfo);
@@ -90,16 +92,18 @@ parent:
async MessagePortForceClose(nsID uuid, nsID destinationUuid, uint32_t sequenceId);
async PAsmJSCacheEntry(OpenMode openMode,
WriteParams write,
PrincipalInfo principalInfo);
async PQuota();
+ async PSyncManager();
+
child:
async PCache();
async PCacheStreamControl();
both:
async PBlob(BlobConstructorParams params);
async PFileDescriptorSet(FileDescriptor fd);
diff --git a/ipc/glue/moz.build b/ipc/glue/moz.build
--- a/ipc/glue/moz.build
+++ b/ipc/glue/moz.build
@@ -135,16 +135,17 @@ SOURCES += [
'GeckoChildProcessHost.cpp',
'URIUtils.cpp',
]
LOCAL_INCLUDES += [
'/caps',
'/dom/broadcastchannel',
'/dom/indexedDB',
+ '/dom/sync',
'/dom/workers',
'/media/webrtc/trunk',
'/xpcom/build',
]
IPDL_SOURCES = [
'InputStreamParams.ipdlh',
'PBackground.ipdl',
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment