LCOV - code coverage report
Current view: top level - dom/base - nsPluginArray.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 244 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 52 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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             : 
       7             : #include "nsPluginArray.h"
       8             : 
       9             : #include "mozilla/dom/PluginArrayBinding.h"
      10             : #include "mozilla/dom/PluginBinding.h"
      11             : #include "mozilla/dom/HiddenPluginEvent.h"
      12             : 
      13             : #include "nsMimeTypeArray.h"
      14             : #include "Navigator.h"
      15             : #include "nsIDocShell.h"
      16             : #include "nsIWebNavigation.h"
      17             : #include "nsPluginHost.h"
      18             : #include "nsPluginTags.h"
      19             : #include "nsIObserverService.h"
      20             : #include "nsIWeakReference.h"
      21             : #include "mozilla/Services.h"
      22             : #include "nsIInterfaceRequestorUtils.h"
      23             : #include "nsContentUtils.h"
      24             : #include "nsIPermissionManager.h"
      25             : #include "nsIDocument.h"
      26             : #include "nsIBlocklistService.h"
      27             : 
      28             : using namespace mozilla;
      29             : using namespace mozilla::dom;
      30             : 
      31           0 : nsPluginArray::nsPluginArray(nsPIDOMWindowInner* aWindow)
      32           0 :   : mWindow(aWindow)
      33             : {
      34           0 : }
      35             : 
      36             : void
      37           0 : nsPluginArray::Init()
      38             : {
      39             :   nsCOMPtr<nsIObserverService> obsService =
      40           0 :     mozilla::services::GetObserverService();
      41           0 :   if (obsService) {
      42           0 :     obsService->AddObserver(this, "plugin-info-updated", true);
      43             :   }
      44           0 : }
      45             : 
      46             : nsPluginArray::~nsPluginArray() = default;
      47             : 
      48             : nsPIDOMWindowInner*
      49           0 : nsPluginArray::GetParentObject() const
      50             : {
      51           0 :   MOZ_ASSERT(mWindow);
      52           0 :   return mWindow;
      53             : }
      54             : 
      55             : JSObject*
      56           0 : nsPluginArray::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
      57             : {
      58           0 :   return PluginArrayBinding::Wrap(aCx, this, aGivenProto);
      59             : }
      60             : 
      61           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginArray)
      62           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginArray)
      63           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginArray)
      64           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
      65           0 :   NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIObserver)
      66           0 :   NS_INTERFACE_MAP_ENTRY(nsIObserver)
      67           0 :   NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
      68           0 : NS_INTERFACE_MAP_END
      69             : 
      70           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginArray,
      71             :                                       mWindow,
      72             :                                       mPlugins,
      73             :                                       mCTPPlugins)
      74             : 
      75             : static void
      76           0 : GetPluginMimeTypes(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
      77             :                    nsTArray<RefPtr<nsMimeType> >& aMimeTypes)
      78             : {
      79           0 :   for (uint32_t i = 0; i < aPlugins.Length(); ++i) {
      80           0 :     nsPluginElement *plugin = aPlugins[i];
      81           0 :     aMimeTypes.AppendElements(plugin->MimeTypes());
      82             :   }
      83           0 : }
      84             : 
      85             : static bool
      86           0 : operator<(const RefPtr<nsMimeType>& lhs, const RefPtr<nsMimeType>& rhs)
      87             : {
      88             :   // Sort MIME types alphabetically by type name.
      89           0 :   return lhs->Type() < rhs->Type();
      90             : }
      91             : 
      92             : void
      93           0 : nsPluginArray::GetMimeTypes(nsTArray<RefPtr<nsMimeType>>& aMimeTypes)
      94             : {
      95           0 :   aMimeTypes.Clear();
      96             : 
      97           0 :   if (!AllowPlugins()) {
      98           0 :     return;
      99             :   }
     100             : 
     101           0 :   EnsurePlugins();
     102             : 
     103           0 :   GetPluginMimeTypes(mPlugins, aMimeTypes);
     104             : 
     105             :   // Alphabetize the enumeration order of non-hidden MIME types to reduce
     106             :   // fingerprintable entropy based on plugins' installation file times.
     107           0 :   aMimeTypes.Sort();
     108             : }
     109             : 
     110             : void
     111           0 : nsPluginArray::GetCTPMimeTypes(nsTArray<RefPtr<nsMimeType>>& aMimeTypes)
     112             : {
     113           0 :   aMimeTypes.Clear();
     114             : 
     115           0 :   if (!AllowPlugins()) {
     116           0 :     return;
     117             :   }
     118             : 
     119           0 :   EnsurePlugins();
     120             : 
     121           0 :   GetPluginMimeTypes(mCTPPlugins, aMimeTypes);
     122             : 
     123             :   // Alphabetize the enumeration order of non-hidden MIME types to reduce
     124             :   // fingerprintable entropy based on plugins' installation file times.
     125           0 :   aMimeTypes.Sort();
     126             : }
     127             : 
     128             : nsPluginElement*
     129           0 : nsPluginArray::Item(uint32_t aIndex, CallerType aCallerType)
     130             : {
     131             :   bool unused;
     132           0 :   return IndexedGetter(aIndex, unused, aCallerType);
     133             : }
     134             : 
     135             : nsPluginElement*
     136           0 : nsPluginArray::NamedItem(const nsAString& aName, CallerType aCallerType)
     137             : {
     138             :   bool unused;
     139           0 :   return NamedGetter(aName, unused, aCallerType);
     140             : }
     141             : 
     142             : void
     143           0 : nsPluginArray::Refresh(bool aReloadDocuments)
     144             : {
     145           0 :   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
     146             : 
     147           0 :   if(!AllowPlugins() || !pluginHost) {
     148           0 :     return;
     149             :   }
     150             : 
     151             :   // NS_ERROR_PLUGINS_PLUGINSNOTCHANGED on reloading plugins indicates
     152             :   // that plugins did not change and was not reloaded
     153           0 :   if (pluginHost->ReloadPlugins() ==
     154             :       NS_ERROR_PLUGINS_PLUGINSNOTCHANGED) {
     155           0 :     nsTArray<nsCOMPtr<nsIInternalPluginTag> > newPluginTags;
     156           0 :     pluginHost->GetPlugins(newPluginTags);
     157             : 
     158             :     // Check if the number of plugins we know about are different from
     159             :     // the number of plugin tags the plugin host knows about. If the
     160             :     // lengths are different, we refresh. This is safe because we're
     161             :     // notified for every plugin enabling/disabling event that
     162             :     // happens, and therefore the lengths will be in sync only when
     163             :     // the both arrays contain the same plugin tags (though as
     164             :     // different types).
     165           0 :     if (newPluginTags.Length() == mPlugins.Length()) {
     166           0 :       return;
     167             :     }
     168             :   }
     169             : 
     170           0 :   mPlugins.Clear();
     171           0 :   mCTPPlugins.Clear();
     172             : 
     173           0 :   nsCOMPtr<nsIDOMNavigator> navigator = mWindow->GetNavigator();
     174             : 
     175           0 :   if (!navigator) {
     176           0 :     return;
     177             :   }
     178             : 
     179           0 :   static_cast<mozilla::dom::Navigator*>(navigator.get())->RefreshMIMEArray();
     180             : 
     181           0 :   nsCOMPtr<nsIWebNavigation> webNav = do_GetInterface(mWindow);
     182           0 :   if (aReloadDocuments && webNav) {
     183           0 :     webNav->Reload(nsIWebNavigation::LOAD_FLAGS_NONE);
     184             :   }
     185             : }
     186             : 
     187             : nsPluginElement*
     188           0 : nsPluginArray::IndexedGetter(uint32_t aIndex, bool &aFound, CallerType aCallerType)
     189             : {
     190           0 :   aFound = false;
     191             : 
     192           0 :   if (!AllowPlugins() || nsContentUtils::ResistFingerprinting(aCallerType)) {
     193           0 :     return nullptr;
     194             :   }
     195             : 
     196           0 :   EnsurePlugins();
     197             : 
     198           0 :   aFound = aIndex < mPlugins.Length();
     199             : 
     200           0 :   if (!aFound) {
     201           0 :     return nullptr;
     202             :   }
     203             : 
     204           0 :   return mPlugins[aIndex];
     205             : }
     206             : 
     207             : void
     208           0 : nsPluginArray::Invalidate()
     209             : {
     210             :   nsCOMPtr<nsIObserverService> obsService =
     211           0 :     mozilla::services::GetObserverService();
     212           0 :   if (obsService) {
     213           0 :     obsService->RemoveObserver(this, "plugin-info-updated");
     214             :   }
     215           0 : }
     216             : 
     217             : static nsPluginElement*
     218           0 : FindPlugin(const nsTArray<RefPtr<nsPluginElement> >& aPlugins,
     219             :            const nsAString& aName)
     220             : {
     221           0 :   for (uint32_t i = 0; i < aPlugins.Length(); ++i) {
     222           0 :     nsAutoString pluginName;
     223           0 :     nsPluginElement* plugin = aPlugins[i];
     224           0 :     plugin->GetName(pluginName);
     225             : 
     226           0 :     if (pluginName.Equals(aName)) {
     227           0 :       return plugin;
     228             :     }
     229             :   }
     230             : 
     231           0 :   return nullptr;
     232             : }
     233             : 
     234             : nsPluginElement*
     235           0 : nsPluginArray::NamedGetter(const nsAString& aName, bool &aFound,
     236             :                            CallerType aCallerType)
     237             : {
     238           0 :   aFound = false;
     239             : 
     240           0 :   if (!AllowPlugins() || nsContentUtils::ResistFingerprinting(aCallerType)) {
     241           0 :     return nullptr;
     242             :   }
     243             : 
     244           0 :   EnsurePlugins();
     245             : 
     246           0 :   nsPluginElement* plugin = FindPlugin(mPlugins, aName);
     247           0 :   aFound = (plugin != nullptr);
     248           0 :   if (!aFound) {
     249           0 :     nsPluginElement* hiddenPlugin = FindPlugin(mCTPPlugins, aName);
     250           0 :     if (hiddenPlugin) {
     251           0 :       NotifyHiddenPluginTouched(hiddenPlugin);
     252             :     }
     253             :   }
     254           0 :   return plugin;
     255             : }
     256             : 
     257           0 : void nsPluginArray::NotifyHiddenPluginTouched(nsPluginElement* aHiddenElement)
     258             : {
     259           0 :   HiddenPluginEventInit init;
     260           0 :   init.mTag = aHiddenElement->PluginTag();
     261           0 :   nsCOMPtr<nsIDocument> doc = aHiddenElement->GetParentObject()->GetDoc();
     262             :   RefPtr<HiddenPluginEvent> event =
     263           0 :     HiddenPluginEvent::Constructor(doc, NS_LITERAL_STRING("HiddenPlugin"), init);
     264           0 :   event->SetTarget(doc);
     265           0 :   event->SetTrusted(true);
     266           0 :   event->WidgetEventPtr()->mFlags.mOnlyChromeDispatch = true;
     267             :   bool dummy;
     268           0 :   doc->DispatchEvent(event, &dummy);
     269           0 : }
     270             : 
     271             : uint32_t
     272           0 : nsPluginArray::Length(CallerType aCallerType)
     273             : {
     274           0 :   if (!AllowPlugins() || nsContentUtils::ResistFingerprinting(aCallerType)) {
     275           0 :     return 0;
     276             :   }
     277             : 
     278           0 :   EnsurePlugins();
     279             : 
     280           0 :   return mPlugins.Length();
     281             : }
     282             : 
     283             : void
     284           0 : nsPluginArray::GetSupportedNames(nsTArray<nsString>& aRetval,
     285             :                                  CallerType aCallerType)
     286             : {
     287           0 :   aRetval.Clear();
     288             : 
     289           0 :   if (!AllowPlugins() || nsContentUtils::ResistFingerprinting(aCallerType)) {
     290           0 :     return;
     291             :   }
     292             : 
     293           0 :   for (uint32_t i = 0; i < mPlugins.Length(); ++i) {
     294           0 :     nsAutoString pluginName;
     295           0 :     mPlugins[i]->GetName(pluginName);
     296             : 
     297           0 :     aRetval.AppendElement(pluginName);
     298             :   }
     299             : }
     300             : 
     301             : NS_IMETHODIMP
     302           0 : nsPluginArray::Observe(nsISupports *aSubject, const char *aTopic,
     303             :                        const char16_t *aData) {
     304           0 :   if (!nsCRT::strcmp(aTopic, "plugin-info-updated")) {
     305           0 :     Refresh(false);
     306             :   }
     307             : 
     308           0 :   return NS_OK;
     309             : }
     310             : 
     311             : bool
     312           0 : nsPluginArray::AllowPlugins() const
     313             : {
     314           0 :   if (!mWindow) {
     315           0 :     return false;
     316             :   }
     317           0 :   nsCOMPtr<nsIDocument> doc = mWindow->GetDoc();
     318           0 :   if (!doc) {
     319           0 :     return false;
     320             :   }
     321             : 
     322           0 :   return doc->GetAllowPlugins();
     323             : }
     324             : 
     325             : static bool
     326           0 : operator<(const RefPtr<nsPluginElement>& lhs,
     327             :           const RefPtr<nsPluginElement>& rhs)
     328             : {
     329             :   // Sort plugins alphabetically by name.
     330           0 :   return lhs->PluginTag()->Name() < rhs->PluginTag()->Name();
     331             : }
     332             : 
     333             : static bool
     334           0 : PluginShouldBeHidden(const nsCString& aName) {
     335             :   // This only supports one hidden plugin
     336           0 :   return Preferences::GetCString("plugins.navigator.hidden_ctp_plugin").Equals(aName);
     337             : }
     338             : 
     339             : void
     340           0 : nsPluginArray::EnsurePlugins()
     341             : {
     342           0 :   if (!mPlugins.IsEmpty() || !mCTPPlugins.IsEmpty()) {
     343             :     // We already have an array of plugin elements.
     344           0 :     return;
     345             :   }
     346             : 
     347           0 :   RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
     348           0 :   if (!pluginHost) {
     349             :     // We have no plugin host.
     350           0 :     return;
     351             :   }
     352             : 
     353           0 :   nsTArray<nsCOMPtr<nsIInternalPluginTag> > pluginTags;
     354           0 :   pluginHost->GetPlugins(pluginTags);
     355             : 
     356             :   // need to wrap each of these with a nsPluginElement, which is
     357             :   // scriptable.
     358           0 :   for (uint32_t i = 0; i < pluginTags.Length(); ++i) {
     359           0 :     nsCOMPtr<nsPluginTag> pluginTag = do_QueryInterface(pluginTags[i]);
     360           0 :     if (!pluginTag) {
     361           0 :       mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
     362           0 :     } else if (pluginTag->IsActive()) {
     363           0 :       uint32_t permission = nsIPermissionManager::ALLOW_ACTION;
     364             :       uint32_t blocklistState;
     365           0 :       if (pluginTag->IsClicktoplay() &&
     366           0 :           NS_SUCCEEDED(pluginTag->GetBlocklistState(&blocklistState)) &&
     367           0 :           blocklistState == nsIBlocklistService::STATE_NOT_BLOCKED) {
     368           0 :         nsCString name;
     369           0 :         pluginTag->GetName(name);
     370           0 :         if (PluginShouldBeHidden(name)) {
     371           0 :           RefPtr<nsPluginHost> pluginHost = nsPluginHost::GetInst();
     372           0 :           nsCString permString;
     373           0 :           nsresult rv = pluginHost->GetPermissionStringForTag(pluginTag, 0, permString);
     374           0 :           if (rv == NS_OK) {
     375           0 :             nsCOMPtr<nsIDocument> currentDoc = mWindow->GetExtantDoc();
     376             : 
     377             :             // The top-level content document gets the final say on whether or not
     378             :             // a plugin is going to be hidden or not, regardless of the origin
     379             :             // that a subframe is hosted at. This is to avoid spamming the user
     380             :             // with the hidden plugin notification bar when third-party iframes
     381             :             // attempt to access navigator.plugins after the user has already
     382             :             // expressed that the top-level document has this permission.
     383           0 :             nsCOMPtr<nsIDocument> topDoc = currentDoc->GetTopLevelContentDocument();
     384             : 
     385           0 :             if (topDoc) {
     386           0 :               nsIPrincipal* principal = topDoc->NodePrincipal();
     387           0 :               nsCOMPtr<nsIPermissionManager> permMgr = services::GetPermissionManager();
     388           0 :               permMgr->TestPermissionFromPrincipal(principal, permString.get(), &permission);
     389             :             }
     390             :           }
     391             :         }
     392             :       }
     393           0 :       if (permission == nsIPermissionManager::ALLOW_ACTION) {
     394           0 :         mPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
     395             :       } else {
     396           0 :         mCTPPlugins.AppendElement(new nsPluginElement(mWindow, pluginTags[i]));
     397             :       }
     398             :     }
     399             :   }
     400             : 
     401           0 :   if (mPlugins.Length() == 0 && mCTPPlugins.Length() != 0) {
     402             :     nsCOMPtr<nsPluginTag> hiddenTag = new nsPluginTag("Hidden Plugin", nullptr, "dummy.plugin", nullptr, nullptr,
     403           0 :                                                       nullptr, nullptr, nullptr, 0, 0, false);
     404           0 :     mPlugins.AppendElement(new nsPluginElement(mWindow, hiddenTag));
     405             :   }
     406             : 
     407             :   // Alphabetize the enumeration order of non-hidden plugins to reduce
     408             :   // fingerprintable entropy based on plugins' installation file times.
     409           0 :   mPlugins.Sort();
     410             : }
     411             : // nsPluginElement implementation.
     412             : 
     413           0 : NS_IMPL_CYCLE_COLLECTING_ADDREF(nsPluginElement)
     414           0 : NS_IMPL_CYCLE_COLLECTING_RELEASE(nsPluginElement)
     415           0 : NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(nsPluginElement)
     416           0 :   NS_WRAPPERCACHE_INTERFACE_MAP_ENTRY
     417           0 :   NS_INTERFACE_MAP_ENTRY(nsISupports)
     418           0 : NS_INTERFACE_MAP_END
     419             : 
     420           0 : NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(nsPluginElement, mWindow, mMimeTypes)
     421             : 
     422           0 : nsPluginElement::nsPluginElement(nsPIDOMWindowInner* aWindow,
     423           0 :                                  nsIInternalPluginTag* aPluginTag)
     424             :   : mWindow(aWindow),
     425           0 :     mPluginTag(aPluginTag)
     426             : {
     427           0 : }
     428             : 
     429             : nsPluginElement::~nsPluginElement() = default;
     430             : 
     431             : nsPIDOMWindowInner*
     432           0 : nsPluginElement::GetParentObject() const
     433             : {
     434           0 :   MOZ_ASSERT(mWindow);
     435           0 :   return mWindow;
     436             : }
     437             : 
     438             : JSObject*
     439           0 : nsPluginElement::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
     440             : {
     441           0 :   return PluginBinding::Wrap(aCx, this, aGivenProto);
     442             : }
     443             : 
     444             : void
     445           0 : nsPluginElement::GetDescription(nsString& retval) const
     446             : {
     447           0 :   CopyUTF8toUTF16(mPluginTag->Description(), retval);
     448           0 : }
     449             : 
     450             : void
     451           0 : nsPluginElement::GetFilename(nsString& retval) const
     452             : {
     453           0 :   CopyUTF8toUTF16(mPluginTag->FileName(), retval);
     454           0 : }
     455             : 
     456             : void
     457           0 : nsPluginElement::GetVersion(nsString& retval) const
     458             : {
     459           0 :   CopyUTF8toUTF16(mPluginTag->Version(), retval);
     460           0 : }
     461             : 
     462             : void
     463           0 : nsPluginElement::GetName(nsString& retval) const
     464             : {
     465           0 :   CopyUTF8toUTF16(mPluginTag->Name(), retval);
     466           0 : }
     467             : 
     468             : nsMimeType*
     469           0 : nsPluginElement::Item(uint32_t aIndex)
     470             : {
     471           0 :   EnsurePluginMimeTypes();
     472             : 
     473           0 :   return mMimeTypes.SafeElementAt(aIndex);
     474             : }
     475             : 
     476             : nsMimeType*
     477           0 : nsPluginElement::NamedItem(const nsAString& aName)
     478             : {
     479             :   bool unused;
     480           0 :   return NamedGetter(aName, unused);
     481             : }
     482             : 
     483             : nsMimeType*
     484           0 : nsPluginElement::IndexedGetter(uint32_t aIndex, bool &aFound)
     485             : {
     486           0 :   EnsurePluginMimeTypes();
     487             : 
     488           0 :   aFound = aIndex < mMimeTypes.Length();
     489             : 
     490           0 :   if (!aFound) {
     491           0 :     return nullptr;
     492             :   }
     493             : 
     494           0 :   return mMimeTypes[aIndex];
     495             : }
     496             : 
     497             : nsMimeType*
     498           0 : nsPluginElement::NamedGetter(const nsAString& aName, bool &aFound)
     499             : {
     500           0 :   EnsurePluginMimeTypes();
     501             : 
     502           0 :   aFound = false;
     503             : 
     504           0 :   for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
     505           0 :     if (mMimeTypes[i]->Type().Equals(aName)) {
     506           0 :       aFound = true;
     507             : 
     508           0 :       return mMimeTypes[i];
     509             :     }
     510             :   }
     511             : 
     512           0 :   return nullptr;
     513             : }
     514             : 
     515             : uint32_t
     516           0 : nsPluginElement::Length()
     517             : {
     518           0 :   EnsurePluginMimeTypes();
     519             : 
     520           0 :   return mMimeTypes.Length();
     521             : }
     522             : 
     523             : void
     524           0 : nsPluginElement::GetSupportedNames(nsTArray<nsString>& retval)
     525             : {
     526           0 :   EnsurePluginMimeTypes();
     527             : 
     528           0 :   for (uint32_t i = 0; i < mMimeTypes.Length(); ++i) {
     529           0 :     retval.AppendElement(mMimeTypes[i]->Type());
     530             :   }
     531           0 : }
     532             : 
     533             : nsTArray<RefPtr<nsMimeType> >&
     534           0 : nsPluginElement::MimeTypes()
     535             : {
     536           0 :   EnsurePluginMimeTypes();
     537             : 
     538           0 :   return mMimeTypes;
     539             : }
     540             : 
     541             : void
     542           0 : nsPluginElement::EnsurePluginMimeTypes()
     543             : {
     544           0 :   if (!mMimeTypes.IsEmpty()) {
     545           0 :     return;
     546             :   }
     547             : 
     548           0 :   if (mPluginTag->MimeTypes().Length() != mPluginTag->MimeDescriptions().Length() ||
     549           0 :       mPluginTag->MimeTypes().Length() != mPluginTag->Extensions().Length()) {
     550           0 :     MOZ_ASSERT(false, "mime type arrays expected to be the same length");
     551             :     return;
     552             :   }
     553             : 
     554           0 :   for (uint32_t i = 0; i < mPluginTag->MimeTypes().Length(); ++i) {
     555           0 :     NS_ConvertUTF8toUTF16 type(mPluginTag->MimeTypes()[i]);
     556           0 :     NS_ConvertUTF8toUTF16 description(mPluginTag->MimeDescriptions()[i]);
     557           0 :     NS_ConvertUTF8toUTF16 extension(mPluginTag->Extensions()[i]);
     558             : 
     559           0 :     mMimeTypes.AppendElement(new nsMimeType(mWindow, this, type, description,
     560           0 :                                             extension));
     561             :   }
     562             : }

Generated by: LCOV version 1.13