/src/mozilla-central/dom/plugins/base/nsPluginHost.h
Line | Count | Source (jump to first uncovered line) |
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 nsPluginHost_h_ |
7 | | #define nsPluginHost_h_ |
8 | | |
9 | | #include "mozilla/LinkedList.h" |
10 | | #include "mozilla/StaticPtr.h" |
11 | | |
12 | | #include "nsIPluginHost.h" |
13 | | #include "nsIObserver.h" |
14 | | #include "nsCOMPtr.h" |
15 | | #include "prlink.h" |
16 | | #include "nsIPluginTag.h" |
17 | | #include "nsPluginsDir.h" |
18 | | #include "nsPluginDirServiceProvider.h" |
19 | | #include "nsWeakPtr.h" |
20 | | #include "nsIPrompt.h" |
21 | | #include "nsWeakReference.h" |
22 | | #include "MainThreadUtils.h" |
23 | | #include "nsTArray.h" |
24 | | #include "nsINamed.h" |
25 | | #include "nsTObserverArray.h" |
26 | | #include "nsITimer.h" |
27 | | #include "nsPluginTags.h" |
28 | | #include "nsIEffectiveTLDService.h" |
29 | | #include "nsIIDNService.h" |
30 | | #include "nsCRT.h" |
31 | | #include "mozilla/dom/PromiseNativeHandler.h" |
32 | | |
33 | | #ifdef XP_WIN |
34 | | #include <minwindef.h> |
35 | | #include "nsIWindowsRegKey.h" |
36 | | #endif |
37 | | |
38 | | namespace mozilla { |
39 | | namespace plugins { |
40 | | class FakePluginTag; |
41 | | class PluginTag; |
42 | | class BlocklistPromiseHandler; |
43 | | } // namespace plugins |
44 | | } // namespace mozilla |
45 | | |
46 | | class nsNPAPIPlugin; |
47 | | class nsIFile; |
48 | | class nsIChannel; |
49 | | class nsPluginNativeWindow; |
50 | | class nsObjectLoadingContent; |
51 | | class nsPluginInstanceOwner; |
52 | | class nsPluginUnloadRunnable; |
53 | | class nsNPAPIPluginInstance; |
54 | | class nsNPAPIPluginStreamListener; |
55 | | class nsIPluginInstanceOwner; |
56 | | class nsIInputStream; |
57 | | class nsIStreamListener; |
58 | | #ifndef npapi_h_ |
59 | | struct _NPP; |
60 | | typedef _NPP* NPP; |
61 | | #endif |
62 | | |
63 | | class nsInvalidPluginTag : public nsISupports |
64 | | { |
65 | | virtual ~nsInvalidPluginTag(); |
66 | | public: |
67 | | explicit nsInvalidPluginTag(const char* aFullPath, int64_t aLastModifiedTime = 0); |
68 | | |
69 | | NS_DECL_ISUPPORTS |
70 | | |
71 | | nsCString mFullPath; |
72 | | int64_t mLastModifiedTime; |
73 | | bool mSeen; |
74 | | |
75 | | RefPtr<nsInvalidPluginTag> mPrev; |
76 | | RefPtr<nsInvalidPluginTag> mNext; |
77 | | }; |
78 | | |
79 | | class nsPluginHost final : public nsIPluginHost, |
80 | | public nsIObserver, |
81 | | public nsITimerCallback, |
82 | | public nsSupportsWeakReference, |
83 | | public nsINamed |
84 | | { |
85 | | friend class nsPluginTag; |
86 | | friend class nsFakePluginTag; |
87 | | virtual ~nsPluginHost(); |
88 | | |
89 | | public: |
90 | | nsPluginHost(); |
91 | | |
92 | | static already_AddRefed<nsPluginHost> GetInst(); |
93 | | |
94 | | NS_DECL_ISUPPORTS |
95 | | NS_DECL_NSIPLUGINHOST |
96 | | NS_DECL_NSIOBSERVER |
97 | | NS_DECL_NSITIMERCALLBACK |
98 | | NS_DECL_NSINAMED |
99 | | |
100 | | nsresult LoadPlugins(); |
101 | | nsresult UnloadPlugins(); |
102 | | |
103 | | nsresult SetUpPluginInstance(const nsACString &aMimeType, |
104 | | nsIURI *aURL, |
105 | | nsPluginInstanceOwner *aOwner); |
106 | | |
107 | | // Acts like a bitfield |
108 | | enum PluginFilter { |
109 | | eExcludeNone = nsIPluginHost::EXCLUDE_NONE, |
110 | | eExcludeDisabled = nsIPluginHost::EXCLUDE_DISABLED, |
111 | | eExcludeFake = nsIPluginHost::EXCLUDE_FAKE |
112 | | }; |
113 | | // FIXME-jsplugins comment about fake |
114 | | bool HavePluginForType(const nsACString & aMimeType, |
115 | | PluginFilter aFilter = eExcludeDisabled); |
116 | | |
117 | | // FIXME-jsplugins what if fake has different extensions |
118 | | bool HavePluginForExtension(const nsACString & aExtension, |
119 | | /* out */ nsACString & aMimeType, |
120 | | PluginFilter aFilter = eExcludeDisabled); |
121 | | |
122 | | void GetPlugins(nsTArray<nsCOMPtr<nsIInternalPluginTag>>& aPluginArray, |
123 | | bool aIncludeDisabled = false); |
124 | | |
125 | | nsresult FindPluginsForContent(uint32_t aPluginEpoch, |
126 | | nsTArray<mozilla::plugins::PluginTag>* aPlugins, |
127 | | nsTArray<mozilla::plugins::FakePluginTag>* aFakePlugins, |
128 | | uint32_t* aNewPluginEpoch); |
129 | | |
130 | | nsresult GetURL(nsISupports* pluginInst, |
131 | | const char* url, |
132 | | const char* target, |
133 | | nsNPAPIPluginStreamListener* streamListener, |
134 | | const char* altHost, |
135 | | const char* referrer, |
136 | | bool forceJSEnabled); |
137 | | nsresult PostURL(nsISupports* pluginInst, |
138 | | const char* url, |
139 | | uint32_t postDataLen, |
140 | | const char* postData, |
141 | | const char* target, |
142 | | nsNPAPIPluginStreamListener* streamListener, |
143 | | const char* altHost, |
144 | | const char* referrer, |
145 | | bool forceJSEnabled, |
146 | | uint32_t postHeadersLength, |
147 | | const char* postHeaders); |
148 | | |
149 | | nsresult UserAgent(const char **retstring); |
150 | | nsresult ParsePostBufferToFixHeaders(const char *inPostData, |
151 | | uint32_t inPostDataLen, |
152 | | char **outPostData, |
153 | | uint32_t *outPostDataLen); |
154 | | nsresult NewPluginNativeWindow(nsPluginNativeWindow ** aPluginNativeWindow); |
155 | | |
156 | | void AddIdleTimeTarget(nsIPluginInstanceOwner* objectFrame, bool isVisible); |
157 | | void RemoveIdleTimeTarget(nsIPluginInstanceOwner* objectFrame); |
158 | | |
159 | | nsresult GetPluginName(nsNPAPIPluginInstance *aPluginInstance, |
160 | | const char** aPluginName); |
161 | | nsresult StopPluginInstance(nsNPAPIPluginInstance* aInstance); |
162 | | nsresult GetPluginTagForInstance(nsNPAPIPluginInstance *aPluginInstance, |
163 | | nsIPluginTag **aPluginTag); |
164 | | |
165 | | nsresult |
166 | | NewPluginURLStream(const nsString& aURL, |
167 | | nsNPAPIPluginInstance *aInstance, |
168 | | nsNPAPIPluginStreamListener *aListener, |
169 | | nsIInputStream *aPostStream = nullptr, |
170 | | const char *aHeadersData = nullptr, |
171 | | uint32_t aHeadersDataLen = 0); |
172 | | |
173 | | nsresult |
174 | | GetURLWithHeaders(nsNPAPIPluginInstance *pluginInst, |
175 | | const char* url, |
176 | | const char* target = nullptr, |
177 | | nsNPAPIPluginStreamListener* streamListener = nullptr, |
178 | | const char* altHost = nullptr, |
179 | | const char* referrer = nullptr, |
180 | | bool forceJSEnabled = false, |
181 | | uint32_t getHeadersLength = 0, |
182 | | const char* getHeaders = nullptr); |
183 | | |
184 | | nsresult |
185 | | AddHeadersToChannel(const char *aHeadersData, uint32_t aHeadersDataLen, |
186 | | nsIChannel *aGenericChannel); |
187 | | |
188 | | // Helper that checks if a type is whitelisted in plugin.allowed_types. |
189 | | // Always returns true if plugin.allowed_types is not set |
190 | | static bool IsTypeWhitelisted(const char *aType); |
191 | | |
192 | | // Helper that checks if a plugin of a given MIME type can be loaded by the |
193 | | // parent process. It checks the plugin.load_in_parent_process.<mime> pref. |
194 | | // Always returns false if plugin.load_in_parent_process.<mime> is not set. |
195 | | static bool ShouldLoadTypeInParent(const nsACString& aMimeType); |
196 | | |
197 | | /** |
198 | | * Returns true if a plugin can be used to load the requested MIME type. Used |
199 | | * for short circuiting before sending things to plugin code. |
200 | | */ |
201 | | static bool |
202 | | CanUsePluginForMIMEType(const nsACString& aMIMEType); |
203 | | |
204 | | // checks whether aType is a type we recognize for potential special handling |
205 | | enum SpecialType { |
206 | | eSpecialType_None, |
207 | | // Needed to whitelist for async init support |
208 | | eSpecialType_Test, |
209 | | // Informs some decisions about OOP and quirks |
210 | | eSpecialType_Flash |
211 | | }; |
212 | | static SpecialType GetSpecialType(const nsACString & aMIMEType); |
213 | | |
214 | | static nsresult PostPluginUnloadEvent(PRLibrary* aLibrary); |
215 | | |
216 | | void PluginCrashed(nsNPAPIPlugin* plugin, |
217 | | const nsAString& pluginDumpID, |
218 | | const nsAString& browserDumpID); |
219 | | |
220 | | nsNPAPIPluginInstance *FindInstance(const char *mimetype); |
221 | | nsNPAPIPluginInstance *FindOldestStoppedInstance(); |
222 | | uint32_t StoppedInstanceCount(); |
223 | | |
224 | | nsTArray< RefPtr<nsNPAPIPluginInstance> > *InstanceArray(); |
225 | | |
226 | | // Return the tag for |aLibrary| if found, nullptr if not. |
227 | | nsPluginTag* FindTagForLibrary(PRLibrary* aLibrary); |
228 | | |
229 | | // The last argument should be false if we already have an in-flight stream |
230 | | // and don't need to set up a new stream. |
231 | | nsresult InstantiatePluginInstance(const nsACString& aMimeType, nsIURI* aURL, |
232 | | nsObjectLoadingContent *aContent, |
233 | | nsPluginInstanceOwner** aOwner); |
234 | | |
235 | | // Does not accept nullptr and should never fail. |
236 | | nsPluginTag* TagForPlugin(nsNPAPIPlugin* aPlugin); |
237 | | |
238 | | nsPluginTag* PluginWithId(uint32_t aId); |
239 | | |
240 | | nsresult GetPlugin(const nsACString &aMimeType, nsNPAPIPlugin** aPlugin); |
241 | | nsresult GetPluginForContentProcess(uint32_t aPluginId, nsNPAPIPlugin** aPlugin); |
242 | | void NotifyContentModuleDestroyed(uint32_t aPluginId); |
243 | | |
244 | | nsresult NewPluginStreamListener(nsIURI* aURL, |
245 | | nsNPAPIPluginInstance* aInstance, |
246 | | nsIStreamListener **aStreamListener); |
247 | | |
248 | | void CreateWidget(nsPluginInstanceOwner* aOwner); |
249 | | |
250 | | nsresult EnumerateSiteData(const nsACString& domain, |
251 | | const InfallibleTArray<nsCString>& sites, |
252 | | InfallibleTArray<nsCString>& result, |
253 | | bool firstMatchOnly); |
254 | | |
255 | | nsresult SendPluginsToContent(); |
256 | | nsresult SetPluginsInContent(uint32_t aPluginEpoch, |
257 | | nsTArray<mozilla::plugins::PluginTag>& aPlugins, |
258 | | nsTArray<mozilla::plugins::FakePluginTag>& aFakePlugins); |
259 | | private: |
260 | | friend class nsPluginUnloadRunnable; |
261 | | friend class mozilla::plugins::BlocklistPromiseHandler; |
262 | | |
263 | | void DestroyRunningInstances(nsPluginTag* aPluginTag); |
264 | | |
265 | | // Writes updated plugins settings to disk and unloads the plugin |
266 | | // if it is now disabled. Should only be called by the plugin tag in question |
267 | | void UpdatePluginInfo(nsPluginTag* aPluginTag); |
268 | | |
269 | | nsresult TrySetUpPluginInstance(const nsACString &aMimeType, nsIURI *aURL, |
270 | | nsPluginInstanceOwner *aOwner); |
271 | | |
272 | | // FIXME-jsplugins comment here about when things may be fake |
273 | | nsPluginTag* |
274 | | FindPreferredPlugin(const InfallibleTArray<nsPluginTag*>& matches); |
275 | | |
276 | | // Find a plugin for the given type. If aIncludeFake is true a fake plugin |
277 | | // will be preferred if one exists; otherwise a fake plugin will never be |
278 | | // returned. If aCheckEnabled is false, disabled plugins can be returned. |
279 | | nsIInternalPluginTag* FindPluginForType(const nsACString& aMimeType, |
280 | | bool aIncludeFake, bool aCheckEnabled); |
281 | | |
282 | | // Find specifically a fake plugin for the given type. If aCheckEnabled is |
283 | | // false, disabled plugins can be returned. |
284 | | nsFakePluginTag* FindFakePluginForType(const nsACString & aMimeType, |
285 | | bool aCheckEnabled); |
286 | | |
287 | | // Find specifically a fake plugin for the given extension. If aCheckEnabled |
288 | | // is false, disabled plugins can be returned. aMimeType will be filled in |
289 | | // with the MIME type the plugin is registered for. |
290 | | nsFakePluginTag* FindFakePluginForExtension(const nsACString & aExtension, |
291 | | /* out */ nsACString & aMimeType, |
292 | | bool aCheckEnabled); |
293 | | |
294 | | // Find specifically a native (NPAPI) plugin for the given type. If |
295 | | // aCheckEnabled is false, disabled plugins can be returned. |
296 | | nsPluginTag* FindNativePluginForType(const nsACString & aMimeType, |
297 | | bool aCheckEnabled); |
298 | | |
299 | | // Find specifically a native (NPAPI) plugin for the given extension. If |
300 | | // aCheckEnabled is false, disabled plugins can be returned. aMimeType will |
301 | | // be filled in with the MIME type the plugin is registered for. |
302 | | nsPluginTag* FindNativePluginForExtension(const nsACString & aExtension, |
303 | | /* out */ nsACString & aMimeType, |
304 | | bool aCheckEnabled); |
305 | | |
306 | | nsresult |
307 | | FindStoppedPluginForURL(nsIURI* aURL, nsIPluginInstanceOwner *aOwner); |
308 | | |
309 | | nsresult |
310 | | FindPlugins(bool aCreatePluginList, bool * aPluginsChanged); |
311 | | |
312 | | // FIXME revisit, no ns prefix |
313 | | // Registers or unregisters the given mime type with the category manager |
314 | | enum nsRegisterType { ePluginRegister, |
315 | | ePluginUnregister, |
316 | | // Checks if this type should still be registered first |
317 | | ePluginMaybeUnregister }; |
318 | | void RegisterWithCategoryManager(const nsCString& aMimeType, |
319 | | nsRegisterType aType); |
320 | | |
321 | | void AddPluginTag(nsPluginTag* aPluginTag); |
322 | | |
323 | | void UpdatePluginBlocklistState(nsPluginTag* aPluginTag, |
324 | | bool aShouldSoftblock = false); |
325 | | |
326 | | nsresult |
327 | | ScanPluginsDirectory(nsIFile *pluginsDir, |
328 | | bool aCreatePluginList, |
329 | | bool *aPluginsChanged); |
330 | | |
331 | | nsresult |
332 | | ScanPluginsDirectoryList(nsISimpleEnumerator *dirEnum, |
333 | | bool aCreatePluginList, |
334 | | bool *aPluginsChanged); |
335 | | |
336 | | nsresult EnsurePluginLoaded(nsPluginTag* aPluginTag); |
337 | | |
338 | | bool IsRunningPlugin(nsPluginTag * aPluginTag); |
339 | | |
340 | | // Stores all plugins info into the registry |
341 | | nsresult WritePluginInfo(); |
342 | | |
343 | | // Loads all cached plugins info into mCachedPlugins |
344 | | nsresult ReadPluginInfo(); |
345 | | |
346 | | // Given a file path, returns the plugins info from our cache |
347 | | // and removes it from the cache. |
348 | | void RemoveCachedPluginsInfo(const char *filePath, |
349 | | nsPluginTag **result); |
350 | | |
351 | | // Checks to see if a tag object is in our list of live tags. |
352 | | bool IsLiveTag(nsIPluginTag* tag); |
353 | | |
354 | | // Checks our list of live tags for an equivalent tag. |
355 | | nsPluginTag* HaveSamePlugin(const nsPluginTag * aPluginTag); |
356 | | |
357 | | // Returns the first plugin at |path| |
358 | | nsPluginTag* FirstPluginWithPath(const nsCString& path); |
359 | | |
360 | | nsresult EnsurePrivateDirServiceProvider(); |
361 | | |
362 | | void OnPluginInstanceDestroyed(nsPluginTag* aPluginTag); |
363 | | |
364 | | // To be used by the chrome process whenever the set of plugins changes. |
365 | | void IncrementChromeEpoch(); |
366 | | |
367 | | // To be used by the chrome process; returns the current epoch. |
368 | | uint32_t ChromeEpoch(); |
369 | | |
370 | | // To be used by the content process to get/set the last observed epoch value |
371 | | // from the chrome process. |
372 | | uint32_t ChromeEpochForContent(); |
373 | | void SetChromeEpochForContent(uint32_t aEpoch); |
374 | | |
375 | | void UpdateInMemoryPluginInfo(nsPluginTag* aPluginTag); |
376 | | |
377 | | nsresult ActuallyReloadPlugins(); |
378 | | |
379 | | RefPtr<nsPluginTag> mPlugins; |
380 | | RefPtr<nsPluginTag> mCachedPlugins; |
381 | | RefPtr<nsInvalidPluginTag> mInvalidPlugins; |
382 | | |
383 | | nsTArray< RefPtr<nsFakePluginTag> > mFakePlugins; |
384 | | |
385 | | bool mPluginsLoaded; |
386 | | |
387 | | // set by pref plugin.override_internal_types |
388 | | bool mOverrideInternalTypes; |
389 | | |
390 | | // set by pref plugin.disable |
391 | | bool mPluginsDisabled; |
392 | | |
393 | | // Any instances in this array will have valid plugin objects via GetPlugin(). |
394 | | // When removing an instance it might not die - be sure to null out it's plugin. |
395 | | nsTArray< RefPtr<nsNPAPIPluginInstance> > mInstances; |
396 | | |
397 | | nsCOMPtr<nsIFile> mPluginRegFile; |
398 | | #ifdef XP_WIN |
399 | | RefPtr<nsPluginDirServiceProvider> mPrivateDirServiceProvider; |
400 | | |
401 | | // In order to reload plugins when they change, we watch the registry via |
402 | | // this object. |
403 | | nsCOMPtr<nsIWindowsRegKey> mRegKeyHKLM; |
404 | | nsCOMPtr<nsIWindowsRegKey> mRegKeyHKCU; |
405 | | #endif |
406 | | |
407 | | nsCOMPtr<nsIEffectiveTLDService> mTLDService; |
408 | | nsCOMPtr<nsIIDNService> mIDNService; |
409 | | |
410 | | // Helpers for ClearSiteData and SiteHasData. |
411 | | nsresult NormalizeHostname(nsCString& host); |
412 | | |
413 | | nsWeakPtr mCurrentDocument; // weak reference, we use it to id document only |
414 | | |
415 | | // This epoch increases each time we load the list of plugins from disk. |
416 | | // In the chrome process, this stores the actual epoch. |
417 | | // In the content process, this stores the last epoch value observed |
418 | | // when reading plugins from chrome. |
419 | | uint32_t mPluginEpoch; |
420 | | |
421 | | static nsIFile *sPluginTempDir; |
422 | | |
423 | | // We need to hold a global ptr to ourselves because we register for |
424 | | // two different CIDs for some reason... |
425 | | static mozilla::StaticRefPtr<nsPluginHost> sInst; |
426 | | }; |
427 | | |
428 | | class PluginDestructionGuard : public mozilla::LinkedListElement<PluginDestructionGuard> |
429 | | { |
430 | | public: |
431 | | explicit PluginDestructionGuard(nsNPAPIPluginInstance *aInstance); |
432 | | explicit PluginDestructionGuard(NPP npp); |
433 | | |
434 | | ~PluginDestructionGuard(); |
435 | | |
436 | | static bool DelayDestroy(nsNPAPIPluginInstance *aInstance); |
437 | | |
438 | | protected: |
439 | | void Init() |
440 | 0 | { |
441 | 0 | NS_ASSERTION(NS_IsMainThread(), "Should be on the main thread"); |
442 | 0 |
|
443 | 0 | mDelayedDestroy = false; |
444 | 0 |
|
445 | 0 | sList.insertBack(this); |
446 | 0 | } |
447 | | |
448 | | RefPtr<nsNPAPIPluginInstance> mInstance; |
449 | | bool mDelayedDestroy; |
450 | | |
451 | | static mozilla::LinkedList<PluginDestructionGuard> sList; |
452 | | }; |
453 | | |
454 | | #endif // nsPluginHost_h_ |