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 : #include "nsPluginTags.h"
7 :
8 : #include "prlink.h"
9 : #include "plstr.h"
10 : #include "nsIPluginInstanceOwner.h"
11 : #include "nsPluginsDir.h"
12 : #include "nsPluginHost.h"
13 : #include "nsIBlocklistService.h"
14 : #include "nsPluginLogging.h"
15 : #include "nsNPAPIPlugin.h"
16 : #include "nsCharSeparatedTokenizer.h"
17 : #include "mozilla/Preferences.h"
18 : #include "mozilla/Unused.h"
19 : #include "nsNetUtil.h"
20 : #include <cctype>
21 : #include "mozilla/Encoding.h"
22 : #include "mozilla/dom/ContentChild.h"
23 : #include "mozilla/dom/FakePluginTagInitBinding.h"
24 :
25 : using mozilla::dom::FakePluginTagInit;
26 : using namespace mozilla;
27 :
28 : // These legacy flags are used in the plugin registry. The states are now
29 : // stored in prefs, but we still need to be able to import them.
30 : #define NS_PLUGIN_FLAG_ENABLED 0x0001 // is this plugin enabled?
31 : // no longer used 0x0002 // reuse only if regenerating pluginreg.dat
32 : #define NS_PLUGIN_FLAG_FROMCACHE 0x0004 // this plugintag info was loaded from cache
33 : // no longer used 0x0008 // reuse only if regenerating pluginreg.dat
34 : #define NS_PLUGIN_FLAG_CLICKTOPLAY 0x0020 // this is a click-to-play plugin
35 :
36 : static const char kPrefDefaultEnabledState[] = "plugin.default.state";
37 : static const char kPrefDefaultEnabledStateXpi[] = "plugin.defaultXpi.state";
38 :
39 : // check comma delimited extensions
40 0 : static bool ExtensionInList(const nsCString& aExtensionList,
41 : const nsACString& aExtension)
42 : {
43 0 : nsCCharSeparatedTokenizer extensions(aExtensionList, ',');
44 0 : while (extensions.hasMoreTokens()) {
45 0 : const nsACString& extension = extensions.nextToken();
46 0 : if (extension.Equals(aExtension, nsCaseInsensitiveCStringComparator())) {
47 0 : return true;
48 : }
49 : }
50 0 : return false;
51 : }
52 :
53 : // Search for an extension in an extensions array, and return its
54 : // matching mime type
55 0 : static bool SearchExtensions(const nsTArray<nsCString> & aExtensions,
56 : const nsTArray<nsCString> & aMimeTypes,
57 : const nsACString & aFindExtension,
58 : nsACString & aMatchingType)
59 : {
60 0 : uint32_t mimes = aMimeTypes.Length();
61 0 : MOZ_ASSERT(mimes == aExtensions.Length(),
62 : "These arrays should have matching elements");
63 :
64 0 : aMatchingType.Truncate();
65 :
66 0 : for (uint32_t i = 0; i < mimes; i++) {
67 0 : if (ExtensionInList(aExtensions[i], aFindExtension)) {
68 0 : aMatchingType = aMimeTypes[i];
69 0 : return true;
70 : }
71 : }
72 :
73 0 : return false;
74 : }
75 :
76 : static nsCString
77 0 : MakeNiceFileName(const nsCString & aFileName)
78 : {
79 0 : nsCString niceName = aFileName;
80 0 : int32_t niceNameLength = aFileName.RFind(".");
81 0 : NS_ASSERTION(niceNameLength != kNotFound, "aFileName doesn't have a '.'?");
82 0 : while (niceNameLength > 0) {
83 0 : char chr = aFileName[niceNameLength - 1];
84 0 : if (!std::isalpha(chr))
85 0 : niceNameLength--;
86 : else
87 0 : break;
88 : }
89 :
90 : // If it turns out that niceNameLength <= 0, we'll fall back and use the
91 : // entire aFileName (which we've already taken care of, a few lines back).
92 0 : if (niceNameLength > 0) {
93 0 : niceName.Truncate(niceNameLength);
94 : }
95 :
96 0 : ToLowerCase(niceName);
97 0 : return niceName;
98 : }
99 :
100 : static nsCString
101 0 : MakePrefNameForPlugin(const char* const subname, nsIInternalPluginTag* aTag)
102 : {
103 0 : nsCString pref;
104 0 : nsAutoCString pluginName(aTag->GetNiceFileName());
105 :
106 0 : if (pluginName.IsEmpty()) {
107 : // Use filename if nice name fails
108 0 : pluginName = aTag->FileName();
109 0 : if (pluginName.IsEmpty()) {
110 0 : MOZ_ASSERT_UNREACHABLE("Plugin with no filename or nice name in list");
111 : pluginName.AssignLiteral("unknown-plugin-name");
112 : }
113 : }
114 :
115 0 : pref.AssignLiteral("plugin.");
116 0 : pref.Append(subname);
117 0 : pref.Append('.');
118 0 : pref.Append(pluginName);
119 :
120 0 : return pref;
121 : }
122 :
123 : static nsresult
124 0 : CStringArrayToXPCArray(nsTArray<nsCString> & aArray,
125 : uint32_t* aCount,
126 : char16_t*** aResults)
127 : {
128 0 : uint32_t count = aArray.Length();
129 0 : if (!count) {
130 0 : *aResults = nullptr;
131 0 : *aCount = 0;
132 0 : return NS_OK;
133 : }
134 :
135 0 : *aResults =
136 0 : static_cast<char16_t**>(moz_xmalloc(count * sizeof(**aResults)));
137 0 : *aCount = count;
138 :
139 0 : for (uint32_t i = 0; i < count; i++) {
140 0 : (*aResults)[i] = ToNewUnicode(NS_ConvertUTF8toUTF16(aArray[i]));
141 : }
142 :
143 0 : return NS_OK;
144 : }
145 :
146 : static nsCString
147 0 : GetStatePrefNameForPlugin(nsIInternalPluginTag* aTag)
148 : {
149 0 : return MakePrefNameForPlugin("state", aTag);
150 : }
151 :
152 : static nsresult
153 0 : IsEnabledStateLockedForPlugin(nsIInternalPluginTag* aTag,
154 : bool* aIsEnabledStateLocked)
155 : {
156 0 : *aIsEnabledStateLocked = false;
157 0 : nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
158 :
159 0 : if (NS_WARN_IF(!prefs)) {
160 0 : return NS_ERROR_FAILURE;
161 : }
162 :
163 0 : Unused << prefs->PrefIsLocked(GetStatePrefNameForPlugin(aTag).get(),
164 0 : aIsEnabledStateLocked);
165 :
166 0 : return NS_OK;
167 : }
168 :
169 : /* nsIInternalPluginTag */
170 0 : nsIInternalPluginTag::nsIInternalPluginTag()
171 : {
172 0 : }
173 :
174 0 : nsIInternalPluginTag::nsIInternalPluginTag(const char* aName,
175 : const char* aDescription,
176 : const char* aFileName,
177 0 : const char* aVersion)
178 : : mName(aName)
179 : , mDescription(aDescription)
180 : , mFileName(aFileName)
181 0 : , mVersion(aVersion)
182 : {
183 0 : }
184 :
185 0 : nsIInternalPluginTag::nsIInternalPluginTag(const char* aName,
186 : const char* aDescription,
187 : const char* aFileName,
188 : const char* aVersion,
189 : const nsTArray<nsCString>& aMimeTypes,
190 : const nsTArray<nsCString>& aMimeDescriptions,
191 0 : const nsTArray<nsCString>& aExtensions)
192 : : mName(aName)
193 : , mDescription(aDescription)
194 : , mFileName(aFileName)
195 : , mVersion(aVersion)
196 : , mMimeTypes(aMimeTypes)
197 : , mMimeDescriptions(aMimeDescriptions)
198 0 : , mExtensions(aExtensions)
199 : {
200 0 : }
201 :
202 0 : nsIInternalPluginTag::~nsIInternalPluginTag()
203 : {
204 0 : }
205 :
206 : bool
207 0 : nsIInternalPluginTag::HasExtension(const nsACString& aExtension,
208 : nsACString& aMatchingType) const
209 : {
210 0 : return SearchExtensions(mExtensions, mMimeTypes, aExtension, aMatchingType);
211 : }
212 :
213 : bool
214 0 : nsIInternalPluginTag::HasMimeType(const nsACString& aMimeType) const
215 : {
216 0 : return mMimeTypes.Contains(aMimeType,
217 0 : nsCaseInsensitiveCStringArrayComparator());
218 : }
219 :
220 : /* nsPluginTag */
221 :
222 : uint32_t nsPluginTag::sNextId;
223 :
224 0 : nsPluginTag::nsPluginTag(nsPluginInfo* aPluginInfo,
225 : int64_t aLastModifiedTime,
226 0 : bool fromExtension)
227 0 : : nsIInternalPluginTag(aPluginInfo->fName, aPluginInfo->fDescription,
228 0 : aPluginInfo->fFileName, aPluginInfo->fVersion),
229 0 : mId(sNextId++),
230 : mContentProcessRunningCount(0),
231 : mHadLocalInstance(false),
232 : mLibrary(nullptr),
233 : mIsJavaPlugin(false),
234 : mIsFlashPlugin(false),
235 : mSupportsAsyncRender(false),
236 0 : mFullPath(aPluginInfo->fFullPath),
237 : mLastModifiedTime(aLastModifiedTime),
238 : mSandboxLevel(0),
239 : mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
240 : mCachedBlocklistStateValid(false),
241 0 : mIsFromExtension(fromExtension)
242 : {
243 0 : InitMime(aPluginInfo->fMimeTypeArray,
244 0 : aPluginInfo->fMimeDescriptionArray,
245 0 : aPluginInfo->fExtensionArray,
246 0 : aPluginInfo->fVariantCount);
247 0 : InitSandboxLevel();
248 0 : EnsureMembersAreUTF8();
249 0 : FixupVersion();
250 0 : }
251 :
252 0 : nsPluginTag::nsPluginTag(const char* aName,
253 : const char* aDescription,
254 : const char* aFileName,
255 : const char* aFullPath,
256 : const char* aVersion,
257 : const char* const* aMimeTypes,
258 : const char* const* aMimeDescriptions,
259 : const char* const* aExtensions,
260 : int32_t aVariants,
261 : int64_t aLastModifiedTime,
262 : bool fromExtension,
263 0 : bool aArgsAreUTF8)
264 : : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion),
265 0 : mId(sNextId++),
266 : mContentProcessRunningCount(0),
267 : mHadLocalInstance(false),
268 : mLibrary(nullptr),
269 : mIsJavaPlugin(false),
270 : mIsFlashPlugin(false),
271 : mSupportsAsyncRender(false),
272 : mFullPath(aFullPath),
273 : mLastModifiedTime(aLastModifiedTime),
274 : mSandboxLevel(0),
275 : mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
276 : mCachedBlocklistStateValid(false),
277 0 : mIsFromExtension(fromExtension)
278 : {
279 0 : InitMime(aMimeTypes, aMimeDescriptions, aExtensions,
280 0 : static_cast<uint32_t>(aVariants));
281 0 : InitSandboxLevel();
282 0 : if (!aArgsAreUTF8)
283 0 : EnsureMembersAreUTF8();
284 0 : FixupVersion();
285 0 : }
286 :
287 0 : nsPluginTag::nsPluginTag(uint32_t aId,
288 : const char* aName,
289 : const char* aDescription,
290 : const char* aFileName,
291 : const char* aFullPath,
292 : const char* aVersion,
293 : nsTArray<nsCString> aMimeTypes,
294 : nsTArray<nsCString> aMimeDescriptions,
295 : nsTArray<nsCString> aExtensions,
296 : bool aIsJavaPlugin,
297 : bool aIsFlashPlugin,
298 : bool aSupportsAsyncRender,
299 : int64_t aLastModifiedTime,
300 : bool aFromExtension,
301 0 : int32_t aSandboxLevel)
302 : : nsIInternalPluginTag(aName, aDescription, aFileName, aVersion, aMimeTypes,
303 : aMimeDescriptions, aExtensions),
304 : mId(aId),
305 : mContentProcessRunningCount(0),
306 : mLibrary(nullptr),
307 : mIsJavaPlugin(aIsJavaPlugin),
308 : mIsFlashPlugin(aIsFlashPlugin),
309 : mSupportsAsyncRender(aSupportsAsyncRender),
310 : mLastModifiedTime(aLastModifiedTime),
311 : mSandboxLevel(aSandboxLevel),
312 : mNiceFileName(),
313 : mCachedBlocklistState(nsIBlocklistService::STATE_NOT_BLOCKED),
314 : mCachedBlocklistStateValid(false),
315 0 : mIsFromExtension(aFromExtension)
316 : {
317 0 : }
318 :
319 0 : nsPluginTag::~nsPluginTag()
320 : {
321 0 : NS_ASSERTION(!mNext, "Risk of exhausting the stack space, bug 486349");
322 0 : }
323 :
324 0 : NS_IMPL_ISUPPORTS(nsPluginTag, nsPluginTag, nsIInternalPluginTag, nsIPluginTag)
325 :
326 0 : void nsPluginTag::InitMime(const char* const* aMimeTypes,
327 : const char* const* aMimeDescriptions,
328 : const char* const* aExtensions,
329 : uint32_t aVariantCount)
330 : {
331 0 : if (!aMimeTypes) {
332 0 : return;
333 : }
334 :
335 0 : for (uint32_t i = 0; i < aVariantCount; i++) {
336 0 : if (!aMimeTypes[i]) {
337 0 : continue;
338 : }
339 :
340 0 : nsAutoCString mimeType(aMimeTypes[i]);
341 :
342 : // Convert the MIME type, which is case insensitive, to lowercase in order
343 : // to properly handle a mixed-case type.
344 0 : ToLowerCase(mimeType);
345 :
346 0 : if (!nsPluginHost::IsTypeWhitelisted(mimeType.get())) {
347 0 : continue;
348 : }
349 :
350 : // Look for certain special plugins.
351 0 : switch (nsPluginHost::GetSpecialType(mimeType)) {
352 : case nsPluginHost::eSpecialType_Java:
353 0 : mIsJavaPlugin = true;
354 0 : break;
355 : case nsPluginHost::eSpecialType_Flash:
356 : // VLC sometimes claims to implement the Flash MIME type, and we want
357 : // to allow users to control that separately from Adobe Flash.
358 0 : if (Name().EqualsLiteral("Shockwave Flash")) {
359 0 : mIsFlashPlugin = true;
360 : }
361 0 : break;
362 : case nsPluginHost::eSpecialType_Test:
363 : case nsPluginHost::eSpecialType_None:
364 : default:
365 0 : break;
366 : }
367 :
368 : // Fill in our MIME type array.
369 0 : mMimeTypes.AppendElement(mimeType);
370 :
371 : // Now fill in the MIME descriptions.
372 0 : if (aMimeDescriptions && aMimeDescriptions[i]) {
373 : // we should cut off the list of suffixes which the mime
374 : // description string may have, see bug 53895
375 : // it is usually in form "some description (*.sf1, *.sf2)"
376 : // so we can search for the opening round bracket
377 0 : char cur = '\0';
378 0 : char pre = '\0';
379 0 : char * p = PL_strrchr(aMimeDescriptions[i], '(');
380 0 : if (p && (p != aMimeDescriptions[i])) {
381 0 : if ((p - 1) && *(p - 1) == ' ') {
382 0 : pre = *(p - 1);
383 0 : *(p - 1) = '\0';
384 : } else {
385 0 : cur = *p;
386 0 : *p = '\0';
387 : }
388 : }
389 0 : mMimeDescriptions.AppendElement(nsCString(aMimeDescriptions[i]));
390 : // restore the original string
391 0 : if (cur != '\0') {
392 0 : *p = cur;
393 : }
394 0 : if (pre != '\0') {
395 0 : *(p - 1) = pre;
396 0 : }
397 : } else {
398 0 : mMimeDescriptions.AppendElement(nsCString());
399 : }
400 :
401 : // Now fill in the extensions.
402 0 : if (aExtensions && aExtensions[i]) {
403 0 : mExtensions.AppendElement(nsCString(aExtensions[i]));
404 : } else {
405 0 : mExtensions.AppendElement(nsCString());
406 : }
407 : }
408 : }
409 :
410 : void
411 0 : nsPluginTag::InitSandboxLevel()
412 : {
413 : #if defined(XP_WIN) && defined(MOZ_SANDBOX)
414 : nsAutoCString sandboxPref("dom.ipc.plugins.sandbox-level.");
415 : sandboxPref.Append(GetNiceFileName());
416 : if (NS_FAILED(Preferences::GetInt(sandboxPref.get(), &mSandboxLevel))) {
417 : mSandboxLevel = Preferences::GetInt("dom.ipc.plugins.sandbox-level.default"
418 : );
419 : }
420 :
421 : #if defined(_AMD64_)
422 : // As level 2 is now the default NPAPI sandbox level for 64-bit flash, we
423 : // don't want to allow a lower setting. This should be changed if the
424 : // firefox.js pref file is changed.
425 : if (mIsFlashPlugin && mSandboxLevel < 2) {
426 : mSandboxLevel = 2;
427 : }
428 : #endif
429 : #endif
430 0 : }
431 :
432 : #if !defined(XP_WIN) && !defined(XP_MACOSX)
433 : static void
434 0 : ConvertToUTF8(nsCString& aString)
435 : {
436 0 : Unused << UTF_8_ENCODING->DecodeWithoutBOMHandling(aString, aString);
437 0 : }
438 : #endif
439 :
440 0 : nsresult nsPluginTag::EnsureMembersAreUTF8()
441 : {
442 : #if defined(XP_WIN) || defined(XP_MACOSX)
443 : return NS_OK;
444 : #else
445 0 : ConvertToUTF8(mFileName);
446 0 : ConvertToUTF8(mFullPath);
447 0 : ConvertToUTF8(mName);
448 0 : ConvertToUTF8(mDescription);
449 0 : for (uint32_t i = 0; i < mMimeDescriptions.Length(); ++i) {
450 0 : ConvertToUTF8(mMimeDescriptions[i]);
451 : }
452 0 : return NS_OK;
453 : #endif
454 : }
455 :
456 0 : void nsPluginTag::FixupVersion()
457 : {
458 : #if defined(XP_LINUX)
459 0 : if (mIsFlashPlugin) {
460 0 : mVersion.ReplaceChar(',', '.');
461 : }
462 : #endif
463 0 : }
464 :
465 : NS_IMETHODIMP
466 0 : nsPluginTag::GetDescription(nsACString& aDescription)
467 : {
468 0 : aDescription = mDescription;
469 0 : return NS_OK;
470 : }
471 :
472 : NS_IMETHODIMP
473 0 : nsPluginTag::GetFilename(nsACString& aFileName)
474 : {
475 0 : aFileName = mFileName;
476 0 : return NS_OK;
477 : }
478 :
479 : NS_IMETHODIMP
480 0 : nsPluginTag::GetFullpath(nsACString& aFullPath)
481 : {
482 0 : aFullPath = mFullPath;
483 0 : return NS_OK;
484 : }
485 :
486 : NS_IMETHODIMP
487 0 : nsPluginTag::GetVersion(nsACString& aVersion)
488 : {
489 0 : aVersion = mVersion;
490 0 : return NS_OK;
491 : }
492 :
493 : NS_IMETHODIMP
494 0 : nsPluginTag::GetName(nsACString& aName)
495 : {
496 0 : aName = mName;
497 0 : return NS_OK;
498 : }
499 :
500 : bool
501 0 : nsPluginTag::IsActive()
502 : {
503 0 : return IsEnabled() && !IsBlocklisted();
504 : }
505 :
506 : NS_IMETHODIMP
507 0 : nsPluginTag::GetActive(bool *aResult)
508 : {
509 0 : *aResult = IsActive();
510 0 : return NS_OK;
511 : }
512 :
513 : bool
514 0 : nsPluginTag::IsEnabled()
515 : {
516 0 : const PluginState state = GetPluginState();
517 0 : return (state == ePluginState_Enabled) || (state == ePluginState_Clicktoplay);
518 : }
519 :
520 : NS_IMETHODIMP
521 0 : nsPluginTag::GetDisabled(bool* aDisabled)
522 : {
523 0 : *aDisabled = !IsEnabled();
524 0 : return NS_OK;
525 : }
526 :
527 : bool
528 0 : nsPluginTag::IsBlocklisted()
529 : {
530 : uint32_t blocklistState;
531 0 : nsresult rv = GetBlocklistState(&blocklistState);
532 0 : return NS_FAILED(rv) || blocklistState == nsIBlocklistService::STATE_BLOCKED;
533 : }
534 :
535 : NS_IMETHODIMP
536 0 : nsPluginTag::GetBlocklisted(bool* aBlocklisted)
537 : {
538 0 : *aBlocklisted = IsBlocklisted();
539 0 : return NS_OK;
540 : }
541 :
542 : NS_IMETHODIMP
543 0 : nsPluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked)
544 : {
545 0 : return IsEnabledStateLockedForPlugin(this, aIsEnabledStateLocked);
546 : }
547 :
548 : bool
549 0 : nsPluginTag::IsClicktoplay()
550 : {
551 0 : const PluginState state = GetPluginState();
552 0 : return (state == ePluginState_Clicktoplay);
553 : }
554 :
555 : NS_IMETHODIMP
556 0 : nsPluginTag::GetClicktoplay(bool *aClicktoplay)
557 : {
558 0 : *aClicktoplay = IsClicktoplay();
559 0 : return NS_OK;
560 : }
561 :
562 : NS_IMETHODIMP
563 0 : nsPluginTag::GetEnabledState(uint32_t *aEnabledState)
564 : {
565 : int32_t enabledState;
566 0 : nsresult rv = Preferences::GetInt(GetStatePrefNameForPlugin(this).get(),
567 0 : &enabledState);
568 0 : if (NS_SUCCEEDED(rv) &&
569 0 : enabledState >= nsIPluginTag::STATE_DISABLED &&
570 0 : enabledState <= nsIPluginTag::STATE_ENABLED) {
571 0 : *aEnabledState = (uint32_t)enabledState;
572 0 : return rv;
573 : }
574 :
575 0 : const char* const pref = mIsFromExtension ? kPrefDefaultEnabledStateXpi
576 0 : : kPrefDefaultEnabledState;
577 :
578 0 : enabledState = Preferences::GetInt(pref, nsIPluginTag::STATE_ENABLED);
579 0 : if (enabledState >= nsIPluginTag::STATE_DISABLED &&
580 0 : enabledState <= nsIPluginTag::STATE_ENABLED) {
581 0 : *aEnabledState = (uint32_t)enabledState;
582 0 : return NS_OK;
583 : }
584 :
585 0 : return NS_ERROR_UNEXPECTED;
586 : }
587 :
588 : NS_IMETHODIMP
589 0 : nsPluginTag::SetEnabledState(uint32_t aEnabledState)
590 : {
591 0 : if (aEnabledState >= ePluginState_MaxValue)
592 0 : return NS_ERROR_ILLEGAL_VALUE;
593 0 : uint32_t oldState = nsIPluginTag::STATE_DISABLED;
594 0 : GetEnabledState(&oldState);
595 0 : if (oldState != aEnabledState) {
596 0 : Preferences::SetInt(GetStatePrefNameForPlugin(this).get(), aEnabledState);
597 0 : if (RefPtr<nsPluginHost> host = nsPluginHost::GetInst()) {
598 0 : host->UpdatePluginInfo(this);
599 : }
600 : }
601 0 : return NS_OK;
602 : }
603 :
604 : nsPluginTag::PluginState
605 0 : nsPluginTag::GetPluginState()
606 : {
607 0 : uint32_t enabledState = nsIPluginTag::STATE_DISABLED;
608 0 : GetEnabledState(&enabledState);
609 0 : return (PluginState)enabledState;
610 : }
611 :
612 : void
613 0 : nsPluginTag::SetPluginState(PluginState state)
614 : {
615 : static_assert((uint32_t)nsPluginTag::ePluginState_Disabled == nsIPluginTag::STATE_DISABLED, "nsPluginTag::ePluginState_Disabled must match nsIPluginTag::STATE_DISABLED");
616 : static_assert((uint32_t)nsPluginTag::ePluginState_Clicktoplay == nsIPluginTag::STATE_CLICKTOPLAY, "nsPluginTag::ePluginState_Clicktoplay must match nsIPluginTag::STATE_CLICKTOPLAY");
617 : static_assert((uint32_t)nsPluginTag::ePluginState_Enabled == nsIPluginTag::STATE_ENABLED, "nsPluginTag::ePluginState_Enabled must match nsIPluginTag::STATE_ENABLED");
618 0 : SetEnabledState((uint32_t)state);
619 0 : }
620 :
621 : NS_IMETHODIMP
622 0 : nsPluginTag::GetMimeTypes(uint32_t* aCount, char16_t*** aResults)
623 : {
624 0 : return CStringArrayToXPCArray(mMimeTypes, aCount, aResults);
625 : }
626 :
627 : NS_IMETHODIMP
628 0 : nsPluginTag::GetMimeDescriptions(uint32_t* aCount, char16_t*** aResults)
629 : {
630 0 : return CStringArrayToXPCArray(mMimeDescriptions, aCount, aResults);
631 : }
632 :
633 : NS_IMETHODIMP
634 0 : nsPluginTag::GetExtensions(uint32_t* aCount, char16_t*** aResults)
635 : {
636 0 : return CStringArrayToXPCArray(mExtensions, aCount, aResults);
637 : }
638 :
639 : bool
640 0 : nsPluginTag::HasSameNameAndMimes(const nsPluginTag *aPluginTag) const
641 : {
642 0 : NS_ENSURE_TRUE(aPluginTag, false);
643 :
644 0 : if ((!mName.Equals(aPluginTag->mName)) ||
645 0 : (mMimeTypes.Length() != aPluginTag->mMimeTypes.Length())) {
646 0 : return false;
647 : }
648 :
649 0 : for (uint32_t i = 0; i < mMimeTypes.Length(); i++) {
650 0 : if (!mMimeTypes[i].Equals(aPluginTag->mMimeTypes[i])) {
651 0 : return false;
652 : }
653 : }
654 :
655 0 : return true;
656 : }
657 :
658 : NS_IMETHODIMP
659 0 : nsPluginTag::GetLoaded(bool* aIsLoaded)
660 : {
661 0 : *aIsLoaded = !!mPlugin;
662 0 : return NS_OK;
663 : }
664 :
665 0 : void nsPluginTag::TryUnloadPlugin(bool inShutdown)
666 : {
667 : // We never want to send NPP_Shutdown to an in-process plugin unless
668 : // this process is shutting down.
669 0 : if (!mPlugin) {
670 0 : return;
671 : }
672 0 : if (inShutdown || mPlugin->GetLibrary()->IsOOP()) {
673 0 : mPlugin->Shutdown();
674 0 : mPlugin = nullptr;
675 : }
676 : }
677 :
678 : const nsCString&
679 0 : nsPluginTag::GetNiceFileName()
680 : {
681 0 : if (!mNiceFileName.IsEmpty()) {
682 0 : return mNiceFileName;
683 : }
684 :
685 0 : if (mIsFlashPlugin) {
686 0 : mNiceFileName.AssignLiteral("flash");
687 0 : return mNiceFileName;
688 : }
689 :
690 0 : if (mIsJavaPlugin) {
691 0 : mNiceFileName.AssignLiteral("java");
692 0 : return mNiceFileName;
693 : }
694 :
695 0 : mNiceFileName = MakeNiceFileName(mFileName);
696 0 : return mNiceFileName;
697 : }
698 :
699 : NS_IMETHODIMP
700 0 : nsPluginTag::GetNiceName(nsACString & aResult)
701 : {
702 0 : aResult = GetNiceFileName();
703 0 : return NS_OK;
704 : }
705 :
706 : NS_IMETHODIMP
707 0 : nsPluginTag::GetBlocklistState(uint32_t *aResult)
708 : {
709 : #if defined(MOZ_WIDGET_ANDROID)
710 : *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
711 : return NS_OK;
712 : #else
713 0 : if (mCachedBlocklistStateValid) {
714 0 : *aResult = mCachedBlocklistState;
715 0 : return NS_OK;
716 : }
717 :
718 0 : if (!XRE_IsParentProcess()) {
719 0 : *aResult = nsIBlocklistService::STATE_BLOCKED;
720 0 : dom::ContentChild* cp = dom::ContentChild::GetSingleton();
721 0 : if (!cp->SendGetBlocklistState(mId, aResult)) {
722 0 : return NS_OK;
723 : }
724 : } else {
725 : nsCOMPtr<nsIBlocklistService> blocklist =
726 0 : do_GetService("@mozilla.org/extensions/blocklist;1");
727 :
728 0 : if (!blocklist) {
729 0 : *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
730 0 : return NS_OK;
731 : }
732 :
733 : // The EmptyString()s are so we use the currently running application
734 : // and toolkit versions
735 0 : if (NS_FAILED(blocklist->GetPluginBlocklistState(this, EmptyString(),
736 : EmptyString(), aResult))) {
737 0 : *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
738 0 : return NS_OK;
739 : }
740 : }
741 :
742 0 : MOZ_ASSERT(*aResult <= UINT16_MAX);
743 0 : mCachedBlocklistState = (uint16_t) *aResult;
744 0 : mCachedBlocklistStateValid = true;
745 0 : return NS_OK;
746 : #endif // defined(MOZ_WIDGET_ANDROID)
747 : }
748 :
749 : void
750 0 : nsPluginTag::InvalidateBlocklistState()
751 : {
752 0 : mCachedBlocklistStateValid = false;
753 0 : }
754 :
755 : NS_IMETHODIMP
756 0 : nsPluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime)
757 : {
758 0 : MOZ_ASSERT(aLastModifiedTime);
759 0 : *aLastModifiedTime = mLastModifiedTime;
760 0 : return NS_OK;
761 : }
762 :
763 0 : bool nsPluginTag::IsFromExtension() const
764 : {
765 0 : return mIsFromExtension;
766 : }
767 :
768 : /* nsFakePluginTag */
769 :
770 : uint32_t nsFakePluginTag::sNextId;
771 :
772 0 : nsFakePluginTag::nsFakePluginTag()
773 0 : : mId(sNextId++),
774 0 : mState(nsPluginTag::ePluginState_Disabled)
775 : {
776 0 : }
777 :
778 0 : nsFakePluginTag::nsFakePluginTag(uint32_t aId,
779 : already_AddRefed<nsIURI>&& aHandlerURI,
780 : const char* aName,
781 : const char* aDescription,
782 : const nsTArray<nsCString>& aMimeTypes,
783 : const nsTArray<nsCString>& aMimeDescriptions,
784 : const nsTArray<nsCString>& aExtensions,
785 : const nsCString& aNiceName,
786 0 : const nsString& aSandboxScript)
787 : : nsIInternalPluginTag(aName, aDescription, nullptr, nullptr,
788 : aMimeTypes, aMimeDescriptions, aExtensions),
789 : mId(aId),
790 : mHandlerURI(aHandlerURI),
791 : mNiceName(aNiceName),
792 : mSandboxScript(aSandboxScript),
793 0 : mState(nsPluginTag::ePluginState_Enabled)
794 0 : {}
795 :
796 0 : nsFakePluginTag::~nsFakePluginTag()
797 : {
798 0 : }
799 :
800 0 : NS_IMPL_ADDREF(nsFakePluginTag)
801 0 : NS_IMPL_RELEASE(nsFakePluginTag)
802 0 : NS_INTERFACE_TABLE_HEAD(nsFakePluginTag)
803 : NS_INTERFACE_TABLE_BEGIN
804 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsFakePluginTag, nsIPluginTag,
805 : nsIInternalPluginTag)
806 : NS_INTERFACE_TABLE_ENTRY(nsFakePluginTag, nsIInternalPluginTag)
807 : NS_INTERFACE_TABLE_ENTRY_AMBIGUOUS(nsFakePluginTag, nsISupports,
808 : nsIInternalPluginTag)
809 : NS_INTERFACE_TABLE_ENTRY(nsFakePluginTag, nsIFakePluginTag)
810 0 : NS_INTERFACE_TABLE_END
811 0 : NS_INTERFACE_TABLE_TAIL
812 :
813 : /* static */
814 : nsresult
815 0 : nsFakePluginTag::Create(const FakePluginTagInit& aInitDictionary,
816 : nsFakePluginTag** aPluginTag)
817 : {
818 0 : NS_ENSURE_TRUE(sNextId <= PR_INT32_MAX, NS_ERROR_OUT_OF_MEMORY);
819 0 : NS_ENSURE_TRUE(!aInitDictionary.mMimeEntries.IsEmpty(), NS_ERROR_INVALID_ARG);
820 :
821 0 : RefPtr<nsFakePluginTag> tag = new nsFakePluginTag();
822 0 : nsresult rv = NS_NewURI(getter_AddRefs(tag->mHandlerURI),
823 0 : aInitDictionary.mHandlerURI);
824 0 : NS_ENSURE_SUCCESS(rv, rv);
825 :
826 0 : CopyUTF16toUTF8(aInitDictionary.mNiceName, tag->mNiceName);
827 0 : CopyUTF16toUTF8(aInitDictionary.mFullPath, tag->mFullPath);
828 0 : CopyUTF16toUTF8(aInitDictionary.mName, tag->mName);
829 0 : CopyUTF16toUTF8(aInitDictionary.mDescription, tag->mDescription);
830 0 : CopyUTF16toUTF8(aInitDictionary.mFileName, tag->mFileName);
831 0 : CopyUTF16toUTF8(aInitDictionary.mVersion, tag->mVersion);
832 0 : tag->mSandboxScript = aInitDictionary.mSandboxScript;
833 :
834 0 : for (const FakePluginMimeEntry& mimeEntry : aInitDictionary.mMimeEntries) {
835 0 : CopyUTF16toUTF8(mimeEntry.mType, *tag->mMimeTypes.AppendElement());
836 0 : CopyUTF16toUTF8(mimeEntry.mDescription,
837 0 : *tag->mMimeDescriptions.AppendElement());
838 0 : CopyUTF16toUTF8(mimeEntry.mExtension, *tag->mExtensions.AppendElement());
839 : }
840 :
841 0 : tag.forget(aPluginTag);
842 0 : return NS_OK;
843 : }
844 :
845 : bool
846 0 : nsFakePluginTag::HandlerURIMatches(nsIURI* aURI)
847 : {
848 0 : bool equals = false;
849 0 : return NS_SUCCEEDED(mHandlerURI->Equals(aURI, &equals)) && equals;
850 : }
851 :
852 : NS_IMETHODIMP
853 0 : nsFakePluginTag::GetHandlerURI(nsIURI **aResult)
854 : {
855 0 : NS_IF_ADDREF(*aResult = mHandlerURI);
856 0 : return NS_OK;
857 : }
858 :
859 : NS_IMETHODIMP
860 0 : nsFakePluginTag::GetSandboxScript(nsAString& aSandboxScript)
861 : {
862 0 : aSandboxScript = mSandboxScript;
863 0 : return NS_OK;
864 : }
865 :
866 : NS_IMETHODIMP
867 0 : nsFakePluginTag::GetDescription(/* utf-8 */ nsACString& aResult)
868 : {
869 0 : aResult = mDescription;
870 0 : return NS_OK;
871 : }
872 :
873 : NS_IMETHODIMP
874 0 : nsFakePluginTag::GetFilename(/* utf-8 */ nsACString& aResult)
875 : {
876 0 : aResult = mFileName;
877 0 : return NS_OK;
878 : }
879 :
880 : NS_IMETHODIMP
881 0 : nsFakePluginTag::GetFullpath(/* utf-8 */ nsACString& aResult)
882 : {
883 0 : aResult = mFullPath;
884 0 : return NS_OK;
885 : }
886 :
887 : NS_IMETHODIMP
888 0 : nsFakePluginTag::GetVersion(/* utf-8 */ nsACString& aResult)
889 : {
890 0 : aResult = mVersion;
891 0 : return NS_OK;
892 : }
893 :
894 : NS_IMETHODIMP
895 0 : nsFakePluginTag::GetName(/* utf-8 */ nsACString& aResult)
896 : {
897 0 : aResult = mName;
898 0 : return NS_OK;
899 : }
900 :
901 : const nsCString&
902 0 : nsFakePluginTag::GetNiceFileName()
903 : {
904 : // We don't try to mimic the special-cased flash/java names if the fake plugin
905 : // claims one of their MIME types, but do allow directly setting niceName if
906 : // emulating those is desired.
907 0 : if (mNiceName.IsEmpty() && !mFileName.IsEmpty()) {
908 0 : mNiceName = MakeNiceFileName(mFileName);
909 : }
910 :
911 0 : return mNiceName;
912 : }
913 :
914 : NS_IMETHODIMP
915 0 : nsFakePluginTag::GetNiceName(/* utf-8 */ nsACString& aResult)
916 : {
917 0 : aResult = GetNiceFileName();
918 0 : return NS_OK;
919 : }
920 :
921 : NS_IMETHODIMP
922 0 : nsFakePluginTag::GetBlocklistState(uint32_t* aResult)
923 : {
924 : // Fake tags don't currently support blocklisting
925 0 : *aResult = nsIBlocklistService::STATE_NOT_BLOCKED;
926 0 : return NS_OK;
927 : }
928 :
929 : NS_IMETHODIMP
930 0 : nsFakePluginTag::GetBlocklisted(bool* aBlocklisted)
931 : {
932 : // Fake tags can't be blocklisted
933 0 : *aBlocklisted = false;
934 0 : return NS_OK;
935 : }
936 :
937 : NS_IMETHODIMP
938 0 : nsFakePluginTag::GetIsEnabledStateLocked(bool* aIsEnabledStateLocked)
939 : {
940 0 : return IsEnabledStateLockedForPlugin(this, aIsEnabledStateLocked);
941 : }
942 :
943 : bool
944 0 : nsFakePluginTag::IsEnabled()
945 : {
946 0 : return mState == nsPluginTag::ePluginState_Enabled ||
947 0 : mState == nsPluginTag::ePluginState_Clicktoplay;
948 : }
949 :
950 : NS_IMETHODIMP
951 0 : nsFakePluginTag::GetDisabled(bool* aDisabled)
952 : {
953 0 : *aDisabled = !IsEnabled();
954 0 : return NS_OK;
955 : }
956 :
957 : NS_IMETHODIMP
958 0 : nsFakePluginTag::GetClicktoplay(bool* aClicktoplay)
959 : {
960 0 : *aClicktoplay = (mState == nsPluginTag::ePluginState_Clicktoplay);
961 0 : return NS_OK;
962 : }
963 :
964 : NS_IMETHODIMP
965 0 : nsFakePluginTag::GetEnabledState(uint32_t* aEnabledState)
966 : {
967 0 : *aEnabledState = (uint32_t)mState;
968 0 : return NS_OK;
969 : }
970 :
971 : NS_IMETHODIMP
972 0 : nsFakePluginTag::SetEnabledState(uint32_t aEnabledState)
973 : {
974 : // There are static asserts above enforcing that this enum matches
975 0 : mState = (nsPluginTag::PluginState)aEnabledState;
976 : // FIXME-jsplugins update
977 0 : return NS_OK;
978 : }
979 :
980 : NS_IMETHODIMP
981 0 : nsFakePluginTag::GetMimeTypes(uint32_t* aCount, char16_t*** aResults)
982 : {
983 0 : return CStringArrayToXPCArray(mMimeTypes, aCount, aResults);
984 : }
985 :
986 : NS_IMETHODIMP
987 0 : nsFakePluginTag::GetMimeDescriptions(uint32_t* aCount, char16_t*** aResults)
988 : {
989 0 : return CStringArrayToXPCArray(mMimeDescriptions, aCount, aResults);
990 : }
991 :
992 : NS_IMETHODIMP
993 0 : nsFakePluginTag::GetExtensions(uint32_t* aCount, char16_t*** aResults)
994 : {
995 0 : return CStringArrayToXPCArray(mExtensions, aCount, aResults);
996 : }
997 :
998 : NS_IMETHODIMP
999 0 : nsFakePluginTag::GetActive(bool *aResult)
1000 : {
1001 : // Fake plugins can't be blocklisted, so this is just !Disabled
1002 0 : *aResult = IsEnabled();
1003 0 : return NS_OK;
1004 : }
1005 :
1006 : NS_IMETHODIMP
1007 0 : nsFakePluginTag::GetLastModifiedTime(PRTime* aLastModifiedTime)
1008 : {
1009 : // FIXME-jsplugins What should this return, if anything?
1010 0 : MOZ_ASSERT(aLastModifiedTime);
1011 0 : *aLastModifiedTime = 0;
1012 0 : return NS_OK;
1013 : }
1014 :
1015 : // We don't load fake plugins out of a library, so they should always be there.
1016 : NS_IMETHODIMP
1017 0 : nsFakePluginTag::GetLoaded(bool* ret)
1018 : {
1019 0 : *ret = true;
1020 0 : return NS_OK;
1021 : }
1022 :
1023 : NS_IMETHODIMP
1024 0 : nsFakePluginTag::GetId(uint32_t* aId)
1025 : {
1026 0 : *aId = mId;
1027 0 : return NS_OK;
1028 : }
|