diff --git a/dom/bindings/Bindings.conf b/dom/bindings/Bindings.conf index b4ce53252baa..08f64d675c34 100644 --- a/dom/bindings/Bindings.conf +++ b/dom/bindings/Bindings.conf @@ -707,6 +707,18 @@ DOMInterfaces = { 'workers': True, }], +'InstallPhaseEvent': { + 'headerFile': 'ServiceWorkerEvents.h', + 'nativeType': 'mozilla::dom::workers::InstallPhaseEvent', + 'workers': True +}, + +'InstallEvent': { + 'headerFile': 'ServiceWorkerEvents.h', + 'nativeType': 'mozilla::dom::workers::InstallEvent', + 'workers': True +}, + 'KeyEvent': { 'concrete': False }, diff --git a/dom/webidl/InstallEvent.webidl b/dom/webidl/InstallEvent.webidl new file mode 100644 index 000000000000..9c6d40349177 --- /dev/null +++ b/dom/webidl/InstallEvent.webidl @@ -0,0 +1,28 @@ +/* -*- 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/. + * + * For more information on this interface, please see + * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html + */ + +// While not explicitly restricted to ServiceWorkerGlobalScope, it probably +// should be. https://github.com/slightlyoff/ServiceWorker/issues/254 +[Constructor(DOMString type, optional InstallEventInit eventInitDict), + Func="mozilla::dom::workers::ServiceWorkerEventsVisible"] +interface InstallEvent : InstallPhaseEvent { + // The currently active worker for this scope when this worker is asked to + // install itself. + // This may be null when a ServiceWorker is being installed for a previously + // uncontrolled scope. + // https://github.com/slightlyoff/ServiceWorker/issues/260 + readonly attribute ServiceWorker? activeWorker; + void replace(); +}; + +// Should be in the spec soon to satisfy conventions about events. +// https://github.com/slightlyoff/ServiceWorker/issues/216. +dictionary InstallEventInit : EventInit { + ServiceWorker? activeWorker = null; +}; diff --git a/dom/webidl/InstallPhaseEvent.webidl b/dom/webidl/InstallPhaseEvent.webidl new file mode 100644 index 000000000000..04337749eba3 --- /dev/null +++ b/dom/webidl/InstallPhaseEvent.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/. + * + * For more information on this interface, please see + * http://slightlyoff.github.io/ServiceWorker/spec/service_worker/index.html + */ + +// While not explicitly restricted to ServiceWorkerGlobalScope, it probably +// should be. https://github.com/slightlyoff/ServiceWorker/issues/254 +[Constructor(DOMString type, optional EventInit eventInitDict), + Func="mozilla::dom::workers::ServiceWorkerEventsVisible"] +interface InstallPhaseEvent : Event { + // https://github.com/slightlyoff/ServiceWorker/issues/261 + void waitUntil(Promise p); +}; diff --git a/dom/webidl/moz.build b/dom/webidl/moz.build index 5e7820ebc1f8..5c690310899a 100644 --- a/dom/webidl/moz.build +++ b/dom/webidl/moz.build @@ -214,6 +214,8 @@ WEBIDL_FILES = [ 'InputEvent.webidl', 'InputMethod.webidl', 'InspectorUtils.webidl', + 'InstallEvent.webidl', + 'InstallPhaseEvent.webidl', 'InterAppConnection.webidl', 'InterAppConnectionRequest.webidl', 'InterAppMessagePort.webidl', diff --git a/dom/workers/ServiceWorkerEvents.cpp b/dom/workers/ServiceWorkerEvents.cpp new file mode 100644 index 000000000000..7b895365afca --- /dev/null +++ b/dom/workers/ServiceWorkerEvents.cpp @@ -0,0 +1,66 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* vim: set ts=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 "ServiceWorkerEvents.h" + +#include "nsContentUtils.h" + +#include "mozilla/dom/Promise.h" +#include "mozilla/dom/WorkerScope.h" +#include "mozilla/dom/workers/bindings/ServiceWorker.h" +#include "mozilla/dom/ServiceWorkerGlobalScopeBinding.h" + +using namespace mozilla::dom; + +BEGIN_WORKERS_NAMESPACE + +bool +ServiceWorkerEventsVisible(JSContext* aCx, JSObject* aObj) +{ + ServiceWorkerGlobalScope* scope = nullptr; + nsresult rv = UnwrapObject(aObj, scope); + return NS_SUCCEEDED(rv) && scope; +} + +InstallPhaseEvent::InstallPhaseEvent(EventTarget* aOwner) + : Event(aOwner, nullptr, nullptr) +{ +} + +void +InstallPhaseEvent::WaitUntil(Promise& aPromise) +{ + MOZ_ASSERT(!NS_IsMainThread()); + + // Only first caller counts. + if (EventPhase() == AT_TARGET && !mPromise) { + mPromise = &aPromise; + } +} + +NS_IMPL_ADDREF_INHERITED(InstallPhaseEvent, Event) +NS_IMPL_RELEASE_INHERITED(InstallPhaseEvent, Event) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InstallPhaseEvent) +NS_INTERFACE_MAP_END_INHERITING(Event) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(InstallPhaseEvent, Event, mPromise) + +InstallEvent::InstallEvent(EventTarget* aOwner) + : InstallPhaseEvent(aOwner) +{ +} + +NS_IMPL_ADDREF_INHERITED(InstallEvent, InstallPhaseEvent) +NS_IMPL_RELEASE_INHERITED(InstallEvent, InstallPhaseEvent) + +NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(InstallEvent) +NS_INTERFACE_MAP_END_INHERITING(InstallPhaseEvent) + +NS_IMPL_CYCLE_COLLECTION_INHERITED(InstallEvent, InstallPhaseEvent, mActiveWorker) + +END_WORKERS_NAMESPACE diff --git a/dom/workers/ServiceWorkerEvents.h b/dom/workers/ServiceWorkerEvents.h new file mode 100644 index 000000000000..73f7f7fd8790 --- /dev/null +++ b/dom/workers/ServiceWorkerEvents.h @@ -0,0 +1,133 @@ +/* -*- Mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 40 -*- */ +/* 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_workers_serviceworkerevents_h__ +#define mozilla_dom_workers_serviceworkerevents_h__ + +#include "mozilla/dom/Event.h" +#include "mozilla/dom/InstallPhaseEventBinding.h" +#include "mozilla/dom/InstallEventBinding.h" + +namespace mozilla { +namespace dom { + class Promise; +} // namespace dom +} // namespace mozilla + +BEGIN_WORKERS_NAMESPACE + +class ServiceWorker; + +bool +ServiceWorkerEventsVisible(JSContext* aCx, JSObject* aObj); + +class InstallPhaseEvent : public Event +{ + nsRefPtr mPromise; + +protected: + InstallPhaseEvent(mozilla::dom::EventTarget* aOwner); + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InstallPhaseEvent, Event) + NS_FORWARD_TO_EVENT + + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE + { + return mozilla::dom::InstallPhaseEventBinding_workers::Wrap(aCx, this); + } + + static already_AddRefed + Constructor(mozilla::dom::EventTarget* aOwner, + const nsAString& aType, + const EventInit& aOptions) + { + nsRefPtr e = new InstallPhaseEvent(aOwner); + bool trusted = e->Init(aOwner); + e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); + e->SetTrusted(trusted); + return e.forget(); + } + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const EventInit& aOptions, + ErrorResult& aRv) + { + nsCOMPtr target = do_QueryInterface(aGlobal.GetAsSupports()); + return Constructor(target, aType, aOptions); + } + + void + WaitUntil(Promise& aPromise); + + already_AddRefed + GetPromise() const + { + nsRefPtr p = mPromise; + return p.forget(); + } +}; + +class InstallEvent MOZ_FINAL : public InstallPhaseEvent +{ + // FIXME(nsm): Bug 982787 will allow actually populating this. + nsRefPtr mActiveWorker; + +protected: + InstallEvent(mozilla::dom::EventTarget* aOwner); + +public: + NS_DECL_ISUPPORTS_INHERITED + NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(InstallEvent, InstallPhaseEvent) + NS_FORWARD_TO_EVENT + + virtual JSObject* WrapObject(JSContext* aCx) MOZ_OVERRIDE + { + return mozilla::dom::InstallEventBinding_workers::Wrap(aCx, this); + } + + static already_AddRefed + Constructor(mozilla::dom::EventTarget* aOwner, + const nsAString& aType, + const InstallEventInit& aOptions) + { + nsRefPtr e = new InstallEvent(aOwner); + bool trusted = e->Init(aOwner); + e->InitEvent(aType, aOptions.mBubbles, aOptions.mCancelable); + e->SetTrusted(trusted); + e->mActiveWorker = aOptions.mActiveWorker; + return e.forget(); + } + + static already_AddRefed + Constructor(const GlobalObject& aGlobal, + const nsAString& aType, + const InstallEventInit& aOptions, + ErrorResult& aRv) + { + nsCOMPtr owner = do_QueryInterface(aGlobal.GetAsSupports()); + return Constructor(owner, aType, aOptions); + } + + already_AddRefed + GetActiveWorker() const + { + nsRefPtr sw = mActiveWorker; + return sw.forget(); + } + + void + Replace() + { + // FIXME(nsm): Unspecced. Bug 982711 + NS_WARNING("Not Implemented"); + }; +}; + +END_WORKERS_NAMESPACE +#endif /* mozilla_dom_workers_serviceworkerevents_h__ */ diff --git a/dom/workers/moz.build b/dom/workers/moz.build index a23fb801c294..69595c784fd0 100644 --- a/dom/workers/moz.build +++ b/dom/workers/moz.build @@ -49,6 +49,7 @@ SOURCES += [ 'ScriptLoader.cpp', 'ServiceWorker.cpp', 'ServiceWorkerContainer.cpp', + 'ServiceWorkerEvents.cpp', 'SharedWorker.cpp', 'URL.cpp', 'WorkerPrivate.cpp',