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