Created
March 17, 2016 11:10
-
-
Save ferjm/b42d34638ccaf40fddb4 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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