1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_serviceworkercontainer_h__ 8 #define mozilla_dom_serviceworkercontainer_h__ 9 10 #include "mozilla/DOMEventTargetHelper.h" 11 #include "mozilla/dom/ServiceWorkerUtils.h" 12 13 class nsIGlobalWindow; 14 15 namespace mozilla { 16 namespace dom { 17 18 class ClientPostMessageArgs; 19 struct MessageEventInit; 20 class Promise; 21 struct RegistrationOptions; 22 class ServiceWorker; 23 24 // Lightweight serviceWorker APIs collection. 25 class ServiceWorkerContainer final : public DOMEventTargetHelper { 26 public: 27 class Inner { 28 public: 29 virtual void AddContainer(ServiceWorkerContainer* aOuter) = 0; 30 31 virtual void RemoveContainer(ServiceWorkerContainer* aOuter) = 0; 32 33 virtual void Register(const ClientInfo& aClientInfo, 34 const nsACString& aScopeURL, 35 const nsACString& aScriptURL, 36 ServiceWorkerUpdateViaCache aUpdateViaCache, 37 ServiceWorkerRegistrationCallback&& aSuccessCB, 38 ServiceWorkerFailureCallback&& aFailureCB) const = 0; 39 40 virtual void GetRegistration( 41 const ClientInfo& aClientInfo, const nsACString& aURL, 42 ServiceWorkerRegistrationCallback&& aSuccessCB, 43 ServiceWorkerFailureCallback&& aFailureCB) const = 0; 44 45 virtual void GetRegistrations( 46 const ClientInfo& aClientInfo, 47 ServiceWorkerRegistrationListCallback&& aSuccessCB, 48 ServiceWorkerFailureCallback&& aFailureCB) const = 0; 49 50 virtual void GetReady(const ClientInfo& aClientInfo, 51 ServiceWorkerRegistrationCallback&& aSuccessCB, 52 ServiceWorkerFailureCallback&& aFailureCB) const = 0; 53 54 NS_INLINE_DECL_PURE_VIRTUAL_REFCOUNTING 55 }; 56 57 NS_DECL_ISUPPORTS_INHERITED NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer,DOMEventTargetHelper)58 NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(ServiceWorkerContainer, 59 DOMEventTargetHelper) 60 61 IMPL_EVENT_HANDLER(controllerchange) 62 IMPL_EVENT_HANDLER(error) 63 IMPL_EVENT_HANDLER(messageerror) 64 65 // Almost a manual expansion of IMPL_EVENT_HANDLER(message), but 66 // with the additional StartMessages() when setting the handler, as 67 // required by the spec. 68 inline mozilla::dom::EventHandlerNonNull* GetOnmessage() { 69 return GetEventHandler(nsGkAtoms::onmessage); 70 } SetOnmessage(mozilla::dom::EventHandlerNonNull * aCallback)71 inline void SetOnmessage(mozilla::dom::EventHandlerNonNull* aCallback) { 72 SetEventHandler(nsGkAtoms::onmessage, aCallback); 73 StartMessages(); 74 } 75 76 static bool IsEnabled(JSContext* aCx, JSObject* aGlobal); 77 78 static already_AddRefed<ServiceWorkerContainer> Create( 79 nsIGlobalObject* aGlobal); 80 81 virtual JSObject* WrapObject(JSContext* aCx, 82 JS::Handle<JSObject*> aGivenProto) override; 83 84 already_AddRefed<Promise> Register(const nsAString& aScriptURL, 85 const RegistrationOptions& aOptions, 86 ErrorResult& aRv); 87 88 already_AddRefed<ServiceWorker> GetController(); 89 90 already_AddRefed<Promise> GetRegistration(const nsAString& aDocumentURL, 91 ErrorResult& aRv); 92 93 already_AddRefed<Promise> GetRegistrations(ErrorResult& aRv); 94 95 void StartMessages(); 96 97 Promise* GetReady(ErrorResult& aRv); 98 99 // Testing only. 100 void GetScopeForUrl(const nsAString& aUrl, nsString& aScope, 101 ErrorResult& aRv); 102 103 // DOMEventTargetHelper 104 void DisconnectFromOwner() override; 105 106 // Invalidates |mControllerWorker| and dispatches a "controllerchange" 107 // event. 108 void ControllerChanged(ErrorResult& aRv); 109 110 void ReceiveMessage(const ClientPostMessageArgs& aArgs); 111 112 private: 113 ServiceWorkerContainer( 114 nsIGlobalObject* aGlobal, 115 already_AddRefed<ServiceWorkerContainer::Inner> aInner); 116 117 ~ServiceWorkerContainer(); 118 119 // Utility method to get the global if its present and if certain 120 // additional validaty checks pass. One of these additional checks 121 // verifies the global can access storage. Since storage access can 122 // vary based on user settings we want to often provide some error 123 // message if the storage check fails. This method takes an optional 124 // callback that can be used to report the storage failure to the 125 // devtools console. 126 nsIGlobalObject* GetGlobalIfValid( 127 ErrorResult& aRv, 128 const std::function<void(Document*)>&& aStorageFailureCB = nullptr) const; 129 130 struct ReceivedMessage; 131 132 // Dispatch a Runnable that dispatches the given message on this 133 // object. When the owner of this object is a Window, the Runnable 134 // is dispatched on the corresponding TabGroup. 135 void EnqueueReceivedMessageDispatch(RefPtr<ReceivedMessage> aMessage); 136 137 template <typename F> 138 void RunWithJSContext(F&& aCallable); 139 140 void DispatchMessage(RefPtr<ReceivedMessage> aMessage); 141 142 // When it fails, returning boolean means whether it's because deserailization 143 // failed or not. 144 static Result<Ok, bool> FillInMessageEventInit(JSContext* aCx, 145 nsIGlobalObject* aGlobal, 146 ReceivedMessage& aMessage, 147 MessageEventInit& aInit, 148 ErrorResult& aRv); 149 150 RefPtr<Inner> mInner; 151 152 // This only changes when a worker hijacks everything in its scope by calling 153 // claim. 154 RefPtr<ServiceWorker> mControllerWorker; 155 156 RefPtr<Promise> mReadyPromise; 157 MozPromiseRequestHolder<ServiceWorkerRegistrationPromise> mReadyPromiseHolder; 158 159 // Set after StartMessages() has been called. 160 bool mMessagesStarted = false; 161 162 // Queue holding messages posted from service worker as long as 163 // StartMessages() hasn't been called. 164 nsTArray<RefPtr<ReceivedMessage>> mPendingMessages; 165 }; 166 167 } // namespace dom 168 } // namespace mozilla 169 170 #endif /* mozilla_dom_serviceworkercontainer_h__ */ 171