Line data Source code
1 : /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 : /* This Source Code Form is subject to the terms of the Mozilla Public
3 : * License, v. 2.0. If a copy of the MPL was not distributed with this
4 : * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 :
6 : #ifndef GMPServiceParent_h_
7 : #define GMPServiceParent_h_
8 :
9 : #include "GMPService.h"
10 : #include "mozilla/gmp/PGMPServiceParent.h"
11 : #include "mozIGeckoMediaPluginChromeService.h"
12 : #include "nsClassHashtable.h"
13 : #include "nsDataHashtable.h"
14 : #include "mozilla/Atomics.h"
15 : #include "nsIAsyncShutdown.h"
16 : #include "nsThreadUtils.h"
17 : #include "mozilla/MozPromise.h"
18 : #include "GMPStorage.h"
19 :
20 : template <class> struct already_AddRefed;
21 :
22 : namespace mozilla {
23 : namespace gmp {
24 :
25 : class GMPParent;
26 : class GMPServiceParent;
27 :
28 : class GeckoMediaPluginServiceParent final : public GeckoMediaPluginService
29 : , public mozIGeckoMediaPluginChromeService
30 : , public nsIAsyncShutdownBlocker
31 : {
32 : public:
33 : static already_AddRefed<GeckoMediaPluginServiceParent> GetSingleton();
34 :
35 : GeckoMediaPluginServiceParent();
36 : nsresult Init() override;
37 :
38 : NS_DECL_ISUPPORTS_INHERITED
39 : NS_DECL_NSIASYNCSHUTDOWNBLOCKER
40 :
41 : // mozIGeckoMediaPluginService
42 : NS_IMETHOD HasPluginForAPI(const nsACString& aAPI,
43 : nsTArray<nsCString>* aTags,
44 : bool *aRetVal) override;
45 : NS_IMETHOD GetNodeId(const nsAString& aOrigin,
46 : const nsAString& aTopLevelOrigin,
47 : const nsAString& aGMPName,
48 : UniquePtr<GetNodeIdCallback>&& aCallback) override;
49 :
50 : NS_DECL_MOZIGECKOMEDIAPLUGINCHROMESERVICE
51 : NS_DECL_NSIOBSERVER
52 :
53 : RefPtr<GenericPromise> EnsureInitialized();
54 : RefPtr<GenericPromise> AsyncAddPluginDirectory(const nsAString& aDirectory);
55 :
56 : // GMP thread access only
57 : bool IsShuttingDown();
58 :
59 : already_AddRefed<GMPStorage> GetMemoryStorageFor(const nsACString& aNodeId);
60 : nsresult ForgetThisSiteNative(const nsAString& aSite,
61 : const mozilla::OriginAttributesPattern& aPattern);
62 :
63 : // Notifies that some user of this class is created/destroyed.
64 : void ServiceUserCreated(GMPServiceParent* aServiceParent);
65 : void ServiceUserDestroyed(GMPServiceParent* aServiceParent);
66 :
67 : void UpdateContentProcessGMPCapabilities();
68 :
69 : AbstractThread* MainThread() const { return mMainThread; }
70 :
71 : private:
72 : friend class GMPServiceParent;
73 :
74 : virtual ~GeckoMediaPluginServiceParent();
75 :
76 : void ClearStorage();
77 :
78 : already_AddRefed<GMPParent> SelectPluginForAPI(const nsACString& aNodeId,
79 : const nsCString& aAPI,
80 : const nsTArray<nsCString>& aTags);
81 :
82 : already_AddRefed<GMPParent> FindPluginForAPIFrom(size_t aSearchStartIndex,
83 : const nsCString& aAPI,
84 : const nsTArray<nsCString>& aTags,
85 : size_t* aOutPluginIndex);
86 :
87 : nsresult GetNodeId(const nsAString& aOrigin, const nsAString& aTopLevelOrigin,
88 : const nsAString& aGMPName, nsACString& aOutId);
89 :
90 : void UnloadPlugins();
91 : void CrashPlugins();
92 : void NotifySyncShutdownComplete();
93 :
94 : void ProcessPossiblePlugin(nsIFile* aDir);
95 :
96 : void RemoveOnGMPThread(const nsAString& aDirectory,
97 : const bool aDeleteFromDisk,
98 : const bool aCanDefer);
99 :
100 0 : struct DirectoryFilter {
101 : virtual bool operator()(nsIFile* aPath) = 0;
102 0 : ~DirectoryFilter() {}
103 : };
104 : void ClearNodeIdAndPlugin(DirectoryFilter& aFilter);
105 : void ClearNodeIdAndPlugin(nsIFile* aPluginStorageDir,
106 : DirectoryFilter& aFilter);
107 : void ForgetThisSiteOnGMPThread(const nsACString& aOrigin,
108 : const mozilla::OriginAttributesPattern& aPattern);
109 : void ClearRecentHistoryOnGMPThread(PRTime aSince);
110 :
111 : already_AddRefed<GMPParent> GetById(uint32_t aPluginId);
112 :
113 : protected:
114 : friend class GMPParent;
115 : void ReAddOnGMPThread(const RefPtr<GMPParent>& aOld);
116 : void PluginTerminated(const RefPtr<GMPParent>& aOld);
117 : void InitializePlugins(AbstractThread* aAbstractGMPThread) override;
118 : RefPtr<GenericPromise::AllPromiseType> LoadFromEnvironment();
119 : RefPtr<GenericPromise> AddOnGMPThread(nsString aDirectory);
120 :
121 : virtual RefPtr<GetGMPContentParentPromise> GetContentParent(
122 : GMPCrashHelper* aHelper,
123 : const nsACString& aNodeIdString,
124 : const nsCString& aAPI,
125 : const nsTArray<nsCString>& aTags) override;
126 :
127 : RefPtr<GetGMPContentParentPromise> GetContentParent(
128 : GMPCrashHelper* aHelper,
129 : const NodeId& aNodeId,
130 : const nsCString& aAPI,
131 : const nsTArray<nsCString>& aTags) override;
132 :
133 : private:
134 : // Creates a copy of aOriginal. Note that the caller is responsible for
135 : // adding this to GeckoMediaPluginServiceParent::mPlugins.
136 : already_AddRefed<GMPParent> ClonePlugin(const GMPParent* aOriginal);
137 : nsresult EnsurePluginsOnDiskScanned();
138 : nsresult InitStorage();
139 :
140 0 : class PathRunnable : public Runnable
141 : {
142 : public:
143 : enum EOperation {
144 : REMOVE,
145 : REMOVE_AND_DELETE_FROM_DISK,
146 : };
147 :
148 0 : PathRunnable(GeckoMediaPluginServiceParent* aService,
149 : const nsAString& aPath,
150 : EOperation aOperation,
151 : bool aDefer = false)
152 0 : : Runnable("gmp::GeckoMediaPluginServiceParent::PathRunnable")
153 : , mService(aService)
154 : , mPath(aPath)
155 : , mOperation(aOperation)
156 0 : , mDefer(aDefer)
157 0 : { }
158 :
159 : NS_DECL_NSIRUNNABLE
160 :
161 : private:
162 : RefPtr<GeckoMediaPluginServiceParent> mService;
163 : nsString mPath;
164 : EOperation mOperation;
165 : bool mDefer;
166 : };
167 :
168 : // Protected by mMutex from the base class.
169 : nsTArray<RefPtr<GMPParent>> mPlugins;
170 : bool mShuttingDown;
171 :
172 : // True if we've inspected MOZ_GMP_PATH on the GMP thread and loaded any
173 : // plugins found there into mPlugins.
174 : Atomic<bool> mScannedPluginOnDisk;
175 :
176 : template<typename T>
177 : class MainThreadOnly {
178 : public:
179 1 : MOZ_IMPLICIT MainThreadOnly(T aValue)
180 1 : : mValue(aValue)
181 1 : {}
182 0 : operator T&() {
183 0 : MOZ_ASSERT(NS_IsMainThread());
184 0 : return mValue;
185 : }
186 :
187 : private:
188 : T mValue;
189 : };
190 :
191 : MainThreadOnly<bool> mWaitingForPluginsSyncShutdown;
192 :
193 : nsTArray<nsString> mPluginsWaitingForDeletion;
194 :
195 : nsCOMPtr<nsIFile> mStorageBaseDir;
196 :
197 : // Hashes of (origin,topLevelOrigin) to the node id for
198 : // non-persistent sessions.
199 : nsClassHashtable<nsUint32HashKey, nsCString> mTempNodeIds;
200 :
201 : // Hashes node id to whether that node id is allowed to store data
202 : // persistently on disk.
203 : nsDataHashtable<nsCStringHashKey, bool> mPersistentStorageAllowed;
204 :
205 : // Synchronization for barrier that ensures we've loaded GMPs from
206 : // MOZ_GMP_PATH before allowing GetContentParentFrom() to proceed.
207 : Monitor mInitPromiseMonitor;
208 : MozPromiseHolder<GenericPromise> mInitPromise;
209 : bool mLoadPluginsFromDiskComplete;
210 :
211 : // Hashes nodeId to the hashtable of storage for that nodeId.
212 : nsRefPtrHashtable<nsCStringHashKey, GMPStorage> mTempGMPStorage;
213 :
214 : // Tracks how many IPC connections to GMPServices running in content
215 : // processes we have. When this is empty we can safely shut down.
216 : // Synchronized across thread via mMutex in base class.
217 : nsTArray<GMPServiceParent*> mServiceParents;
218 :
219 : const RefPtr<AbstractThread> mMainThread;
220 : };
221 :
222 : nsresult ReadSalt(nsIFile* aPath, nsACString& aOutData);
223 : bool MatchOrigin(nsIFile* aPath,
224 : const nsACString& aSite,
225 : const mozilla::OriginAttributesPattern& aPattern);
226 :
227 : class GMPServiceParent final : public PGMPServiceParent
228 : {
229 : public:
230 : explicit GMPServiceParent(GeckoMediaPluginServiceParent* aService);
231 : virtual ~GMPServiceParent();
232 :
233 : ipc::IPCResult RecvGetGMPNodeId(const nsString& aOrigin,
234 : const nsString& aTopLevelOrigin,
235 : const nsString& aGMPName,
236 : nsCString* aID) override;
237 : void ActorDestroy(ActorDestroyReason aWhy) override;
238 :
239 : static bool Create(Endpoint<PGMPServiceParent>&& aGMPService);
240 :
241 : ipc::IPCResult RecvLaunchGMP(const nsCString& aNodeId,
242 : const nsCString& aAPI,
243 : nsTArray<nsCString>&& aTags,
244 : nsTArray<ProcessId>&& aAlreadyBridgedTo,
245 : uint32_t* aOutPluginId,
246 : ProcessId* aOutID,
247 : nsCString* aOutDisplayName,
248 : Endpoint<PGMPContentParent>* aOutEndpoint,
249 : nsresult* aOutRv) override;
250 :
251 : ipc::IPCResult RecvLaunchGMPForNodeId(
252 : const NodeIdData& nodeId,
253 : const nsCString& aAPI,
254 : nsTArray<nsCString>&& aTags,
255 : nsTArray<ProcessId>&& aAlreadyBridgedTo,
256 : uint32_t* aOutPluginId,
257 : ProcessId* aOutID,
258 : nsCString* aOutDisplayName,
259 : Endpoint<PGMPContentParent>* aOutEndpoint,
260 : nsresult* aOutRv) override;
261 :
262 : private:
263 : void CloseTransport(Monitor* aSyncMonitor, bool* aCompleted);
264 :
265 : RefPtr<GeckoMediaPluginServiceParent> mService;
266 : };
267 :
268 : } // namespace gmp
269 : } // namespace mozilla
270 :
271 : #endif // GMPServiceParent_h_
|