summaryrefslogtreecommitdiffstats
path: root/dom/clients/manager/ClientSource.h
blob: dc89a61175cb511f217611e7848afe14c79bb038 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
/* -*- 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_ClientSource_h
#define _mozilla_dom_ClientSource_h

#include "mozilla/dom/ClientInfo.h"
#include "mozilla/dom/ClientOpPromise.h"
#include "mozilla/dom/ClientThing.h"
#include "mozilla/dom/ServiceWorkerDescriptor.h"
#include "mozilla/ResultVariant.h"
#include "mozilla/Variant.h"

#ifdef XP_WIN
#  undef PostMessage
#endif

class nsIContentSecurityPolicy;
class nsIDocShell;
class nsIGlobalObject;
class nsISerialEventTarget;
class nsPIDOMWindowInner;

namespace mozilla {
class ErrorResult;

namespace dom {

class ClientControlledArgs;
class ClientFocusArgs;
class ClientGetInfoAndStateArgs;
class ClientManager;
class ClientPostMessageArgs;
class ClientSourceChild;
class ClientSourceConstructorArgs;
class ClientSourceExecutionReadyArgs;
class ClientState;
class ClientWindowState;
class PClientManagerChild;
class WorkerPrivate;

// ClientSource is an RAII style class that is designed to be held via
// a UniquePtr<>.  When created ClientSource will register the existence
// of a client in the cross-process ClientManagerService.  When the
// ClientSource is destroyed then client entry will be removed.  Code
// that represents globals or browsing environments, such as nsGlobalWindow
// or WorkerPrivate, should use ClientManager to create a ClientSource.
class ClientSource final : public ClientThing<ClientSourceChild> {
  friend class ClientManager;

  NS_DECL_OWNINGTHREAD

  RefPtr<ClientManager> mManager;
  nsCOMPtr<nsISerialEventTarget> mEventTarget;

  Variant<Nothing, RefPtr<nsPIDOMWindowInner>, nsCOMPtr<nsIDocShell>,
          WorkerPrivate*>
      mOwner;

  ClientInfo mClientInfo;
  Maybe<ServiceWorkerDescriptor> mController;
  Maybe<nsCOMPtr<nsIPrincipal>> mPrincipal;

  // Contained a de-duplicated list of ServiceWorker scope strings
  // for which this client has called navigator.serviceWorker.register().
  // Typically there will be either be zero or one scope strings, but
  // there could be more.  We keep this list until the client is closed.
  AutoTArray<nsCString, 1> mRegisteringScopeList;

  void Shutdown();

  void ExecutionReady(const ClientSourceExecutionReadyArgs& aArgs);

  WorkerPrivate* GetWorkerPrivate() const;

  nsIDocShell* GetDocShell() const;

  nsIGlobalObject* GetGlobal() const;

  Result<bool, ErrorResult> MaybeCreateInitialDocument();

  Result<ClientState, ErrorResult> SnapshotWindowState();

  // Private methods called by ClientManager
  ClientSource(ClientManager* aManager, nsISerialEventTarget* aEventTarget,
               const ClientSourceConstructorArgs& aArgs);

  void Activate(PClientManagerChild* aActor);

 public:
  ~ClientSource();

  nsPIDOMWindowInner* GetInnerWindow() const;

  void WorkerExecutionReady(WorkerPrivate* aWorkerPrivate);

  nsresult WindowExecutionReady(nsPIDOMWindowInner* aInnerWindow);

  nsresult DocShellExecutionReady(nsIDocShell* aDocShell);

  void Freeze();

  void Thaw();

  void EvictFromBFCache();

  RefPtr<ClientOpPromise> EvictFromBFCacheOp();

  const ClientInfo& Info() const;

  // Trigger a synchronous IPC ping to the parent process to confirm that
  // the ClientSource actor has been created.  This should only be used
  // by the WorkerPrivate startup code to deal with a ClientHandle::Control()
  // call racing on the main thread.  Do not call this in other circumstances!
  void WorkerSyncPing(WorkerPrivate* aWorkerPrivate);

  // Synchronously mark the ClientSource as controlled by the given service
  // worker.  This can happen as a result of a remote operation or directly
  // by local code.  For example, if a client's initial network load is
  // intercepted by a controlling service worker then this should be called
  // immediately.
  //
  // Note, there is no way to clear the controlling service worker because
  // the specification does not allow that operation.
  void SetController(const ServiceWorkerDescriptor& aServiceWorker);

  // Mark the ClientSource as controlled using the remote operation arguments.
  // This will in turn call SetController().
  RefPtr<ClientOpPromise> Control(const ClientControlledArgs& aArgs);

  // Inherit the controller from a local parent client.  This requires both
  // setting our immediate controller field and also updating the parent-side
  // data structure.
  void InheritController(const ServiceWorkerDescriptor& aServiceWorker);

  // Get the ClientSource's current controlling service worker, if one has
  // been set.
  const Maybe<ServiceWorkerDescriptor>& GetController() const;

  // Note that the client has reached DOMContentLoaded.  Only applies to window
  // clients.
  void NoteDOMContentLoaded();

  // TODO: Convert Focus() to MOZ_CAN_RUN_SCRIPT
  MOZ_CAN_RUN_SCRIPT_BOUNDARY RefPtr<ClientOpPromise> Focus(
      const ClientFocusArgs& aArgs);

  RefPtr<ClientOpPromise> PostMessage(const ClientPostMessageArgs& aArgs);

  RefPtr<ClientOpPromise> GetInfoAndState(
      const ClientGetInfoAndStateArgs& aArgs);

  Result<ClientState, ErrorResult> SnapshotState();

  nsISerialEventTarget* EventTarget() const;

  void SetCsp(nsIContentSecurityPolicy* aCsp);
  void SetPreloadCsp(nsIContentSecurityPolicy* aPreloadCSP);
  void SetCspInfo(const mozilla::ipc::CSPInfo& aCSPInfo);
  const Maybe<mozilla::ipc::CSPInfo>& GetCspInfo();

  void SetAgentClusterId(const nsID& aId) {
    mClientInfo.SetAgentClusterId(aId);
  }

  void Traverse(nsCycleCollectionTraversalCallback& aCallback,
                const char* aName, uint32_t aFlags);

  void NoteCalledRegisterForServiceWorkerScope(const nsACString& aScope);

  bool CalledRegisterForServiceWorkerScope(const nsACString& aScope);

  nsIPrincipal* GetPrincipal();
};

inline void ImplCycleCollectionUnlink(UniquePtr<ClientSource>& aField) {
  aField.reset();
}

inline void ImplCycleCollectionTraverse(
    nsCycleCollectionTraversalCallback& aCallback,
    UniquePtr<ClientSource>& aField, const char* aName, uint32_t aFlags) {
  if (aField) {
    aField->Traverse(aCallback, aName, aFlags);
  }
}

}  // namespace dom
}  // namespace mozilla

#endif  // _mozilla_dom_ClientSource_h