ClientManagerService.h (5610B)
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_ClientManagerService_h 7 #define _mozilla_dom_ClientManagerService_h 8 9 #include "ClientHandleParent.h" 10 #include "ClientOpPromise.h" 11 #include "mozilla/AlreadyAddRefed.h" 12 #include "mozilla/Assertions.h" 13 #include "mozilla/Maybe.h" 14 #include "mozilla/MozPromise.h" 15 #include "mozilla/RefPtr.h" 16 #include "mozilla/Variant.h" 17 #include "mozilla/dom/ClientIPCTypes.h" 18 #include "mozilla/dom/ipc/IdType.h" 19 #include "nsHashKeys.h" 20 #include "nsISupports.h" 21 #include "nsTArray.h" 22 #include "nsTHashMap.h" 23 24 struct nsID; 25 26 namespace mozilla { 27 28 namespace ipc { 29 30 class PrincipalInfo; 31 32 } // namespace ipc 33 34 namespace dom { 35 36 class ClientManagerParent; 37 class ClientSourceParent; 38 class ClientHandleParent; 39 class ThreadsafeContentParentHandle; 40 41 // Define a singleton service to manage client activity throughout the 42 // browser. This service runs on the PBackground thread. To interact 43 // it with it please use the ClientManager and ClientHandle classes. 44 class ClientManagerService final { 45 // Placeholder type that represents a ClientSourceParent that may be created 46 // in the future (e.g. while a redirect chain is being resolved). 47 // 48 // Each FutureClientSourceParent has a promise that callbacks may be chained 49 // to; the promise will be resolved when the associated ClientSourceParent is 50 // created or rejected when it's known that it'll never be created. 51 class FutureClientSourceParent { 52 public: 53 explicit FutureClientSourceParent(const IPCClientInfo& aClientInfo); 54 55 const mozilla::ipc::PrincipalInfo& PrincipalInfo() const { 56 return mPrincipalInfo; 57 } 58 59 already_AddRefed<SourcePromise> Promise() { 60 return mPromiseHolder.Ensure(__func__); 61 } 62 63 void ResolvePromiseIfExists() { 64 mPromiseHolder.ResolveIfExists(true, __func__); 65 } 66 67 void RejectPromiseIfExists(const CopyableErrorResult& aRv) { 68 MOZ_ASSERT(aRv.Failed()); 69 mPromiseHolder.RejectIfExists(aRv, __func__); 70 } 71 72 void SetAsAssociated() { mAssociated = true; } 73 74 bool IsAssociated() const { return mAssociated; } 75 76 private: 77 const mozilla::ipc::PrincipalInfo mPrincipalInfo; 78 MozPromiseHolder<SourcePromise> mPromiseHolder; 79 RefPtr<ClientManagerService> mService = ClientManagerService::GetInstance(); 80 bool mAssociated; 81 }; 82 83 using SourceTableEntry = 84 Variant<FutureClientSourceParent, ClientSourceParent*>; 85 86 // Store the possible ClientSourceParent objects in a hash table. We want to 87 // optimize for insertion, removal, and lookup by UUID. 88 nsTHashMap<nsIDHashKey, SourceTableEntry> mSourceTable; 89 90 nsTArray<ClientManagerParent*> mManagerList; 91 92 bool mShutdown; 93 94 ClientManagerService(); 95 ~ClientManagerService(); 96 97 void Shutdown(); 98 99 // Returns nullptr if aEntry isn't a ClientSourceParent (i.e. it's a 100 // FutureClientSourceParent). 101 ClientSourceParent* MaybeUnwrapAsExistingSource( 102 const SourceTableEntry& aEntry) const; 103 104 public: 105 static already_AddRefed<ClientManagerService> GetOrCreateInstance(); 106 107 // Returns nullptr if the service is not already created. 108 static already_AddRefed<ClientManagerService> GetInstance(); 109 110 bool AddSource(ClientSourceParent* aSource); 111 112 bool RemoveSource(ClientSourceParent* aSource); 113 114 // Returns true when a FutureClientSourceParent is successfully added. 115 bool ExpectFutureSource(const IPCClientInfo& aClientInfo); 116 117 // May still be called if it's possible that the FutureClientSourceParent 118 // no longer exists. 119 void ForgetFutureSource(const IPCClientInfo& aClientInfo); 120 121 // Returns a promise that resolves if/when the ClientSourceParent exists and 122 // rejects if/when it's known that the ClientSourceParent will never exist or 123 // if it's frozen. Note that the ClientSourceParent may not exist anymore 124 // by the time promise callbacks run. 125 RefPtr<SourcePromise> FindSource( 126 const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo); 127 128 // Returns nullptr if the ClientSourceParent doesn't exist yet (i.e. it's a 129 // FutureClientSourceParent or has already been destroyed) or is frozen. 130 ClientSourceParent* FindExistingSource( 131 const nsID& aID, const mozilla::ipc::PrincipalInfo& aPrincipalInfo) const; 132 133 void AddManager(ClientManagerParent* aManager); 134 135 void RemoveManager(ClientManagerParent* aManager); 136 137 RefPtr<ClientOpPromise> Navigate( 138 ThreadsafeContentParentHandle* aOriginContent, 139 const ClientNavigateArgs& aArgs); 140 141 RefPtr<ClientOpPromise> MatchAll( 142 ThreadsafeContentParentHandle* aOriginContent, 143 const ClientMatchAllArgs& aArgs); 144 145 RefPtr<ClientOpPromise> Claim(ThreadsafeContentParentHandle* aOriginContent, 146 const ClientClaimArgs& aArgs); 147 148 RefPtr<ClientOpPromise> GetInfoAndState( 149 ThreadsafeContentParentHandle* aOriginContent, 150 const ClientGetInfoAndStateArgs& aArgs); 151 152 RefPtr<ClientOpPromise> OpenWindow( 153 ThreadsafeContentParentHandle* aOriginContent, 154 const ClientOpenWindowArgs& aArgs); 155 156 bool HasWindow(const Maybe<ContentParentId>& aContentParentId, 157 const mozilla::ipc::PrincipalInfo& aPrincipalInfo, 158 const nsID& aClientId); 159 160 NS_INLINE_DECL_REFCOUNTING(mozilla::dom::ClientManagerService) 161 }; 162 163 } // namespace dom 164 } // namespace mozilla 165 166 #endif // _mozilla_dom_ClientManagerService_h