1 /* -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: nil; tab-width: 8 -*- */
2 /* vim: set sw=2 ts=8 et tw=80 ft=cpp : */
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_WindowGlobalParent_h
8 #define mozilla_dom_WindowGlobalParent_h
9 
10 #include "mozilla/ContentBlockingLog.h"
11 #include "mozilla/ContentBlockingNotifier.h"
12 #include "mozilla/Maybe.h"
13 #include "mozilla/RefPtr.h"
14 #include "mozilla/UniquePtr.h"
15 #include "mozilla/dom/ClientInfo.h"
16 #include "mozilla/dom/ClientIPCTypes.h"
17 #include "mozilla/dom/DOMRect.h"
18 #include "mozilla/dom/PWindowGlobalParent.h"
19 #include "mozilla/dom/WindowContext.h"
20 #include "mozilla/dom/WindowGlobalActorsBinding.h"
21 #include "nsTHashMap.h"
22 #include "nsRefPtrHashtable.h"
23 #include "nsWrapperCache.h"
24 #include "nsISupports.h"
25 #include "nsIDOMProcessParent.h"
26 #include "mozilla/dom/WindowGlobalActor.h"
27 #include "mozilla/dom/CanonicalBrowsingContext.h"
28 #include "mozilla/net/CookieJarSettings.h"
29 
30 class nsIPrincipal;
31 class nsIURI;
32 class nsFrameLoader;
33 
34 namespace mozilla {
35 
36 namespace gfx {
37 class CrossProcessPaint;
38 }  // namespace gfx
39 
40 namespace dom {
41 
42 class BrowserParent;
43 class WindowGlobalChild;
44 class JSWindowActorParent;
45 class JSActorMessageMeta;
46 struct PageUseCounters;
47 class WindowSessionStoreState;
48 struct WindowSessionStoreUpdate;
49 class SSCacheQueryResult;
50 
51 /**
52  * A handle in the parent process to a specific nsGlobalWindowInner object.
53  */
54 class WindowGlobalParent final : public WindowContext,
55                                  public WindowGlobalActor,
56                                  public PWindowGlobalParent {
57   friend class gfx::CrossProcessPaint;
58   friend class PWindowGlobalParent;
59 
60  public:
61   NS_DECL_ISUPPORTS_INHERITED
62   NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(WindowGlobalParent,
63                                                          WindowContext)
64 
65   static already_AddRefed<WindowGlobalParent> GetByInnerWindowId(
66       uint64_t aInnerWindowId);
67 
GetByInnerWindowId(const GlobalObject & aGlobal,uint64_t aInnerWindowId)68   static already_AddRefed<WindowGlobalParent> GetByInnerWindowId(
69       const GlobalObject& aGlobal, uint64_t aInnerWindowId) {
70     return GetByInnerWindowId(aInnerWindowId);
71   }
72 
73   // The same as the corresponding methods on `WindowContext`, except that the
74   // return types are already cast to their parent-process type variants, such
75   // as `WindowGlobalParent` or `CanonicalBrowsingContext`.
GetParentWindowContext()76   WindowGlobalParent* GetParentWindowContext() {
77     return static_cast<WindowGlobalParent*>(
78         WindowContext::GetParentWindowContext());
79   }
TopWindowContext()80   WindowGlobalParent* TopWindowContext() {
81     return static_cast<WindowGlobalParent*>(WindowContext::TopWindowContext());
82   }
GetBrowsingContext()83   CanonicalBrowsingContext* GetBrowsingContext() {
84     return CanonicalBrowsingContext::Cast(WindowContext::GetBrowsingContext());
85   }
86 
87   Element* GetRootOwnerElement();
88 
89   // Has this actor been shut down
IsClosed()90   bool IsClosed() { return !CanSend(); }
91 
92   // Get the other side of this actor if it is an in-process actor. Returns
93   // |nullptr| if the actor has been torn down, or is not in-process.
94   already_AddRefed<WindowGlobalChild> GetChildActor();
95 
96   // Get a JS actor object by name.
97   already_AddRefed<JSWindowActorParent> GetActor(JSContext* aCx,
98                                                  const nsACString& aName,
99                                                  ErrorResult& aRv);
100   already_AddRefed<JSWindowActorParent> GetExistingActor(
101       const nsACString& aName);
102 
103   // Get this actor's manager if it is not an in-process actor. Returns
104   // |nullptr| if the actor has been torn down, or is in-process.
105   BrowserParent* GetBrowserParent();
106 
107   ContentParent* GetContentParent();
108 
109   // The principal of this WindowGlobal. This value will not change over the
110   // lifetime of the WindowGlobal object, even to reflect changes in
111   // |document.domain|.
DocumentPrincipal()112   nsIPrincipal* DocumentPrincipal() { return mDocumentPrincipal; }
113 
DocumentStoragePrincipal()114   nsIPrincipal* DocumentStoragePrincipal() { return mDocumentStoragePrincipal; }
115 
116   // The BrowsingContext which this WindowGlobal has been loaded into.
117   // FIXME: It's quite awkward that this method has a slightly different name
118   // than the one on WindowContext.
BrowsingContext()119   CanonicalBrowsingContext* BrowsingContext() override {
120     return GetBrowsingContext();
121   }
122 
123   // Get the root nsFrameLoader object for the tree of BrowsingContext nodes
124   // which this WindowGlobal is a part of. This will be the nsFrameLoader
125   // holding the BrowserParent for remote tabs, and the root content frameloader
126   // for non-remote tabs.
127   already_AddRefed<nsFrameLoader> GetRootFrameLoader();
128 
129   // The current URI which loaded in the document.
GetDocumentURI()130   nsIURI* GetDocumentURI() override { return mDocumentURI; }
131 
GetDocumentTitle(nsAString & aTitle)132   void GetDocumentTitle(nsAString& aTitle) const {
133     aTitle = mDocumentTitle.valueOr(nsString());
134   }
135 
GetContentBlockingAllowListPrincipal()136   nsIPrincipal* GetContentBlockingAllowListPrincipal() const {
137     return mDocContentBlockingAllowListPrincipal;
138   }
139 
GetClientInfo()140   Maybe<ClientInfo> GetClientInfo() { return mClientInfo; }
141 
142   uint64_t ContentParentId();
143 
144   int32_t OsPid();
145 
146   bool IsCurrentGlobal();
147 
148   bool IsProcessRoot();
149 
150   uint32_t ContentBlockingEvents();
151 
152   void GetContentBlockingLog(nsAString& aLog);
153 
IsInitialDocument()154   bool IsInitialDocument() { return mIsInitialDocument; }
155 
156   already_AddRefed<mozilla::dom::Promise> PermitUnload(
157       PermitUnloadAction aAction, uint32_t aTimeout, mozilla::ErrorResult& aRv);
158 
159   void PermitUnload(std::function<void(bool)>&& aResolver);
160 
161   already_AddRefed<mozilla::dom::Promise> DrawSnapshot(
162       const DOMRect* aRect, double aScale, const nsACString& aBackgroundColor,
163       mozilla::ErrorResult& aRv);
164 
165   already_AddRefed<Promise> GetSecurityInfo(ErrorResult& aRv);
166 
167   static already_AddRefed<WindowGlobalParent> CreateDisconnected(
168       const WindowGlobalInit& aInit);
169 
170   // Initialize the mFrameLoader fields for a created WindowGlobalParent. Must
171   // be called after setting the Manager actor.
172   void Init() final;
173 
174   nsIGlobalObject* GetParentObject();
175   JSObject* WrapObject(JSContext* aCx,
176                        JS::Handle<JSObject*> aGivenProto) override;
177 
178   void NotifyContentBlockingEvent(
179       uint32_t aEvent, nsIRequest* aRequest, bool aBlocked,
180       const nsACString& aTrackingOrigin,
181       const nsTArray<nsCString>& aTrackingFullHashes,
182       const Maybe<
183           ContentBlockingNotifier::StorageAccessPermissionGrantedReason>&
184           aReason = Nothing());
185 
GetContentBlockingLog()186   ContentBlockingLog* GetContentBlockingLog() { return &mContentBlockingLog; }
187 
188   nsIDOMProcessParent* GetDomProcess();
189 
CookieJarSettings()190   nsICookieJarSettings* CookieJarSettings() { return mCookieJarSettings; }
191 
GetCookieJarSettings()192   nsICookieJarSettings* GetCookieJarSettings() const {
193     return mCookieJarSettings;
194   }
195 
DocumentHasLoaded()196   bool DocumentHasLoaded() { return mDocumentHasLoaded; }
197 
DocumentHasUserInteracted()198   bool DocumentHasUserInteracted() { return mDocumentHasUserInteracted; }
199 
SandboxFlags()200   uint32_t SandboxFlags() { return mSandboxFlags; }
201 
GetDocumentBlockAllMixedContent()202   bool GetDocumentBlockAllMixedContent() { return mBlockAllMixedContent; }
203 
GetDocumentUpgradeInsecureRequests()204   bool GetDocumentUpgradeInsecureRequests() { return mUpgradeInsecureRequests; }
205 
206   void DidBecomeCurrentWindowGlobal(bool aCurrent);
207 
HttpsOnlyStatus()208   uint32_t HttpsOnlyStatus() { return mHttpsOnlyStatus; }
209 
210   void AddSecurityState(uint32_t aStateFlags);
GetSecurityFlags()211   uint32_t GetSecurityFlags() { return mSecurityState; }
212 
GetSecurityInfo()213   nsITransportSecurityInfo* GetSecurityInfo() { return mSecurityInfo; }
214 
215   const nsACString& GetRemoteType() override;
216 
217   nsresult WriteFormDataAndScrollToSessionStore(
218       const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
219       uint32_t aEpoch);
220 
221   void NotifySessionStoreUpdatesComplete(Element* aEmbedder);
222 
GetSingleChannelId()223   Maybe<uint64_t> GetSingleChannelId() { return mSingleChannelId; }
224 
GetBFCacheStatus()225   uint16_t GetBFCacheStatus() { return mBFCacheStatus; }
226 
227  protected:
228   already_AddRefed<JSActor> InitJSActor(JS::HandleObject aMaybeActor,
229                                         const nsACString& aName,
230                                         ErrorResult& aRv) override;
AsNativeActor()231   mozilla::ipc::IProtocol* AsNativeActor() override { return this; }
232 
233   // IPC messages
234   mozilla::ipc::IPCResult RecvLoadURI(
235       const MaybeDiscarded<dom::BrowsingContext>& aTargetBC,
236       nsDocShellLoadState* aLoadState, bool aSetNavigating);
237   mozilla::ipc::IPCResult RecvInternalLoad(nsDocShellLoadState* aLoadState);
238   mozilla::ipc::IPCResult RecvUpdateDocumentURI(nsIURI* aURI);
239   mozilla::ipc::IPCResult RecvUpdateDocumentPrincipal(
240       nsIPrincipal* aNewDocumentPrincipal,
241       nsIPrincipal* aNewDocumentStoragePrincipal);
242   mozilla::ipc::IPCResult RecvUpdateDocumentHasLoaded(bool aDocumentHasLoaded);
243   mozilla::ipc::IPCResult RecvUpdateDocumentHasUserInteracted(
244       bool aDocumentHasUserInteracted);
245   mozilla::ipc::IPCResult RecvUpdateSandboxFlags(uint32_t aSandboxFlags);
246   mozilla::ipc::IPCResult RecvUpdateDocumentCspSettings(
247       bool aBlockAllMixedContent, bool aUpgradeInsecureRequests);
248   mozilla::ipc::IPCResult RecvUpdateDocumentTitle(const nsString& aTitle);
249   mozilla::ipc::IPCResult RecvUpdateHttpsOnlyStatus(uint32_t aHttpsOnlyStatus);
RecvSetIsInitialDocument(bool aIsInitialDocument)250   mozilla::ipc::IPCResult RecvSetIsInitialDocument(bool aIsInitialDocument) {
251     mIsInitialDocument = aIsInitialDocument;
252     return IPC_OK();
253   }
254   mozilla::ipc::IPCResult RecvUpdateDocumentSecurityInfo(
255       nsITransportSecurityInfo* aSecurityInfo);
256   mozilla::ipc::IPCResult RecvSetClientInfo(
257       const IPCClientInfo& aIPCClientInfo);
258   mozilla::ipc::IPCResult RecvDestroy();
259   mozilla::ipc::IPCResult RecvRawMessage(
260       const JSActorMessageMeta& aMeta, const Maybe<ClonedMessageData>& aData,
261       const Maybe<ClonedMessageData>& aStack);
262 
263   mozilla::ipc::IPCResult RecvGetContentBlockingEvents(
264       GetContentBlockingEventsResolver&& aResolver);
265   mozilla::ipc::IPCResult RecvUpdateCookieJarSettings(
266       const CookieJarSettingsArgs& aCookieJarSettingsArgs);
267 
268   void ActorDestroy(ActorDestroyReason aWhy) override;
269 
270   void DrawSnapshotInternal(gfx::CrossProcessPaint* aPaint,
271                             const Maybe<IntRect>& aRect, float aScale,
272                             nscolor aBackgroundColor, uint32_t aFlags);
273 
274   // WebShare API - try to share
275   mozilla::ipc::IPCResult RecvShare(IPCWebShareData&& aData,
276                                     ShareResolver&& aResolver);
277 
278   mozilla::ipc::IPCResult RecvCheckPermitUnload(
279       bool aHasInProcessBlocker, XPCOMPermitUnloadAction aAction,
280       CheckPermitUnloadResolver&& aResolver);
281 
282   mozilla::ipc::IPCResult RecvExpectPageUseCounters(
283       const MaybeDiscarded<dom::WindowContext>& aTop);
284   mozilla::ipc::IPCResult RecvAccumulatePageUseCounters(
285       const UseCounters& aUseCounters);
286 
287   mozilla::ipc::IPCResult RecvRequestRestoreTabContent();
288 
289   mozilla::ipc::IPCResult RecvUpdateSessionStore(
290       const Maybe<FormData>& aFormData, const Maybe<nsPoint>& aScrollPosition,
291       uint32_t aEpoch);
292 
293   mozilla::ipc::IPCResult RecvResetSessionStore(uint32_t aEpoch);
294 
295   mozilla::ipc::IPCResult RecvUpdateBFCacheStatus(const uint16_t& aOnFlags,
296                                                   const uint16_t& aOffFlags);
297 
298  public:
299   mozilla::ipc::IPCResult RecvSetSingleChannelId(
300       const Maybe<uint64_t>& aSingleChannelId);
301 
302   mozilla::ipc::IPCResult RecvSetDocumentDomain(nsIURI* aDomain);
303 
304  private:
305   WindowGlobalParent(CanonicalBrowsingContext* aBrowsingContext,
306                      uint64_t aInnerWindowId, uint64_t aOuterWindowId,
307                      FieldValues&& aInit);
308 
309   ~WindowGlobalParent();
310 
311   bool ShouldTrackSiteOriginTelemetry();
312   void FinishAccumulatingPageUseCounters();
313 
314   nsresult ResetSessionStore(uint32_t aEpoch);
315 
316   // Returns failure if the new storage principal cannot be validated
317   // against the current document principle.
318   nsresult SetDocumentStoragePrincipal(
319       nsIPrincipal* aNewDocumentStoragePrincipal);
320 
321   // NOTE: Neither this document principal nor the document storage
322   // principal doesn't reflect possible |document.domain| mutations
323   // which may have been made in the actual document.
324   nsCOMPtr<nsIPrincipal> mDocumentPrincipal;
325   nsCOMPtr<nsIPrincipal> mDocumentStoragePrincipal;
326 
327   // The principal to use for the content blocking allow list.
328   nsCOMPtr<nsIPrincipal> mDocContentBlockingAllowListPrincipal;
329 
330   nsCOMPtr<nsIURI> mDocumentURI;
331   Maybe<nsString> mDocumentTitle;
332 
333   bool mIsInitialDocument;
334 
335   // True if this window has a "beforeunload" event listener.
336   bool mHasBeforeUnload;
337 
338   // The log of all content blocking actions taken on the document related to
339   // this WindowGlobalParent. This is only stored on top-level documents and
340   // includes the activity log for all of the nested subdocuments as well.
341   ContentBlockingLog mContentBlockingLog;
342 
343   uint32_t mSecurityState = 0;
344 
345   Maybe<ClientInfo> mClientInfo;
346   // Fields being mirrored from the corresponding document
347   nsCOMPtr<nsICookieJarSettings> mCookieJarSettings;
348   nsCOMPtr<nsITransportSecurityInfo> mSecurityInfo;
349 
350   uint32_t mSandboxFlags;
351 
352   struct OriginCounter {
353     void UpdateSiteOriginsFrom(WindowGlobalParent* aParent, bool aIncrease);
354     void Accumulate();
355 
356     nsTHashMap<nsCStringHashKey, int32_t> mOriginMap;
357     uint32_t mMaxOrigins = 0;
358   };
359 
360   // Used to collect unique site origin telemetry.
361   //
362   // Is only Some() on top-level content windows.
363   Maybe<OriginCounter> mOriginCounter;
364 
365   bool mDocumentHasLoaded;
366   bool mDocumentHasUserInteracted;
367   bool mDocumentTreeWouldPreloadResources = false;
368   bool mBlockAllMixedContent;
369   bool mUpgradeInsecureRequests;
370 
371   // HTTPS-Only Mode flags
372   uint32_t mHttpsOnlyStatus;
373 
374   // The window of the document whose page use counters our document's use
375   // counters will contribute to.  (If we are a top-level document, this
376   // will point to ourselves.)
377   RefPtr<WindowGlobalParent> mPageUseCountersWindow;
378 
379   // Our page use counters, if we are a top-level document.
380   UniquePtr<PageUseCounters> mPageUseCounters;
381 
382   // Whether we have sent our page use counters, and so should ignore any
383   // subsequent ExpectPageUseCounters calls.
384   bool mSentPageUseCounters = false;
385 
386   uint16_t mBFCacheStatus = 0;
387 
388   // mSingleChannelId records whether the loadgroup contains a single request
389   // with an id. If there is one channel in the loadgroup and it has an id then
390   // mSingleChannelId is set to Some(id) (ids are non-zero). If there is one
391   // request in the loadgroup and it's not a channel or it doesn't have an id,
392   // or there are multiple requests in the loadgroup, then mSingleChannelId is
393   // set to Some(0). If there are no requests in the loadgroup then
394   // mSingleChannelId is set to Nothing().
395   // Note: We ignore favicon loads when considering the requests in the
396   // loadgroup.
397   Maybe<uint64_t> mSingleChannelId;
398 };
399 
400 }  // namespace dom
401 }  // namespace mozilla
402 
ToSupports(mozilla::dom::WindowGlobalParent * aWindowGlobal)403 inline nsISupports* ToSupports(
404     mozilla::dom::WindowGlobalParent* aWindowGlobal) {
405   return static_cast<mozilla::dom::WindowContext*>(aWindowGlobal);
406 }
407 
408 #endif  // !defined(mozilla_dom_WindowGlobalParent_h)
409