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