LCOV - code coverage report
Current view: top level - chrome - nsChromeRegistryChrome.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 322 491 65.6 %
Date: 2017-07-14 16:53:18 Functions: 33 39 84.6 %
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=2 sts=2 sw=2 et 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 "mozilla/dom/ContentParent.h"
       8             : #include "RegistryMessageUtils.h"
       9             : #include "nsResProtocolHandler.h"
      10             : 
      11             : #include "nsChromeRegistryChrome.h"
      12             : 
      13             : #if defined(XP_WIN)
      14             : #include <windows.h>
      15             : #elif defined(XP_MACOSX)
      16             : #include <CoreServices/CoreServices.h>
      17             : #endif
      18             : 
      19             : #include "nsArrayEnumerator.h"
      20             : #include "nsComponentManager.h"
      21             : #include "nsEnumeratorUtils.h"
      22             : #include "nsNetUtil.h"
      23             : #include "nsStringEnumerator.h"
      24             : #include "nsTextFormatter.h"
      25             : #include "nsXPCOMCIDInternal.h"
      26             : 
      27             : #include "mozilla/LookAndFeel.h"
      28             : #include "mozilla/Unused.h"
      29             : #include "mozilla/intl/LocaleService.h"
      30             : 
      31             : #include "nsIObserverService.h"
      32             : #include "nsIPrefBranch.h"
      33             : #include "nsIPrefService.h"
      34             : #include "mozilla/Preferences.h"
      35             : #include "nsIResProtocolHandler.h"
      36             : #include "nsIScriptError.h"
      37             : #include "nsIXULRuntime.h"
      38             : 
      39             : #define SELECTED_SKIN_PREF   "general.skins.selectedSkin"
      40             : #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
      41             : 
      42             : using namespace mozilla;
      43             : using mozilla::dom::ContentParent;
      44             : using mozilla::dom::PContentParent;
      45             : using mozilla::intl::LocaleService;
      46             : 
      47             : // We use a "best-fit" algorithm for matching locales and themes.
      48             : // 1) the exact selected locale/theme
      49             : // 2) (locales only) same language, different country
      50             : //    e.g. en-GB is the selected locale, only en-US is available
      51             : // 3) any available locale/theme
      52             : 
      53             : /**
      54             :  * Match the language-part of two lang-COUNTRY codes, hopefully but
      55             :  * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
      56             :  * work, any other garbage-in will produce undefined results as long
      57             :  * as it does not crash.
      58             :  */
      59             : static bool
      60           0 : LanguagesMatch(const nsACString& a, const nsACString& b)
      61             : {
      62           0 :   if (a.Length() < 2 || b.Length() < 2)
      63           0 :     return false;
      64             : 
      65           0 :   nsACString::const_iterator as, ae, bs, be;
      66           0 :   a.BeginReading(as);
      67           0 :   a.EndReading(ae);
      68           0 :   b.BeginReading(bs);
      69           0 :   b.EndReading(be);
      70             : 
      71           0 :   while (*as == *bs) {
      72           0 :     if (*as == '-')
      73           0 :       return true;
      74             : 
      75           0 :     ++as; ++bs;
      76             : 
      77             :     // reached the end
      78           0 :     if (as == ae && bs == be)
      79           0 :       return true;
      80             : 
      81             :     // "a" is short
      82           0 :     if (as == ae)
      83           0 :       return (*bs == '-');
      84             : 
      85             :     // "b" is short
      86           0 :     if (bs == be)
      87           0 :       return (*as == '-');
      88             :   }
      89             : 
      90           0 :   return false;
      91             : }
      92             : 
      93           1 : nsChromeRegistryChrome::nsChromeRegistryChrome()
      94             :   : mProfileLoaded(false)
      95           1 :   , mDynamicRegistration(true)
      96             : {
      97           1 : }
      98             : 
      99           0 : nsChromeRegistryChrome::~nsChromeRegistryChrome()
     100             : {
     101           0 : }
     102             : 
     103             : nsresult
     104           1 : nsChromeRegistryChrome::Init()
     105             : {
     106           1 :   nsresult rv = nsChromeRegistry::Init();
     107           1 :   if (NS_FAILED(rv))
     108           0 :     return rv;
     109             : 
     110           1 :   mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
     111             : 
     112           1 :   bool safeMode = false;
     113           2 :   nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
     114           1 :   if (xulrun)
     115           1 :     xulrun->GetInSafeMode(&safeMode);
     116             : 
     117           2 :   nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
     118           2 :   nsCOMPtr<nsIPrefBranch> prefs;
     119             : 
     120           1 :   if (prefserv) {
     121           1 :     if (safeMode) {
     122           0 :       prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
     123             :     } else {
     124           1 :       prefs = do_QueryInterface(prefserv);
     125             :     }
     126             :   }
     127             : 
     128           1 :   if (!prefs) {
     129           0 :     NS_WARNING("Could not get pref service!");
     130             :   } else {
     131           2 :     nsXPIDLCString provider;
     132           1 :     rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider));
     133           1 :     if (NS_SUCCEEDED(rv))
     134           1 :       mSelectedSkin = provider;
     135             : 
     136           1 :     rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
     137             :   }
     138             : 
     139           2 :   nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
     140           1 :   if (obsService) {
     141           1 :     obsService->AddObserver(this, "profile-initial-state", true);
     142           1 :     obsService->AddObserver(this, "intl:app-locales-changed", true);
     143             :   }
     144             : 
     145           1 :   return NS_OK;
     146             : }
     147             : 
     148             : NS_IMETHODIMP
     149           1 : nsChromeRegistryChrome::CheckForOSAccessibility()
     150             : {
     151             :   int32_t useAccessibilityTheme =
     152           1 :     LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
     153             : 
     154           1 :   if (useAccessibilityTheme) {
     155             :     /* Set the skin to classic and remove pref observers */
     156           0 :     if (!mSelectedSkin.EqualsLiteral("classic/1.0")) {
     157           0 :       mSelectedSkin.AssignLiteral("classic/1.0");
     158           0 :       RefreshSkins();
     159             :     }
     160             : 
     161           0 :     nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
     162           0 :     if (prefs) {
     163           0 :       prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
     164             :     }
     165             :   }
     166             : 
     167           1 :   return NS_OK;
     168             : }
     169             : 
     170             : NS_IMETHODIMP
     171           2 : nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage,
     172             :                                        nsIUTF8StringEnumerator* *aResult)
     173             : {
     174           4 :   nsCString realpackage;
     175           2 :   nsresult rv = OverrideLocalePackage(aPackage, realpackage);
     176           2 :   if (NS_FAILED(rv))
     177           0 :     return rv;
     178             : 
     179           2 :   nsTArray<nsCString> *a = new nsTArray<nsCString>;
     180           2 :   if (!a)
     181           0 :     return NS_ERROR_OUT_OF_MEMORY;
     182             : 
     183             :   PackageEntry* entry;
     184           2 :   if (mPackagesHash.Get(realpackage, &entry)) {
     185           1 :     entry->locales.EnumerateToArray(a);
     186             :   }
     187             : 
     188           2 :   rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
     189           2 :   if (NS_FAILED(rv))
     190           0 :     delete a;
     191             : 
     192           2 :   return rv;
     193             : }
     194             : 
     195             : NS_IMETHODIMP
     196           1 : nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult)
     197             : {
     198           1 :   *aResult = false;
     199             : 
     200           2 :   nsAutoCString locale;
     201           1 :   GetSelectedLocale(package, false, locale);
     202           1 :   if (locale.Length() < 2)
     203           0 :     return NS_OK;
     204             : 
     205           1 :   *aResult = GetDirectionForLocale(locale);
     206           1 :   return NS_OK;
     207             : }
     208             : 
     209             : /**
     210             :  * This method negotiates only between the app locale and the available
     211             :  * chrome packages.
     212             :  *
     213             :  * If you want to get the current application's UI locale, please use
     214             :  * LocaleService::GetAppLocaleAsLangTag.
     215             :  */
     216             : nsresult
     217           1 : nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
     218             :                                           bool aAsBCP47,
     219             :                                           nsACString& aLocale)
     220             : {
     221           2 :   nsAutoCString reqLocale;
     222           1 :   if (aPackage.Equals("global")) {
     223           0 :     LocaleService::GetInstance()->GetAppLocaleAsLangTag(reqLocale);
     224             :   } else {
     225           2 :     AutoTArray<nsCString, 10> requestedLocales;
     226           1 :     LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
     227           1 :     reqLocale.Assign(requestedLocales[0]);
     228             :   }
     229             : 
     230           2 :   nsCString realpackage;
     231           1 :   nsresult rv = OverrideLocalePackage(aPackage, realpackage);
     232           1 :   if (NS_FAILED(rv))
     233           0 :     return rv;
     234             :   PackageEntry* entry;
     235           1 :   if (!mPackagesHash.Get(realpackage, &entry))
     236           0 :     return NS_ERROR_FILE_NOT_FOUND;
     237             : 
     238           1 :   aLocale = entry->locales.GetSelected(reqLocale, nsProviderArray::LOCALE);
     239           1 :   if (aLocale.IsEmpty())
     240           0 :     return NS_ERROR_FAILURE;
     241             : 
     242           1 :   if (aAsBCP47) {
     243           0 :     SanitizeForBCP47(aLocale);
     244             :   }
     245             : 
     246           1 :   return NS_OK;
     247             : }
     248             : 
     249             : nsresult
     250          27 : nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage,
     251             :                                               nsACString& aOverride)
     252             : {
     253          54 :   const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
     254          54 :   nsAdoptingCString override = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get());
     255          27 :   if (override) {
     256           0 :     aOverride = override;
     257             :   }
     258             :   else {
     259          27 :     aOverride = aPackage;
     260             :   }
     261          54 :   return NS_OK;
     262             : }
     263             : 
     264             : NS_IMETHODIMP
     265           1 : nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic,
     266             :                                 const char16_t *someData)
     267             : {
     268           1 :   nsresult rv = NS_OK;
     269             : 
     270           1 :   if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
     271           0 :     nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
     272           0 :     NS_ASSERTION(prefs, "Bad observer call!");
     273             : 
     274           0 :     NS_ConvertUTF16toUTF8 pref(someData);
     275             : 
     276           0 :     if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
     277           0 :       nsXPIDLCString provider;
     278           0 :       rv = prefs->GetCharPref(pref.get(), getter_Copies(provider));
     279           0 :       if (NS_FAILED(rv)) {
     280           0 :         NS_ERROR("Couldn't get new skin pref!");
     281           0 :         return rv;
     282             :       }
     283             : 
     284           0 :       mSelectedSkin = provider;
     285           0 :       RefreshSkins();
     286             :     } else {
     287           0 :       NS_ERROR("Unexpected pref!");
     288             :     }
     289             :   }
     290           1 :   else if (!strcmp("profile-initial-state", aTopic)) {
     291           1 :     mProfileLoaded = true;
     292             :   }
     293           0 :   else if (!strcmp("intl:app-locales-changed", aTopic)) {
     294           0 :     if (mProfileLoaded) {
     295           0 :       FlushAllCaches();
     296             :     }
     297             :   }
     298             :   else {
     299           0 :     NS_ERROR("Unexpected observer topic!");
     300             :   }
     301             : 
     302           1 :   return rv;
     303             : }
     304             : 
     305             : NS_IMETHODIMP
     306           0 : nsChromeRegistryChrome::CheckForNewChrome()
     307             : {
     308           0 :   mPackagesHash.Clear();
     309           0 :   mOverlayHash.Clear();
     310           0 :   mStyleHash.Clear();
     311           0 :   mOverrideTable.Clear();
     312             : 
     313           0 :   mDynamicRegistration = false;
     314             : 
     315           0 :   nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
     316             : 
     317           0 :   mDynamicRegistration = true;
     318             : 
     319           0 :   SendRegisteredChrome(nullptr);
     320           0 :   return NS_OK;
     321             : }
     322             : 
     323             : static void
     324         579 : SerializeURI(nsIURI* aURI,
     325             :              SerializedURI& aSerializedURI)
     326             : {
     327         579 :   if (!aURI)
     328         236 :     return;
     329             : 
     330         343 :   aURI->GetSpec(aSerializedURI.spec);
     331         343 :   aURI->GetOriginCharset(aSerializedURI.charset);
     332             : }
     333             : 
     334             : void
     335           2 : nsChromeRegistryChrome::SendRegisteredChrome(
     336             :     mozilla::dom::PContentParent* aParent)
     337             : {
     338           4 :   InfallibleTArray<ChromePackage> packages;
     339           4 :   InfallibleTArray<SubstitutionMapping> resources;
     340           4 :   InfallibleTArray<OverrideMapping> overrides;
     341             : 
     342          90 :   for (auto iter = mPackagesHash.Iter(); !iter.Done(); iter.Next()) {
     343         176 :     ChromePackage chromePackage;
     344          88 :     ChromePackageFromPackageEntry(iter.Key(), iter.UserData(), &chromePackage,
     345          88 :                                   mSelectedSkin);
     346          88 :     packages.AppendElement(chromePackage);
     347             :   }
     348             : 
     349             :   // If we were passed a parent then a new child process has been created and
     350             :   // has requested all of the chrome so send it the resources too. Otherwise
     351             :   // resource mappings are sent by the resource protocol handler dynamically.
     352           2 :   if (aParent) {
     353           4 :     nsCOMPtr<nsIIOService> io (do_GetIOService());
     354           2 :     NS_ENSURE_TRUE_VOID(io);
     355             : 
     356           4 :     nsCOMPtr<nsIProtocolHandler> ph;
     357           2 :     nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
     358           2 :     NS_ENSURE_SUCCESS_VOID(rv);
     359             : 
     360           4 :     nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
     361           2 :     nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
     362           2 :     rv = rph->CollectSubstitutions(resources);
     363           2 :     NS_ENSURE_SUCCESS_VOID(rv);
     364             :   }
     365             : 
     366          42 :   for (auto iter = mOverrideTable.Iter(); !iter.Done(); iter.Next()) {
     367          80 :     SerializedURI chromeURI, overrideURI;
     368             : 
     369          40 :     SerializeURI(iter.Key(), chromeURI);
     370          40 :     SerializeURI(iter.UserData(), overrideURI);
     371             : 
     372          80 :     OverrideMapping override = { chromeURI, overrideURI };
     373          40 :     overrides.AppendElement(override);
     374             :   }
     375             : 
     376           4 :   nsAutoCString appLocale;
     377           2 :   LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
     378             : 
     379           2 :   if (aParent) {
     380           4 :     bool success = aParent->SendRegisterChrome(packages, resources, overrides,
     381           2 :                                                appLocale, false);
     382           2 :     NS_ENSURE_TRUE_VOID(success);
     383             :   } else {
     384           0 :     nsTArray<ContentParent*> parents;
     385           0 :     ContentParent::GetAll(parents);
     386           0 :     if (!parents.Length())
     387           0 :       return;
     388             : 
     389           0 :     for (uint32_t i = 0; i < parents.Length(); i++) {
     390             :       DebugOnly<bool> success =
     391           0 :         parents[i]->SendRegisterChrome(packages, resources, overrides,
     392           0 :                                        appLocale, true);
     393           0 :       NS_WARNING_ASSERTION(success,
     394             :                            "couldn't reset a child's registered chrome");
     395             :     }
     396             :   }
     397             : }
     398             : 
     399             : /* static */ void
     400         153 : nsChromeRegistryChrome::ChromePackageFromPackageEntry(const nsACString& aPackageName,
     401             :                                                       PackageEntry* aPackage,
     402             :                                                       ChromePackage* aChromePackage,
     403             :                                                       const nsCString& aSelectedSkin)
     404             : {
     405         306 :   nsAutoCString appLocale;
     406         153 :   LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
     407             : 
     408         153 :   SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
     409         153 :   SerializeURI(aPackage->locales.GetBase(appLocale, nsProviderArray::LOCALE),
     410         153 :                aChromePackage->localeBaseURI);
     411         153 :   SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
     412         153 :                aChromePackage->skinBaseURI);
     413         153 :   aChromePackage->package = aPackageName;
     414         153 :   aChromePackage->flags = aPackage->flags;
     415         153 : }
     416             : 
     417             : static bool
     418         103 : CanLoadResource(nsIURI* aResourceURI)
     419             : {
     420         103 :   bool isLocalResource = false;
     421             :   (void)NS_URIChainHasFlags(aResourceURI,
     422             :                             nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
     423         103 :                             &isLocalResource);
     424         103 :   return isLocalResource;
     425             : }
     426             : 
     427             : nsIURI*
     428         179 : nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
     429             :                                               const nsCString& aProvider,
     430             :                                               const nsCString& aPath)
     431             : {
     432             :   PackageEntry* entry;
     433         179 :   if (!mPackagesHash.Get(aPackage, &entry)) {
     434           0 :     if (!mInitialized)
     435           0 :       return nullptr;
     436             : 
     437           0 :     LogMessage("No chrome package registered for chrome://%s/%s/%s",
     438           0 :                aPackage.get(), aProvider.get(), aPath.get());
     439             : 
     440           0 :     return nullptr;
     441             :   }
     442             : 
     443         179 :   if (aProvider.EqualsLiteral("locale")) {
     444          38 :     nsAutoCString appLocale;
     445          19 :     LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
     446          19 :     return entry->locales.GetBase(appLocale, nsProviderArray::LOCALE);
     447             :   }
     448         160 :   else if (aProvider.EqualsLiteral("skin")) {
     449          61 :     return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
     450             :   }
     451          99 :   else if (aProvider.EqualsLiteral("content")) {
     452          99 :     return entry->baseURI;
     453             :   }
     454           0 :   return nullptr;
     455             : }
     456             : 
     457             : nsresult
     458         893 : nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
     459             :                                             uint32_t* aFlags)
     460             : {
     461             :   PackageEntry* entry;
     462         893 :   if (!mPackagesHash.Get(aPackage, &entry))
     463           0 :     return NS_ERROR_FILE_NOT_FOUND;
     464             : 
     465         893 :   *aFlags = entry->flags;
     466         893 :   return NS_OK;
     467             : }
     468             : 
     469             : nsChromeRegistryChrome::ProviderEntry*
     470         426 : nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
     471             : {
     472         426 :   size_t i = mArray.Length();
     473         426 :   if (!i)
     474         215 :     return nullptr;
     475             : 
     476         211 :   ProviderEntry* found = nullptr;  // Only set if we find a partial-match locale
     477         211 :   ProviderEntry* entry = nullptr;
     478             : 
     479         211 :   while (i--) {
     480         211 :     entry = &mArray[i];
     481         211 :     if (aPreferred.Equals(entry->provider))
     482         211 :       return entry;
     483             : 
     484           0 :     if (aType != LOCALE)
     485           0 :       continue;
     486             : 
     487           0 :     if (LanguagesMatch(aPreferred, entry->provider)) {
     488           0 :       found = entry;
     489           0 :       continue;
     490             :     }
     491             : 
     492           0 :     if (!found && entry->provider.EqualsLiteral("en-US"))
     493           0 :       found = entry;
     494             :   }
     495             : 
     496           0 :   if (!found && aType != EXACT)
     497           0 :     return entry;
     498             : 
     499           0 :   return found;
     500             : }
     501             : 
     502             : nsIURI*
     503         386 : nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
     504             : {
     505         386 :   ProviderEntry* provider = GetProvider(aPreferred, aType);
     506             : 
     507         386 :   if (!provider)
     508         176 :     return nullptr;
     509             : 
     510         210 :   return provider->baseURI;
     511             : }
     512             : 
     513             : const nsACString&
     514           1 : nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
     515             : {
     516           1 :   ProviderEntry* entry = GetProvider(aPreferred, aType);
     517             : 
     518           1 :   if (entry)
     519           1 :     return entry->provider;
     520             : 
     521           0 :   return EmptyCString();
     522             : }
     523             : 
     524             : void
     525          39 : nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
     526             : {
     527          39 :   ProviderEntry* provider = GetProvider(aProvider, EXACT);
     528             : 
     529          39 :   if (provider) {
     530           0 :     provider->baseURI = aBaseURL;
     531           0 :     return;
     532             :   }
     533             : 
     534             :   // no existing entries, add a new one
     535          39 :   mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
     536             : }
     537             : 
     538             : void
     539           1 : nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
     540             : {
     541           1 :   int32_t i = mArray.Length();
     542           3 :   while (i--) {
     543           1 :     a->AppendElement(mArray[i].provider);
     544             :   }
     545           1 : }
     546             : 
     547             : void
     548           7 : nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
     549             : {
     550           7 :   int32_t i = mArray.Count();
     551          11 :   while (i--) {
     552             :     bool equals;
     553           2 :     if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals)
     554           0 :       return;
     555             :   }
     556             : 
     557           7 :   mArray.AppendObject(aURI);
     558             : }
     559             : 
     560             : void
     561           7 : nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay)
     562             : {
     563           7 :   OverlayListEntry* entry = mTable.PutEntry(aBase);
     564           7 :   if (entry)
     565           7 :     entry->AddURI(aOverlay);
     566           7 : }
     567             : 
     568             : const nsCOMArray<nsIURI>*
     569           6 : nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
     570             : {
     571           6 :   OverlayListEntry* entry = mTable.GetEntry(aBase);
     572           6 :   if (!entry)
     573           5 :     return nullptr;
     574             : 
     575           1 :   return &entry->mArray;
     576             : }
     577             : 
     578             : #ifdef MOZ_XUL
     579             : NS_IMETHODIMP
     580           0 : nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
     581             :                                          nsISimpleEnumerator **aResult)
     582             : {
     583           0 :   nsCOMPtr<nsIURI> chromeURLWithoutHash;
     584           0 :   if (aChromeURL) {
     585           0 :     aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
     586             :   }
     587           0 :   const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(chromeURLWithoutHash);
     588           0 :   if (!parray)
     589           0 :     return NS_NewEmptyEnumerator(aResult);
     590             : 
     591           0 :   return NS_NewArrayEnumerator(aResult, *parray);
     592             : }
     593             : 
     594             : NS_IMETHODIMP
     595           6 : nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
     596             :                                        nsISimpleEnumerator **aResult)
     597             : {
     598          12 :   nsCOMPtr<nsIURI> chromeURLWithoutHash;
     599           6 :   if (aChromeURL) {
     600           6 :     aChromeURL->CloneIgnoringRef(getter_AddRefs(chromeURLWithoutHash));
     601             :   }
     602           6 :   const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(chromeURLWithoutHash);
     603           6 :   if (!parray)
     604           5 :     return NS_NewEmptyEnumerator(aResult);
     605             : 
     606           1 :   return NS_NewArrayEnumerator(aResult, *parray);
     607             : }
     608             : #endif // MOZ_XUL
     609             : 
     610             : nsIURI*
     611         130 : nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
     612             : {
     613         130 :   if (!mManifestURI) {
     614          66 :     nsCString uri;
     615          33 :     mFile.GetURIString(uri);
     616          33 :     NS_NewURI(getter_AddRefs(mManifestURI), uri);
     617             :   }
     618         130 :   return mManifestURI;
     619             : }
     620             : 
     621             : already_AddRefed<nsIURI>
     622         130 : nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
     623             : {
     624         130 :   nsIURI* baseuri = GetManifestURI();
     625         130 :   if (!baseuri)
     626           0 :     return nullptr;
     627             : 
     628         260 :   nsCOMPtr<nsIURI> resolved;
     629         130 :   nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
     630         130 :   if (NS_FAILED(rv))
     631           0 :     return nullptr;
     632             : 
     633         130 :   return resolved.forget();
     634             : }
     635             : 
     636             : static void
     637         859 : EnsureLowerCase(char *aBuf)
     638             : {
     639        1642 :   for (; *aBuf; ++aBuf) {
     640         783 :     char ch = *aBuf;
     641         783 :     if (ch >= 'A' && ch <= 'Z')
     642           0 :       *aBuf = ch + 'a' - 'A';
     643             :   }
     644          76 : }
     645             : 
     646             : static void
     647          85 : SendManifestEntry(const ChromeRegistryItem &aItem)
     648             : {
     649          85 :   nsTArray<ContentParent*> parents;
     650          85 :   ContentParent::GetAll(parents);
     651          85 :   if (!parents.Length())
     652          85 :     return;
     653             : 
     654           0 :   for (uint32_t i = 0; i < parents.Length(); i++) {
     655           0 :     Unused << parents[i]->SendRegisterChromeItem(aItem);
     656             :   }
     657             : }
     658             : 
     659             : void
     660          26 : nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
     661             :                                         char *const * argv, int flags)
     662             : {
     663          26 :   char* package = argv[0];
     664          26 :   char* uri = argv[1];
     665             : 
     666          26 :   EnsureLowerCase(package);
     667             : 
     668          52 :   nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
     669          26 :   if (!resolved) {
     670           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     671           0 :                           "During chrome registration, unable to create URI '%s'.", uri);
     672           0 :     return;
     673             :   }
     674             : 
     675          26 :   if (!CanLoadResource(resolved)) {
     676           0 :     LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
     677             :                           "During chrome registration, cannot register non-local URI '%s' as content.",
     678           0 :                           uri);
     679           0 :     return;
     680             :   }
     681             : 
     682          52 :   nsDependentCString packageName(package);
     683          26 :   PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
     684          26 :   entry->baseURI = resolved;
     685          26 :   entry->flags = flags;
     686             : 
     687          26 :   if (mDynamicRegistration) {
     688          52 :     ChromePackage chromePackage;
     689          26 :     ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
     690          26 :                                   mSelectedSkin);
     691          26 :     SendManifestEntry(chromePackage);
     692             :   }
     693             : }
     694             : 
     695             : void
     696          24 : nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
     697             :                                        char *const * argv, int flags)
     698             : {
     699          24 :   char* package = argv[0];
     700          24 :   char* provider = argv[1];
     701          24 :   char* uri = argv[2];
     702             : 
     703          24 :   EnsureLowerCase(package);
     704             : 
     705          48 :   nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
     706          24 :   if (!resolved) {
     707           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     708           0 :                           "During chrome registration, unable to create URI '%s'.", uri);
     709           0 :     return;
     710             :   }
     711             : 
     712          24 :   if (!CanLoadResource(resolved)) {
     713           0 :     LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
     714             :                           "During chrome registration, cannot register non-local URI '%s' as content.",
     715           0 :                           uri);
     716           0 :     return;
     717             :   }
     718             : 
     719          48 :   nsDependentCString packageName(package);
     720          24 :   PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
     721          24 :   entry->locales.SetBase(nsDependentCString(provider), resolved);
     722             : 
     723          24 :   if (mDynamicRegistration) {
     724          48 :     ChromePackage chromePackage;
     725          24 :     ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
     726          24 :                                   mSelectedSkin);
     727          24 :     SendManifestEntry(chromePackage);
     728             :   }
     729             : 
     730             :   // We use mainPackage as the package we track for reporting new locales being
     731             :   // registered. For most cases it will be "global", but for Fennec it will be
     732             :   // "browser".
     733          48 :   nsAutoCString mainPackage;
     734          24 :   nsresult rv = OverrideLocalePackage(NS_LITERAL_CSTRING("global"), mainPackage);
     735          24 :   if (NS_FAILED(rv)) {
     736           0 :     return;
     737             :   }
     738             : 
     739          24 :   if (mainPackage.Equals(package)) {
     740             :     // We should refresh the LocaleService, since the available
     741             :     // locales changed.
     742           1 :     LocaleService::GetInstance()->OnAvailableLocalesChanged();
     743             :   }
     744             : }
     745             : 
     746             : void
     747          15 : nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
     748             :                                      char *const * argv, int flags)
     749             : {
     750          15 :   char* package = argv[0];
     751          15 :   char* provider = argv[1];
     752          15 :   char* uri = argv[2];
     753             : 
     754          15 :   EnsureLowerCase(package);
     755             : 
     756          30 :   nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
     757          15 :   if (!resolved) {
     758           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     759           0 :                           "During chrome registration, unable to create URI '%s'.", uri);
     760           0 :     return;
     761             :   }
     762             : 
     763          15 :   if (!CanLoadResource(resolved)) {
     764           0 :     LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
     765             :                           "During chrome registration, cannot register non-local URI '%s' as content.",
     766           0 :                           uri);
     767           0 :     return;
     768             :   }
     769             : 
     770          30 :   nsDependentCString packageName(package);
     771          15 :   PackageEntry* entry = mPackagesHash.LookupOrAdd(packageName);
     772          15 :   entry->skins.SetBase(nsDependentCString(provider), resolved);
     773             : 
     774          15 :   if (mDynamicRegistration) {
     775          30 :     ChromePackage chromePackage;
     776          15 :     ChromePackageFromPackageEntry(packageName, entry, &chromePackage,
     777          15 :                                   mSelectedSkin);
     778          15 :     SendManifestEntry(chromePackage);
     779             :   }
     780             : }
     781             : 
     782             : void
     783           7 : nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
     784             :                                         char *const * argv, int flags)
     785             : {
     786           7 :   char* base = argv[0];
     787           7 :   char* overlay = argv[1];
     788             : 
     789          14 :   nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
     790          14 :   nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
     791           7 :   if (!baseuri || !overlayuri) {
     792           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     793           0 :                           "During chrome registration, unable to create URI.");
     794           0 :     return;
     795             :   }
     796             : 
     797           7 :   if (!CanLoadResource(overlayuri)) {
     798           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     799           0 :                           "Cannot register non-local URI '%s' as an overlay.", overlay);
     800           0 :     return;
     801             :   }
     802             : 
     803          14 :   nsCOMPtr<nsIURI> baseuriWithoutHash;
     804           7 :   baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
     805             : 
     806           7 :   mOverlayHash.Add(baseuriWithoutHash, overlayuri);
     807             : }
     808             : 
     809             : void
     810           0 : nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
     811             :                                       char *const * argv, int flags)
     812             : {
     813           0 :   char* base = argv[0];
     814           0 :   char* overlay = argv[1];
     815             : 
     816           0 :   nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
     817           0 :   nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
     818           0 :   if (!baseuri || !overlayuri) {
     819           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     820           0 :                           "During chrome registration, unable to create URI.");
     821           0 :     return;
     822             :   }
     823             : 
     824           0 :   if (!CanLoadResource(overlayuri)) {
     825           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     826           0 :                           "Cannot register non-local URI '%s' as a style overlay.", overlay);
     827           0 :     return;
     828             :   }
     829             : 
     830           0 :   nsCOMPtr<nsIURI> baseuriWithoutHash;
     831           0 :   baseuri->CloneIgnoringRef(getter_AddRefs(baseuriWithoutHash));
     832             : 
     833           0 :   mStyleHash.Add(baseuriWithoutHash, overlayuri);
     834             : }
     835             : 
     836             : void
     837          20 : nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
     838             :                                          char *const * argv, int flags)
     839             : {
     840          20 :   char* chrome = argv[0];
     841          20 :   char* resolved = argv[1];
     842             : 
     843          40 :   nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
     844          40 :   nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
     845          20 :   if (!chromeuri || !resolveduri) {
     846           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     847           0 :                           "During chrome registration, unable to create URI.");
     848           0 :     return;
     849             :   }
     850             : 
     851          20 :   if (cx.mType == NS_SKIN_LOCATION) {
     852          14 :     bool chromeSkinOnly = false;
     853          14 :     nsresult rv = chromeuri->SchemeIs("chrome", &chromeSkinOnly);
     854          14 :     chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
     855          14 :     if (chromeSkinOnly) {
     856          14 :       rv = resolveduri->SchemeIs("chrome", &chromeSkinOnly);
     857          14 :       chromeSkinOnly = chromeSkinOnly && NS_SUCCEEDED(rv);
     858             :     }
     859          14 :     if (chromeSkinOnly) {
     860          28 :       nsAutoCString chromePath, resolvedPath;
     861          14 :       chromeuri->GetPath(chromePath);
     862          14 :       resolveduri->GetPath(resolvedPath);
     863          70 :       chromeSkinOnly = StringBeginsWith(chromePath, NS_LITERAL_CSTRING("/skin/")) &&
     864          42 :                        StringBeginsWith(resolvedPath, NS_LITERAL_CSTRING("/skin/"));
     865             :     }
     866          14 :     if (!chromeSkinOnly) {
     867           0 :       LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     868             :                             "Cannot register non-chrome://.../skin/ URIs '%s' and '%s' as overrides and/or to be overridden from a skin manifest.",
     869           0 :                             chrome, resolved);
     870           0 :       return;
     871             :     }
     872             :   }
     873             : 
     874          20 :   if (!CanLoadResource(resolveduri)) {
     875           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     876           0 :                           "Cannot register non-local URI '%s' for an override.", resolved);
     877           0 :     return;
     878             :   }
     879          20 :   mOverrideTable.Put(chromeuri, resolveduri);
     880             : 
     881          20 :   if (mDynamicRegistration) {
     882          40 :     SerializedURI serializedChrome;
     883          40 :     SerializedURI serializedOverride;
     884             : 
     885          20 :     SerializeURI(chromeuri, serializedChrome);
     886          20 :     SerializeURI(resolveduri, serializedOverride);
     887             : 
     888          40 :     OverrideMapping override = { serializedChrome, serializedOverride };
     889          20 :     SendManifestEntry(override);
     890             :   }
     891             : }
     892             : 
     893             : void
     894          11 : nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
     895             :                                          char *const * argv, int flags)
     896             : {
     897          11 :   char* package = argv[0];
     898          11 :   char* uri = argv[1];
     899             : 
     900          11 :   EnsureLowerCase(package);
     901          22 :   nsDependentCString host(package);
     902             : 
     903          22 :   nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
     904          11 :   if (!io) {
     905           0 :     NS_WARNING("No IO service trying to process chrome manifests");
     906           0 :     return;
     907             :   }
     908             : 
     909          22 :   nsCOMPtr<nsIProtocolHandler> ph;
     910          11 :   nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
     911          11 :   if (NS_FAILED(rv))
     912           0 :     return;
     913             : 
     914          22 :   nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
     915             : 
     916          22 :   nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
     917          11 :   if (!resolved) {
     918           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     919           0 :                           "During chrome registration, unable to create URI '%s'.", uri);
     920           0 :     return;
     921             :   }
     922             : 
     923          11 :   if (!CanLoadResource(resolved)) {
     924           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     925             :                           "Warning: cannot register non-local URI '%s' as a resource.",
     926           0 :                           uri);
     927           0 :     return;
     928             :   }
     929             : 
     930          11 :   rv = rph->SetSubstitution(host, resolved);
     931          11 :   if (NS_FAILED(rv)) {
     932           0 :     LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
     933             :                           "Warning: cannot set substitution for '%s'.",
     934           0 :                           uri);
     935             :   }
     936             : }

Generated by: LCOV version 1.13