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 #ifndef _mozilla_dom_ClientSource_h
7 #define _mozilla_dom_ClientSource_h
8 
9 #include "mozilla/dom/ClientInfo.h"
10 #include "mozilla/dom/ClientOpPromise.h"
11 #include "mozilla/dom/ClientThing.h"
12 #include "mozilla/dom/ServiceWorkerDescriptor.h"
13 #include "mozilla/ResultVariant.h"
14 #include "mozilla/Variant.h"
15 
16 #ifdef XP_WIN
17 #  undef PostMessage
18 #endif
19 
20 class nsIContentSecurityPolicy;
21 class nsIDocShell;
22 class nsIGlobalObject;
23 class nsISerialEventTarget;
24 class nsPIDOMWindowInner;
25 
26 namespace mozilla {
27 class ErrorResult;
28 
29 namespace dom {
30 
31 class ClientControlledArgs;
32 class ClientFocusArgs;
33 class ClientGetInfoAndStateArgs;
34 class ClientManager;
35 class ClientPostMessageArgs;
36 class ClientSourceChild;
37 class ClientSourceConstructorArgs;
38 class ClientSourceExecutionReadyArgs;
39 class ClientState;
40 class ClientWindowState;
41 class PClientManagerChild;
42 class WorkerPrivate;
43 
44 // ClientSource is an RAII style class that is designed to be held via
45 // a UniquePtr<>.  When created ClientSource will register the existence
46 // of a client in the cross-process ClientManagerService.  When the
47 // ClientSource is destroyed then client entry will be removed.  Code
48 // that represents globals or browsing environments, such as nsGlobalWindow
49 // or WorkerPrivate, should use ClientManager to create a ClientSource.
50 class ClientSource final : public ClientThing<ClientSourceChild> {
51   friend class ClientManager;
52 
53   NS_DECL_OWNINGTHREAD
54 
55   RefPtr<ClientManager> mManager;
56   nsCOMPtr<nsISerialEventTarget> mEventTarget;
57 
58   Variant<Nothing, RefPtr<nsPIDOMWindowInner>, nsCOMPtr<nsIDocShell>,
59           WorkerPrivate*>
60       mOwner;
61 
62   ClientInfo mClientInfo;
63   Maybe<ServiceWorkerDescriptor> mController;
64 
65   // Contained a de-duplicated list of ServiceWorker scope strings
66   // for which this client has called navigator.serviceWorker.register().
67   // Typically there will be either be zero or one scope strings, but
68   // there could be more.  We keep this list until the client is closed.
69   AutoTArray<nsCString, 1> mRegisteringScopeList;
70 
71   void Shutdown();
72 
73   void ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs);
74 
75   WorkerPrivate* GetWorkerPrivate() const;
76 
77   nsIDocShell* GetDocShell() const;
78 
79   nsIGlobalObject* GetGlobal() const;
80 
81   Result<bool, ErrorResult> MaybeCreateInitialDocument();
82 
83   Result<ClientState, ErrorResult> SnapshotWindowState();
84 
85   // Private methods called by ClientManager
86   ClientSource(ClientManager* aManager, nsISerialEventTarget* aEventTarget,
87                const ClientSourceConstructorArgs& aArgs);
88 
89   void Activate(PClientManagerChild* aActor);
90 
91  public:
92   ~ClientSource();
93 
94   nsPIDOMWindowInner* GetInnerWindow() const;
95 
96   void WorkerExecutionReady(WorkerPrivate* aWorkerPrivate);
97 
98   nsresult WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow);
99 
100   nsresult DocShellExecutionReady(nsIDocShell* aDocShell);
101 
102   void Freeze();
103 
104   void Thaw();
105 
106   const ClientInfo& Info() const;
107 
108   // Trigger a synchronous IPC ping to the parent process to confirm that
109   // the ClientSource actor has been created.  This should only be used
110   // by the WorkerPrivate startup code to deal with a ClientHandle::Control()
111   // call racing on the main thread.  Do not call this in other circumstances!
112   void WorkerSyncPing(WorkerPrivate* aWorkerPrivate);
113 
114   // Synchronously mark the ClientSource as controlled by the given service
115   // worker.  This can happen as a result of a remote operation or directly
116   // by local code.  For example, if a client's initial network load is
117   // intercepted by a controlling service worker then this should be called
118   // immediately.
119   //
120   // Note, there is no way to clear the controlling service worker because
121   // the specification does not allow that operation.
122   void SetController(const ServiceWorkerDescriptor& aServiceWorker);
123 
124   // Mark the ClientSource as controlled using the remote operation arguments.
125   // This will in turn call SetController().
126   RefPtr<ClientOpPromise> Control(const ClientControlledArgs& aArgs);
127 
128   // Inherit the controller from a local parent client.  This requires both
129   // setting our immediate controller field and also updating the parent-side
130   // data structure.
131   void InheritController(const ServiceWorkerDescriptor& aServiceWorker);
132 
133   // Get the ClientSource's current controlling service worker, if one has
134   // been set.
135   const Maybe<ServiceWorkerDescriptor>& GetController() const;
136 
137   // Note that the client has reached DOMContentLoaded.  Only applies to window
138   // clients.
139   void NoteDOMContentLoaded();
140 
141   RefPtr<ClientOpPromise> Focus(const ClientFocusArgs& aArgs);
142 
143   RefPtr<ClientOpPromise> PostMessage(const ClientPostMessageArgs& aArgs);
144 
145   RefPtr<ClientOpPromise> GetInfoAndState(
146       const ClientGetInfoAndStateArgs& aArgs);
147 
148   Result<ClientState, ErrorResult> SnapshotState();
149 
150   nsISerialEventTarget* EventTarget() const;
151 
152   void SetCsp(nsIContentSecurityPolicy* aCsp);
153   void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP);
154   void SetCspInfo(const mozilla::ipc::CSPInfo& aCSPInfo);
155   const Maybe<mozilla::ipc::CSPInfo>& GetCspInfo();
156 
SetAgentClusterId(const nsID & aId)157   void SetAgentClusterId(const nsID& aId) {
158     mClientInfo.SetAgentClusterId(aId);
159   }
160 
161   void Traverse(nsCycleCollectionTraversalCallback& aCallback,
162                 const char* aName, uint32_t aFlags);
163 
164   void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);
165 
166   bool CalledRegisterForServiceWorkerScope(const nsACString& aScope);
167 };
168 
ImplCycleCollectionUnlink(UniquePtr<ClientSource> & aField)169 inline void ImplCycleCollectionUnlink(UniquePtr<ClientSource>& aField) {
170   aField.reset();
171 }
172 
ImplCycleCollectionTraverse(nsCycleCollectionTraversalCallback & aCallback,UniquePtr<ClientSource> & aField,const char * aName,uint32_t aFlags)173 inline void ImplCycleCollectionTraverse(
174     nsCycleCollectionTraversalCallback& aCallback,
175     UniquePtr<ClientSource>& aField, const char* aName, uint32_t aFlags) {
176   if (aField) {
177     aField->Traverse(aCallback, aName, aFlags);
178   }
179 }
180 
181 }  // namespace dom
182 }  // namespace mozilla
183 
184 #endif  // _mozilla_dom_ClientSource_h
185