tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

nsChromeRegistryChrome.cpp (20314B)


      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 
     29 #include "nsIObserverService.h"
     30 #include "mozilla/AppShutdown.h"
     31 #include "mozilla/Components.h"
     32 #include "mozilla/Preferences.h"
     33 #include "nsIResProtocolHandler.h"
     34 #include "nsIScriptError.h"
     35 #include "nsIXULRuntime.h"
     36 
     37 #define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
     38 #define SKIN "classic/1.0"_ns
     39 
     40 using namespace mozilla;
     41 using mozilla::dom::ContentParent;
     42 using mozilla::dom::PContentParent;
     43 using mozilla::intl::LocaleService;
     44 
     45 // We use a "best-fit" algorithm for matching locales and themes.
     46 // 1) the exact selected locale/theme
     47 // 2) (locales only) same language, different country
     48 //    e.g. en-GB is the selected locale, only en-US is available
     49 // 3) any available locale/theme
     50 
     51 /**
     52 * Match the language-part of two lang-COUNTRY codes, hopefully but
     53 * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
     54 * work, any other garbage-in will produce undefined results as long
     55 * as it does not crash.
     56 */
     57 static bool LanguagesMatch(const nsACString& a, const nsACString& b) {
     58  if (a.Length() < 2 || b.Length() < 2) return false;
     59 
     60  nsACString::const_iterator as, ae, bs, be;
     61  a.BeginReading(as);
     62  a.EndReading(ae);
     63  b.BeginReading(bs);
     64  b.EndReading(be);
     65 
     66  while (*as == *bs) {
     67    if (*as == '-') return true;
     68 
     69    ++as;
     70    ++bs;
     71 
     72    // reached the end
     73    if (as == ae && bs == be) return true;
     74 
     75    // "a" is short
     76    if (as == ae) return (*bs == '-');
     77 
     78    // "b" is short
     79    if (bs == be) return (*as == '-');
     80  }
     81 
     82  return false;
     83 }
     84 
     85 nsChromeRegistryChrome::nsChromeRegistryChrome()
     86    : mProfileLoaded(false), mDynamicRegistration(true) {}
     87 
     88 nsChromeRegistryChrome::~nsChromeRegistryChrome() {}
     89 
     90 nsresult nsChromeRegistryChrome::Init() {
     91  nsresult rv = nsChromeRegistry::Init();
     92  if (NS_FAILED(rv)) return rv;
     93 
     94  bool safeMode = false;
     95  nsCOMPtr<nsIXULRuntime> xulrun(do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
     96  if (xulrun) xulrun->GetInSafeMode(&safeMode);
     97 
     98  nsCOMPtr<nsIObserverService> obsService =
     99      mozilla::services::GetObserverService();
    100  if (obsService) {
    101    obsService->AddObserver(this, "profile-initial-state", true);
    102    obsService->AddObserver(this, "intl:app-locales-changed", true);
    103  }
    104 
    105  return NS_OK;
    106 }
    107 
    108 NS_IMETHODIMP
    109 nsChromeRegistryChrome::GetLocalesForPackage(
    110    const nsACString& aPackage, nsIUTF8StringEnumerator** aResult) {
    111  nsCString realpackage;
    112  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
    113  if (NS_FAILED(rv)) return rv;
    114 
    115  nsTArray<nsCString>* a = new nsTArray<nsCString>;
    116  if (!a) return NS_ERROR_OUT_OF_MEMORY;
    117 
    118  PackageEntry* entry;
    119  if (mPackagesHash.Get(realpackage, &entry)) {
    120    entry->locales.EnumerateToArray(a);
    121  }
    122 
    123  rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
    124  if (NS_FAILED(rv)) delete a;
    125 
    126  return rv;
    127 }
    128 
    129 NS_IMETHODIMP
    130 nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool* aResult) {
    131  *aResult = false;
    132 
    133  nsAutoCString locale;
    134  GetSelectedLocale(package, locale);
    135  if (locale.Length() < 2) return NS_OK;
    136 
    137  *aResult = LocaleService::IsLocaleRTL(locale);
    138  return NS_OK;
    139 }
    140 
    141 /**
    142 * This method negotiates only between the app locale and the available
    143 * chrome packages.
    144 *
    145 * If you want to get the current application's UI locale, please use
    146 * LocaleService::GetAppLocaleAsBCP47.
    147 */
    148 nsresult nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
    149                                                   nsACString& aLocale) {
    150  nsAutoCString reqLocale;
    151  if (aPackage.EqualsLiteral("global")) {
    152    LocaleService::GetInstance()->GetAppLocaleAsBCP47(reqLocale);
    153  } else {
    154    AutoTArray<nsCString, 10> requestedLocales;
    155    LocaleService::GetInstance()->GetRequestedLocales(requestedLocales);
    156    reqLocale.Assign(requestedLocales[0]);
    157  }
    158 
    159  nsCString realpackage;
    160  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
    161  if (NS_FAILED(rv)) return rv;
    162  PackageEntry* entry;
    163  if (!mPackagesHash.Get(realpackage, &entry)) return NS_ERROR_FILE_NOT_FOUND;
    164 
    165  aLocale = entry->locales.GetSelected(reqLocale, nsProviderArray::LOCALE);
    166  if (aLocale.IsEmpty()) return NS_ERROR_FAILURE;
    167 
    168  return NS_OK;
    169 }
    170 
    171 nsresult nsChromeRegistryChrome::OverrideLocalePackage(
    172    const nsACString& aPackage, nsACString& aOverride) {
    173  const nsACString& pref = nsLiteralCString(PACKAGE_OVERRIDE_BRANCH) + aPackage;
    174  nsAutoCString override;
    175  nsresult rv = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get(),
    176                                                 override);
    177  if (NS_SUCCEEDED(rv)) {
    178    aOverride = override;
    179  } else {
    180    aOverride = aPackage;
    181  }
    182  return NS_OK;
    183 }
    184 
    185 NS_IMETHODIMP
    186 nsChromeRegistryChrome::Observe(nsISupports* aSubject, const char* aTopic,
    187                                const char16_t* someData) {
    188  nsresult rv = NS_OK;
    189 
    190  if (!strcmp("profile-initial-state", aTopic)) {
    191    mProfileLoaded = true;
    192  } else if (!strcmp("intl:app-locales-changed", aTopic)) {
    193    if (mProfileLoaded) {
    194      FlushAllCaches();
    195    }
    196  } else {
    197    NS_ERROR("Unexpected observer topic!");
    198  }
    199 
    200  return rv;
    201 }
    202 
    203 NS_IMETHODIMP
    204 nsChromeRegistryChrome::CheckForNewChrome() {
    205  if (AppShutdown::IsInOrBeyond(ShutdownPhase::AppShutdownConfirmed)) {
    206    MOZ_ASSERT(false, "checking for new chrome during shutdown");
    207    return NS_ERROR_UNEXPECTED;
    208  }
    209 
    210  mPackagesHash.Clear();
    211  mOverrideTable.Clear();
    212 
    213  mDynamicRegistration = false;
    214 
    215  nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
    216 
    217  mDynamicRegistration = true;
    218 
    219  SendRegisteredChrome(nullptr);
    220  return NS_OK;
    221 }
    222 
    223 static void SerializeURI(nsIURI* aURI, SerializedURI& aSerializedURI) {
    224  if (!aURI) return;
    225 
    226  aURI->GetSpec(aSerializedURI.spec);
    227 }
    228 
    229 void nsChromeRegistryChrome::SendRegisteredChrome(
    230    mozilla::dom::PContentParent* aParent) {
    231  nsTArray<ChromePackage> packages;
    232  nsTArray<SubstitutionMapping> resources;
    233  nsTArray<OverrideMapping> overrides;
    234 
    235  for (const auto& entry : mPackagesHash) {
    236    ChromePackage chromePackage;
    237    ChromePackageFromPackageEntry(entry.GetKey(), entry.GetWeak(),
    238                                  &chromePackage, SKIN);
    239    packages.AppendElement(chromePackage);
    240  }
    241 
    242  // If we were passed a parent then a new child process has been created and
    243  // has requested all of the chrome so send it the resources too. Otherwise
    244  // resource mappings are sent by the resource protocol handler dynamically.
    245  if (aParent) {
    246    nsCOMPtr<nsIIOService> io(do_GetIOService());
    247    NS_ENSURE_TRUE_VOID(io);
    248 
    249    nsCOMPtr<nsIProtocolHandler> ph;
    250    nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
    251    NS_ENSURE_SUCCESS_VOID(rv);
    252 
    253    nsCOMPtr<nsIResProtocolHandler> irph(do_QueryInterface(ph));
    254    nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
    255    rv = rph->CollectSubstitutions(resources);
    256    NS_ENSURE_SUCCESS_VOID(rv);
    257  }
    258 
    259  for (const auto& entry : mOverrideTable) {
    260    SerializedURI chromeURI, overrideURI;
    261 
    262    SerializeURI(entry.GetKey(), chromeURI);
    263    SerializeURI(entry.GetWeak(), overrideURI);
    264 
    265    overrides.AppendElement(
    266        OverrideMapping{std::move(chromeURI), std::move(overrideURI)});
    267  }
    268 
    269  nsAutoCString appLocale;
    270  LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
    271 
    272  if (aParent) {
    273    bool success = aParent->SendRegisterChrome(packages, resources, overrides,
    274                                               appLocale, false);
    275    NS_ENSURE_TRUE_VOID(success);
    276  } else {
    277    nsTArray<ContentParent*> parents;
    278    ContentParent::GetAll(parents);
    279    if (!parents.Length()) return;
    280 
    281    for (uint32_t i = 0; i < parents.Length(); i++) {
    282      DebugOnly<bool> success = parents[i]->SendRegisterChrome(
    283          packages, resources, overrides, appLocale, true);
    284      NS_WARNING_ASSERTION(success,
    285                           "couldn't reset a child's registered chrome");
    286    }
    287  }
    288 }
    289 
    290 /* static */
    291 void nsChromeRegistryChrome::ChromePackageFromPackageEntry(
    292    const nsACString& aPackageName, PackageEntry* aPackage,
    293    ChromePackage* aChromePackage, const nsCString& aSelectedSkin) {
    294  nsAutoCString appLocale;
    295  LocaleService::GetInstance()->GetAppLocaleAsBCP47(appLocale);
    296 
    297  SerializeURI(aPackage->baseURI, aChromePackage->contentBaseURI);
    298  SerializeURI(aPackage->locales.GetBase(appLocale, nsProviderArray::LOCALE),
    299               aChromePackage->localeBaseURI);
    300  SerializeURI(aPackage->skins.GetBase(aSelectedSkin, nsProviderArray::ANY),
    301               aChromePackage->skinBaseURI);
    302  aChromePackage->package = aPackageName;
    303  aChromePackage->flags = aPackage->flags;
    304 }
    305 
    306 static bool CanLoadResource(nsIURI* aResourceURI) {
    307  bool isLocalResource = false;
    308  (void)NS_URIChainHasFlags(aResourceURI,
    309                            nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
    310                            &isLocalResource);
    311  return isLocalResource;
    312 }
    313 
    314 nsIURI* nsChromeRegistryChrome::GetBaseURIFromPackage(
    315    const nsCString& aPackage, const nsCString& aProvider,
    316    const nsCString& aPath) {
    317  PackageEntry* entry;
    318  if (!mPackagesHash.Get(aPackage, &entry)) {
    319    if (!mInitialized) return nullptr;
    320 
    321    LogMessage("No chrome package registered for chrome://%s/%s/%s",
    322               aPackage.get(), aProvider.get(), aPath.get());
    323 
    324    return nullptr;
    325  }
    326 
    327  if (aProvider.EqualsLiteral("locale")) {
    328    nsAutoCString appLocale;
    329    LocaleService::GetInstance()->GetAppLocaleAsLangTag(appLocale);
    330    return entry->locales.GetBase(appLocale, nsProviderArray::LOCALE);
    331  }
    332 
    333  if (aProvider.EqualsLiteral("skin")) {
    334    return entry->skins.GetBase(SKIN, nsProviderArray::ANY);
    335  }
    336 
    337  if (aProvider.EqualsLiteral("content")) {
    338    return entry->baseURI;
    339  }
    340  return nullptr;
    341 }
    342 
    343 nsresult nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
    344                                                     uint32_t* aFlags) {
    345  PackageEntry* entry;
    346  if (!mPackagesHash.Get(aPackage, &entry)) return NS_ERROR_FILE_NOT_FOUND;
    347 
    348  *aFlags = entry->flags;
    349  return NS_OK;
    350 }
    351 
    352 nsChromeRegistryChrome::ProviderEntry*
    353 nsChromeRegistryChrome::nsProviderArray::GetProvider(
    354    const nsACString& aPreferred, MatchType aType) {
    355  size_t i = mArray.Length();
    356  if (!i) return nullptr;
    357 
    358  ProviderEntry* found = nullptr;  // Only set if we find a partial-match locale
    359  ProviderEntry* entry = nullptr;
    360 
    361  while (i--) {
    362    entry = &mArray[i];
    363    if (aPreferred.Equals(entry->provider)) return entry;
    364 
    365    if (aType != LOCALE) continue;
    366 
    367    if (LanguagesMatch(aPreferred, entry->provider)) {
    368      found = entry;
    369      continue;
    370    }
    371 
    372    if (!found && entry->provider.EqualsLiteral("en-US")) found = entry;
    373  }
    374 
    375  if (!found && aType != EXACT) return entry;
    376 
    377  return found;
    378 }
    379 
    380 nsIURI* nsChromeRegistryChrome::nsProviderArray::GetBase(
    381    const nsACString& aPreferred, MatchType aType) {
    382  ProviderEntry* provider = GetProvider(aPreferred, aType);
    383 
    384  if (!provider) return nullptr;
    385 
    386  return provider->baseURI;
    387 }
    388 
    389 const nsACString& nsChromeRegistryChrome::nsProviderArray::GetSelected(
    390    const nsACString& aPreferred, MatchType aType) {
    391  ProviderEntry* entry = GetProvider(aPreferred, aType);
    392 
    393  if (entry) return entry->provider;
    394 
    395  return EmptyCString();
    396 }
    397 
    398 void nsChromeRegistryChrome::nsProviderArray::SetBase(
    399    const nsACString& aProvider, nsIURI* aBaseURL) {
    400  ProviderEntry* provider = GetProvider(aProvider, EXACT);
    401 
    402  if (provider) {
    403    provider->baseURI = aBaseURL;
    404    return;
    405  }
    406 
    407  // no existing entries, add a new one
    408  mArray.AppendElement(ProviderEntry(aProvider, aBaseURL));
    409 }
    410 
    411 void nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(
    412    nsTArray<nsCString>* a) {
    413  int32_t i = mArray.Length();
    414  while (i--) {
    415    a->AppendElement(mArray[i].provider);
    416  }
    417 }
    418 
    419 nsIURI* nsChromeRegistry::ManifestProcessingContext::GetManifestURI() {
    420  if (!mManifestURI) {
    421    nsCString uri;
    422    mFile.GetURIString(uri);
    423    NS_NewURI(getter_AddRefs(mManifestURI), uri);
    424  }
    425  return mManifestURI;
    426 }
    427 
    428 already_AddRefed<nsIURI>
    429 nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri) {
    430  nsIURI* baseuri = GetManifestURI();
    431  if (!baseuri) return nullptr;
    432 
    433  nsCOMPtr<nsIURI> resolved;
    434  nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
    435  if (NS_FAILED(rv)) return nullptr;
    436 
    437  return resolved.forget();
    438 }
    439 
    440 static void EnsureLowerCase(char* aBuf) {
    441  for (; *aBuf; ++aBuf) {
    442    char ch = *aBuf;
    443    if (ch >= 'A' && ch <= 'Z') *aBuf = ch + 'a' - 'A';
    444  }
    445 }
    446 
    447 static void SendManifestEntry(const ChromeRegistryItem& aItem) {
    448  nsTArray<ContentParent*> parents;
    449  ContentParent::GetAll(parents);
    450  if (!parents.Length()) return;
    451 
    452  for (uint32_t i = 0; i < parents.Length(); i++) {
    453    (void)parents[i]->SendRegisterChromeItem(aItem);
    454  }
    455 }
    456 
    457 void nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx,
    458                                             int lineno, char* const* argv,
    459                                             int flags) {
    460  char* package = argv[0];
    461  char* uri = argv[1];
    462 
    463  EnsureLowerCase(package);
    464 
    465  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
    466  if (!resolved) {
    467    LogMessageWithContext(
    468        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    469        "During chrome registration, unable to create URI '%s'.", uri);
    470    return;
    471  }
    472 
    473  if (!CanLoadResource(resolved)) {
    474    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
    475                          "During chrome registration, cannot register "
    476                          "non-local URI '%s' as content.",
    477                          uri);
    478    return;
    479  }
    480 
    481  nsDependentCString packageName(package);
    482  PackageEntry* entry = mPackagesHash.GetOrInsertNew(packageName);
    483  entry->baseURI = resolved;
    484  entry->flags = flags;
    485 
    486  if (mDynamicRegistration) {
    487    ChromePackage chromePackage;
    488    ChromePackageFromPackageEntry(packageName, entry, &chromePackage, SKIN);
    489    SendManifestEntry(chromePackage);
    490  }
    491 }
    492 
    493 void nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx,
    494                                            int lineno, char* const* argv,
    495                                            int flags) {
    496  char* package = argv[0];
    497  char* provider = argv[1];
    498  char* uri = argv[2];
    499 
    500  EnsureLowerCase(package);
    501 
    502  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
    503  if (!resolved) {
    504    LogMessageWithContext(
    505        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    506        "During chrome registration, unable to create URI '%s'.", uri);
    507    return;
    508  }
    509 
    510  if (!CanLoadResource(resolved)) {
    511    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
    512                          "During chrome registration, cannot register "
    513                          "non-local URI '%s' as content.",
    514                          uri);
    515    return;
    516  }
    517 
    518  nsDependentCString packageName(package);
    519  PackageEntry* entry = mPackagesHash.GetOrInsertNew(packageName);
    520  entry->locales.SetBase(nsDependentCString(provider), resolved);
    521 
    522  if (mDynamicRegistration) {
    523    ChromePackage chromePackage;
    524    ChromePackageFromPackageEntry(packageName, entry, &chromePackage, SKIN);
    525    SendManifestEntry(chromePackage);
    526  }
    527 
    528  // We use mainPackage as the package we track for reporting new locales being
    529  // registered. For most cases it will be "global", but for Fennec it will be
    530  // "browser".
    531  nsAutoCString mainPackage;
    532  nsresult rv = OverrideLocalePackage("global"_ns, mainPackage);
    533  if (NS_FAILED(rv)) {
    534    return;
    535  }
    536 }
    537 
    538 void nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx,
    539                                          int lineno, char* const* argv,
    540                                          int flags) {
    541  char* package = argv[0];
    542  char* provider = argv[1];
    543  char* uri = argv[2];
    544 
    545  EnsureLowerCase(package);
    546 
    547  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
    548  if (!resolved) {
    549    LogMessageWithContext(
    550        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    551        "During chrome registration, unable to create URI '%s'.", uri);
    552    return;
    553  }
    554 
    555  if (!CanLoadResource(resolved)) {
    556    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
    557                          "During chrome registration, cannot register "
    558                          "non-local URI '%s' as content.",
    559                          uri);
    560    return;
    561  }
    562 
    563  nsDependentCString packageName(package);
    564  PackageEntry* entry = mPackagesHash.GetOrInsertNew(packageName);
    565  entry->skins.SetBase(nsDependentCString(provider), resolved);
    566 
    567  if (mDynamicRegistration) {
    568    ChromePackage chromePackage;
    569    ChromePackageFromPackageEntry(packageName, entry, &chromePackage, SKIN);
    570    SendManifestEntry(chromePackage);
    571  }
    572 }
    573 
    574 void nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx,
    575                                              int lineno, char* const* argv,
    576                                              int flags) {
    577  char* chrome = argv[0];
    578  char* resolved = argv[1];
    579 
    580  nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
    581  nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
    582  if (!chromeuri || !resolveduri) {
    583    LogMessageWithContext(cx.GetManifestURI(), lineno,
    584                          nsIScriptError::warningFlag,
    585                          "During chrome registration, unable to create URI.");
    586    return;
    587  }
    588 
    589  if (!CanLoadResource(resolveduri)) {
    590    LogMessageWithContext(
    591        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    592        "Cannot register non-local URI '%s' for an override.", resolved);
    593    return;
    594  }
    595  mOverrideTable.InsertOrUpdate(chromeuri, resolveduri);
    596 
    597  if (mDynamicRegistration) {
    598    SerializedURI serializedChrome;
    599    SerializedURI serializedOverride;
    600 
    601    SerializeURI(chromeuri, serializedChrome);
    602    SerializeURI(resolveduri, serializedOverride);
    603 
    604    OverrideMapping override = {serializedChrome, serializedOverride};
    605    SendManifestEntry(override);
    606  }
    607 }
    608 
    609 void nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx,
    610                                              int lineno, char* const* argv,
    611                                              int flags) {
    612  char* package = argv[0];
    613  char* uri = argv[1];
    614 
    615  EnsureLowerCase(package);
    616  nsDependentCString host(package);
    617 
    618  nsCOMPtr<nsIIOService> io = mozilla::components::IO::Service();
    619  if (!io) {
    620    NS_WARNING("No IO service trying to process chrome manifests");
    621    return;
    622  }
    623 
    624  nsCOMPtr<nsIProtocolHandler> ph;
    625  nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
    626  if (NS_FAILED(rv)) return;
    627 
    628  nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
    629 
    630  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
    631  if (!resolved) {
    632    LogMessageWithContext(
    633        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    634        "During chrome registration, unable to create URI '%s'.", uri);
    635    return;
    636  }
    637 
    638  if (!CanLoadResource(resolved)) {
    639    LogMessageWithContext(
    640        cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
    641        "Warning: cannot register non-local URI '%s' as a resource.", uri);
    642    return;
    643  }
    644 
    645  // By default, Firefox resources are not content-accessible unless the
    646  // manifests opts in.
    647  bool contentAccessible = (flags & nsChromeRegistry::CONTENT_ACCESSIBLE);
    648 
    649  uint32_t substitutionFlags = 0;
    650  if (contentAccessible) {
    651    substitutionFlags |= nsIResProtocolHandler::ALLOW_CONTENT_ACCESS;
    652  }
    653  rv = rph->SetSubstitutionWithFlags(host, resolved, substitutionFlags);
    654  if (NS_FAILED(rv)) {
    655    LogMessageWithContext(cx.GetManifestURI(), lineno,
    656                          nsIScriptError::warningFlag,
    657                          "Warning: cannot set substitution for '%s'.", uri);
    658  }
    659 }