chrome/src/nsChromeRegistryChrome.cpp

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/chrome/src/nsChromeRegistryChrome.cpp	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,1039 @@
     1.4 +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
     1.5 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.6 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.7 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.8 +
     1.9 +#include "mozilla/dom/PContentParent.h"
    1.10 +#include "RegistryMessageUtils.h"
    1.11 +#include "nsResProtocolHandler.h"
    1.12 +
    1.13 +#include "nsChromeRegistryChrome.h"
    1.14 +
    1.15 +#if defined(XP_WIN)
    1.16 +#include <windows.h>
    1.17 +#elif defined(XP_MACOSX)
    1.18 +#include <CoreServices/CoreServices.h>
    1.19 +#endif
    1.20 +
    1.21 +#include "nsArrayEnumerator.h"
    1.22 +#include "nsComponentManager.h"
    1.23 +#include "nsEnumeratorUtils.h"
    1.24 +#include "nsNetUtil.h"
    1.25 +#include "nsStringEnumerator.h"
    1.26 +#include "nsTextFormatter.h"
    1.27 +#include "nsXPCOMCIDInternal.h"
    1.28 +
    1.29 +#include "mozilla/LookAndFeel.h"
    1.30 +
    1.31 +#include "nsICommandLine.h"
    1.32 +#include "nsILocaleService.h"
    1.33 +#include "nsIObserverService.h"
    1.34 +#include "nsIPrefBranch.h"
    1.35 +#include "nsIPrefService.h"
    1.36 +#include "mozilla/Preferences.h"
    1.37 +#include "nsIResProtocolHandler.h"
    1.38 +#include "nsIScriptError.h"
    1.39 +#include "nsIXPConnect.h"
    1.40 +#include "nsIXULRuntime.h"
    1.41 +
    1.42 +#define UILOCALE_CMD_LINE_ARG "UILocale"
    1.43 +
    1.44 +#define MATCH_OS_LOCALE_PREF "intl.locale.matchOS"
    1.45 +#define SELECTED_LOCALE_PREF "general.useragent.locale"
    1.46 +#define SELECTED_SKIN_PREF   "general.skins.selectedSkin"
    1.47 +#define PACKAGE_OVERRIDE_BRANCH "chrome.override_package."
    1.48 +
    1.49 +using namespace mozilla;
    1.50 +
    1.51 +static PLDHashOperator
    1.52 +RemoveAll(PLDHashTable *table, PLDHashEntryHdr *entry, uint32_t number, void *arg)
    1.53 +{
    1.54 +  return (PLDHashOperator) (PL_DHASH_NEXT | PL_DHASH_REMOVE);
    1.55 +}
    1.56 +
    1.57 +// We use a "best-fit" algorithm for matching locales and themes. 
    1.58 +// 1) the exact selected locale/theme
    1.59 +// 2) (locales only) same language, different country
    1.60 +//    e.g. en-GB is the selected locale, only en-US is available
    1.61 +// 3) any available locale/theme
    1.62 +
    1.63 +/**
    1.64 + * Match the language-part of two lang-COUNTRY codes, hopefully but
    1.65 + * not guaranteed to be in the form ab-CD or abz-CD. "ab" should also
    1.66 + * work, any other garbage-in will produce undefined results as long
    1.67 + * as it does not crash.
    1.68 + */
    1.69 +static bool
    1.70 +LanguagesMatch(const nsACString& a, const nsACString& b)
    1.71 +{
    1.72 +  if (a.Length() < 2 || b.Length() < 2)
    1.73 +    return false;
    1.74 +
    1.75 +  nsACString::const_iterator as, ae, bs, be;
    1.76 +  a.BeginReading(as);
    1.77 +  a.EndReading(ae);
    1.78 +  b.BeginReading(bs);
    1.79 +  b.EndReading(be);
    1.80 +
    1.81 +  while (*as == *bs) {
    1.82 +    if (*as == '-')
    1.83 +      return true;
    1.84 + 
    1.85 +    ++as; ++bs;
    1.86 +
    1.87 +    // reached the end
    1.88 +    if (as == ae && bs == be)
    1.89 +      return true;
    1.90 +
    1.91 +    // "a" is short
    1.92 +    if (as == ae)
    1.93 +      return (*bs == '-');
    1.94 +
    1.95 +    // "b" is short
    1.96 +    if (bs == be)
    1.97 +      return (*as == '-');
    1.98 +  }
    1.99 +
   1.100 +  return false;
   1.101 +}
   1.102 +
   1.103 +nsChromeRegistryChrome::nsChromeRegistryChrome()
   1.104 +  : mProfileLoaded(false)
   1.105 +{
   1.106 +  mPackagesHash.ops = nullptr;
   1.107 +}
   1.108 +
   1.109 +nsChromeRegistryChrome::~nsChromeRegistryChrome()
   1.110 +{
   1.111 +  if (mPackagesHash.ops)
   1.112 +    PL_DHashTableFinish(&mPackagesHash);
   1.113 +}
   1.114 +
   1.115 +nsresult
   1.116 +nsChromeRegistryChrome::Init()
   1.117 +{
   1.118 +  nsresult rv = nsChromeRegistry::Init();
   1.119 +  if (NS_FAILED(rv))
   1.120 +    return rv;
   1.121 +
   1.122 +  mSelectedLocale = NS_LITERAL_CSTRING("en-US");
   1.123 +  mSelectedSkin = NS_LITERAL_CSTRING("classic/1.0");
   1.124 +
   1.125 +  PL_DHashTableInit(&mPackagesHash, &kTableOps,
   1.126 +                    nullptr, sizeof(PackageEntry), 16);
   1.127 +
   1.128 +  bool safeMode = false;
   1.129 +  nsCOMPtr<nsIXULRuntime> xulrun (do_GetService(XULAPPINFO_SERVICE_CONTRACTID));
   1.130 +  if (xulrun)
   1.131 +    xulrun->GetInSafeMode(&safeMode);
   1.132 +
   1.133 +  nsCOMPtr<nsIPrefService> prefserv (do_GetService(NS_PREFSERVICE_CONTRACTID));
   1.134 +  nsCOMPtr<nsIPrefBranch> prefs;
   1.135 +
   1.136 +  if (safeMode)
   1.137 +    prefserv->GetDefaultBranch(nullptr, getter_AddRefs(prefs));
   1.138 +  else
   1.139 +    prefs = do_QueryInterface(prefserv);
   1.140 +
   1.141 +  if (!prefs) {
   1.142 +    NS_WARNING("Could not get pref service!");
   1.143 +  }
   1.144 +  else {
   1.145 +    nsXPIDLCString provider;
   1.146 +    rv = prefs->GetCharPref(SELECTED_SKIN_PREF, getter_Copies(provider));
   1.147 +    if (NS_SUCCEEDED(rv))
   1.148 +      mSelectedSkin = provider;
   1.149 +
   1.150 +    SelectLocaleFromPref(prefs);
   1.151 +
   1.152 +    rv = prefs->AddObserver(MATCH_OS_LOCALE_PREF, this, true);
   1.153 +    rv = prefs->AddObserver(SELECTED_LOCALE_PREF, this, true);
   1.154 +    rv = prefs->AddObserver(SELECTED_SKIN_PREF, this, true);
   1.155 +  }
   1.156 +
   1.157 +  nsCOMPtr<nsIObserverService> obsService = mozilla::services::GetObserverService();
   1.158 +  if (obsService) {
   1.159 +    obsService->AddObserver(this, "command-line-startup", true);
   1.160 +    obsService->AddObserver(this, "profile-initial-state", true);
   1.161 +  }
   1.162 +
   1.163 +  return NS_OK;
   1.164 +}
   1.165 +
   1.166 +NS_IMETHODIMP
   1.167 +nsChromeRegistryChrome::CheckForOSAccessibility()
   1.168 +{
   1.169 +  int32_t useAccessibilityTheme =
   1.170 +    LookAndFeel::GetInt(LookAndFeel::eIntID_UseAccessibilityTheme, 0);
   1.171 +
   1.172 +  if (useAccessibilityTheme) {
   1.173 +    /* Set the skin to classic and remove pref observers */
   1.174 +    if (!mSelectedSkin.EqualsLiteral("classic/1.0")) {
   1.175 +      mSelectedSkin.AssignLiteral("classic/1.0");
   1.176 +      RefreshSkins();
   1.177 +    }
   1.178 +
   1.179 +    nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
   1.180 +    if (prefs) {
   1.181 +      prefs->RemoveObserver(SELECTED_SKIN_PREF, this);
   1.182 +    }
   1.183 +  }
   1.184 +
   1.185 +  return NS_OK;
   1.186 +}
   1.187 +
   1.188 +NS_IMETHODIMP
   1.189 +nsChromeRegistryChrome::GetLocalesForPackage(const nsACString& aPackage,
   1.190 +                                       nsIUTF8StringEnumerator* *aResult)
   1.191 +{
   1.192 +  nsCString realpackage;
   1.193 +  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
   1.194 +  if (NS_FAILED(rv))
   1.195 +    return rv;
   1.196 +
   1.197 +  nsTArray<nsCString> *a = new nsTArray<nsCString>;
   1.198 +  if (!a)
   1.199 +    return NS_ERROR_OUT_OF_MEMORY;
   1.200 +
   1.201 +  PackageEntry* entry =
   1.202 +      static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.203 +                                                      & realpackage,
   1.204 +                                                      PL_DHASH_LOOKUP));
   1.205 +
   1.206 +  if (PL_DHASH_ENTRY_IS_BUSY(entry)) {
   1.207 +    entry->locales.EnumerateToArray(a);
   1.208 +  }
   1.209 +
   1.210 +  rv = NS_NewAdoptingUTF8StringEnumerator(aResult, a);
   1.211 +  if (NS_FAILED(rv))
   1.212 +    delete a;
   1.213 +
   1.214 +  return rv;
   1.215 +}
   1.216 +
   1.217 +static nsresult
   1.218 +getUILangCountry(nsACString& aUILang)
   1.219 +{
   1.220 +  nsresult rv;
   1.221 +
   1.222 +  nsCOMPtr<nsILocaleService> localeService = do_GetService(NS_LOCALESERVICE_CONTRACTID, &rv);
   1.223 +  NS_ENSURE_SUCCESS(rv, rv);
   1.224 +
   1.225 +  nsAutoString uiLang;
   1.226 +  rv = localeService->GetLocaleComponentForUserAgent(uiLang);
   1.227 +  NS_ENSURE_SUCCESS(rv, rv);
   1.228 +
   1.229 +  CopyUTF16toUTF8(uiLang, aUILang);
   1.230 +  return NS_OK;
   1.231 +}
   1.232 +
   1.233 +NS_IMETHODIMP
   1.234 +nsChromeRegistryChrome::IsLocaleRTL(const nsACString& package, bool *aResult)
   1.235 +{
   1.236 +  *aResult = false;
   1.237 +
   1.238 +  nsAutoCString locale;
   1.239 +  GetSelectedLocale(package, locale);
   1.240 +  if (locale.Length() < 2)
   1.241 +    return NS_OK;
   1.242 +
   1.243 +  // first check the intl.uidirection.<locale> preference, and if that is not
   1.244 +  // set, check the same preference but with just the first two characters of
   1.245 +  // the locale. If that isn't set, default to left-to-right.
   1.246 +  nsAutoCString prefString = NS_LITERAL_CSTRING("intl.uidirection.") + locale;
   1.247 +  nsCOMPtr<nsIPrefBranch> prefBranch (do_GetService(NS_PREFSERVICE_CONTRACTID));
   1.248 +  if (!prefBranch)
   1.249 +    return NS_OK;
   1.250 +  
   1.251 +  nsXPIDLCString dir;
   1.252 +  prefBranch->GetCharPref(prefString.get(), getter_Copies(dir));
   1.253 +  if (dir.IsEmpty()) {
   1.254 +    int32_t hyphen = prefString.FindChar('-');
   1.255 +    if (hyphen >= 1) {
   1.256 +      nsAutoCString shortPref(Substring(prefString, 0, hyphen));
   1.257 +      prefBranch->GetCharPref(shortPref.get(), getter_Copies(dir));
   1.258 +    }
   1.259 +  }
   1.260 +  *aResult = dir.EqualsLiteral("rtl");
   1.261 +  return NS_OK;
   1.262 +}
   1.263 +
   1.264 +nsresult
   1.265 +nsChromeRegistryChrome::GetSelectedLocale(const nsACString& aPackage,
   1.266 +                                          nsACString& aLocale)
   1.267 +{
   1.268 +  nsCString realpackage;
   1.269 +  nsresult rv = OverrideLocalePackage(aPackage, realpackage);
   1.270 +  if (NS_FAILED(rv))
   1.271 +    return rv;
   1.272 +  PackageEntry* entry =
   1.273 +      static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.274 +                                                      & realpackage,
   1.275 +                                                      PL_DHASH_LOOKUP));
   1.276 +
   1.277 +  if (PL_DHASH_ENTRY_IS_FREE(entry))
   1.278 +    return NS_ERROR_FAILURE;
   1.279 +
   1.280 +  aLocale = entry->locales.GetSelected(mSelectedLocale, nsProviderArray::LOCALE);
   1.281 +  if (aLocale.IsEmpty())
   1.282 +    return NS_ERROR_FAILURE;
   1.283 +
   1.284 +  return NS_OK;
   1.285 +}
   1.286 +
   1.287 +nsresult
   1.288 +nsChromeRegistryChrome::OverrideLocalePackage(const nsACString& aPackage,
   1.289 +                                              nsACString& aOverride)
   1.290 +{
   1.291 +  const nsACString& pref = NS_LITERAL_CSTRING(PACKAGE_OVERRIDE_BRANCH) + aPackage;
   1.292 +  nsAdoptingCString override = mozilla::Preferences::GetCString(PromiseFlatCString(pref).get());
   1.293 +  if (override) {
   1.294 +    aOverride = override;
   1.295 +  }
   1.296 +  else {
   1.297 +    aOverride = aPackage;
   1.298 +  }
   1.299 +  return NS_OK;
   1.300 +}
   1.301 +
   1.302 +nsresult
   1.303 +nsChromeRegistryChrome::SelectLocaleFromPref(nsIPrefBranch* prefs)
   1.304 +{
   1.305 +  nsresult rv;
   1.306 +  bool matchOSLocale = false;
   1.307 +  rv = prefs->GetBoolPref(MATCH_OS_LOCALE_PREF, &matchOSLocale);
   1.308 +
   1.309 +  if (NS_SUCCEEDED(rv) && matchOSLocale) {
   1.310 +    // compute lang and region code only when needed!
   1.311 +    nsAutoCString uiLocale;
   1.312 +    rv = getUILangCountry(uiLocale);
   1.313 +    if (NS_SUCCEEDED(rv))
   1.314 +      mSelectedLocale = uiLocale;
   1.315 +  }
   1.316 +  else {
   1.317 +    nsXPIDLCString provider;
   1.318 +    rv = prefs->GetCharPref(SELECTED_LOCALE_PREF, getter_Copies(provider));
   1.319 +    if (NS_SUCCEEDED(rv)) {
   1.320 +      mSelectedLocale = provider;
   1.321 +    }
   1.322 +  }
   1.323 +
   1.324 +  if (NS_FAILED(rv))
   1.325 +    NS_ERROR("Couldn't select locale from pref!");
   1.326 +
   1.327 +  return rv;
   1.328 +}
   1.329 +
   1.330 +NS_IMETHODIMP
   1.331 +nsChromeRegistryChrome::Observe(nsISupports *aSubject, const char *aTopic,
   1.332 +                                const char16_t *someData)
   1.333 +{
   1.334 +  nsresult rv = NS_OK;
   1.335 +
   1.336 +  if (!strcmp(NS_PREFBRANCH_PREFCHANGE_TOPIC_ID, aTopic)) {
   1.337 +    nsCOMPtr<nsIPrefBranch> prefs (do_QueryInterface(aSubject));
   1.338 +    NS_ASSERTION(prefs, "Bad observer call!");
   1.339 +
   1.340 +    NS_ConvertUTF16toUTF8 pref(someData);
   1.341 +
   1.342 +    if (pref.EqualsLiteral(MATCH_OS_LOCALE_PREF) ||
   1.343 +        pref.EqualsLiteral(SELECTED_LOCALE_PREF)) {
   1.344 +        rv = UpdateSelectedLocale();
   1.345 +        if (NS_SUCCEEDED(rv) && mProfileLoaded)
   1.346 +          FlushAllCaches();
   1.347 +    }
   1.348 +    else if (pref.EqualsLiteral(SELECTED_SKIN_PREF)) {
   1.349 +      nsXPIDLCString provider;
   1.350 +      rv = prefs->GetCharPref(pref.get(), getter_Copies(provider));
   1.351 +      if (NS_FAILED(rv)) {
   1.352 +        NS_ERROR("Couldn't get new skin pref!");
   1.353 +        return rv;
   1.354 +      }
   1.355 +
   1.356 +      mSelectedSkin = provider;
   1.357 +      RefreshSkins();
   1.358 +    } else {
   1.359 +      NS_ERROR("Unexpected pref!");
   1.360 +    }
   1.361 +  }
   1.362 +  else if (!strcmp("command-line-startup", aTopic)) {
   1.363 +    nsCOMPtr<nsICommandLine> cmdLine (do_QueryInterface(aSubject));
   1.364 +    if (cmdLine) {
   1.365 +      nsAutoString uiLocale;
   1.366 +      rv = cmdLine->HandleFlagWithParam(NS_LITERAL_STRING(UILOCALE_CMD_LINE_ARG),
   1.367 +                                        false, uiLocale);
   1.368 +      if (NS_SUCCEEDED(rv) && !uiLocale.IsEmpty()) {
   1.369 +        CopyUTF16toUTF8(uiLocale, mSelectedLocale);
   1.370 +        nsCOMPtr<nsIPrefBranch> prefs (do_GetService(NS_PREFSERVICE_CONTRACTID));
   1.371 +        if (prefs) {
   1.372 +          prefs->RemoveObserver(SELECTED_LOCALE_PREF, this);
   1.373 +        }
   1.374 +      }
   1.375 +    }
   1.376 +  }
   1.377 +  else if (!strcmp("profile-initial-state", aTopic)) {
   1.378 +    mProfileLoaded = true;
   1.379 +  }
   1.380 +  else {
   1.381 +    NS_ERROR("Unexpected observer topic!");
   1.382 +  }
   1.383 +
   1.384 +  return rv;
   1.385 +}
   1.386 +
   1.387 +NS_IMETHODIMP
   1.388 +nsChromeRegistryChrome::CheckForNewChrome()
   1.389 +{
   1.390 +  PL_DHashTableEnumerate(&mPackagesHash, RemoveAll, nullptr);
   1.391 +  mOverlayHash.Clear();
   1.392 +  mStyleHash.Clear();
   1.393 +  mOverrideTable.Clear();
   1.394 +
   1.395 +  nsComponentManagerImpl::gComponentManager->RereadChromeManifests();
   1.396 +  return NS_OK;
   1.397 +}
   1.398 +
   1.399 +nsresult nsChromeRegistryChrome::UpdateSelectedLocale()
   1.400 +{
   1.401 +  nsresult rv = NS_OK;
   1.402 +  nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
   1.403 +  if (prefs) {
   1.404 +    rv = SelectLocaleFromPref(prefs);
   1.405 +    if (NS_SUCCEEDED(rv)) {
   1.406 +      nsCOMPtr<nsIObserverService> obsSvc =
   1.407 +        mozilla::services::GetObserverService();
   1.408 +      NS_ASSERTION(obsSvc, "Couldn't get observer service.");
   1.409 +      obsSvc->NotifyObservers((nsIChromeRegistry*) this,
   1.410 +                              "selected-locale-has-changed", nullptr);
   1.411 +    }
   1.412 +  }
   1.413 +
   1.414 +  return rv;
   1.415 +}
   1.416 +
   1.417 +static void
   1.418 +SerializeURI(nsIURI* aURI,
   1.419 +             SerializedURI& aSerializedURI)
   1.420 +{
   1.421 +  if (!aURI)
   1.422 +    return;
   1.423 +
   1.424 +  aURI->GetSpec(aSerializedURI.spec);
   1.425 +  aURI->GetOriginCharset(aSerializedURI.charset);
   1.426 +}
   1.427 +
   1.428 +static PLDHashOperator
   1.429 +EnumerateOverride(nsIURI* aURIKey,
   1.430 +                  nsIURI* aURI,
   1.431 +                  void* aArg)
   1.432 +{
   1.433 +  nsTArray<OverrideMapping>* overrides =
   1.434 +      static_cast<nsTArray<OverrideMapping>*>(aArg);
   1.435 +
   1.436 +  SerializedURI chromeURI, overrideURI;
   1.437 +
   1.438 +  SerializeURI(aURIKey, chromeURI);
   1.439 +  SerializeURI(aURI, overrideURI);
   1.440 +        
   1.441 +  OverrideMapping override = {
   1.442 +    chromeURI, overrideURI
   1.443 +  };
   1.444 +  overrides->AppendElement(override);
   1.445 +  return (PLDHashOperator)PL_DHASH_NEXT;
   1.446 +}
   1.447 +
   1.448 +struct EnumerationArgs
   1.449 +{
   1.450 +  InfallibleTArray<ChromePackage>& packages;
   1.451 +  const nsCString& selectedLocale;
   1.452 +  const nsCString& selectedSkin;
   1.453 +};
   1.454 +
   1.455 +void
   1.456 +nsChromeRegistryChrome::SendRegisteredChrome(
   1.457 +    mozilla::dom::PContentParent* aParent)
   1.458 +{
   1.459 +  InfallibleTArray<ChromePackage> packages;
   1.460 +  InfallibleTArray<ResourceMapping> resources;
   1.461 +  InfallibleTArray<OverrideMapping> overrides;
   1.462 +
   1.463 +  EnumerationArgs args = {
   1.464 +    packages, mSelectedLocale, mSelectedSkin
   1.465 +  };
   1.466 +  PL_DHashTableEnumerate(&mPackagesHash, CollectPackages, &args);
   1.467 +
   1.468 +  nsCOMPtr<nsIIOService> io (do_GetIOService());
   1.469 +  NS_ENSURE_TRUE_VOID(io);
   1.470 +
   1.471 +  nsCOMPtr<nsIProtocolHandler> ph;
   1.472 +  nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
   1.473 +  NS_ENSURE_SUCCESS_VOID(rv);
   1.474 +
   1.475 +  //FIXME: Some substitutions are set up lazily and might not exist yet
   1.476 +  nsCOMPtr<nsIResProtocolHandler> irph (do_QueryInterface(ph));
   1.477 +  nsResProtocolHandler* rph = static_cast<nsResProtocolHandler*>(irph.get());
   1.478 +  rph->CollectSubstitutions(resources);
   1.479 +
   1.480 +  mOverrideTable.EnumerateRead(&EnumerateOverride, &overrides);
   1.481 +
   1.482 +  bool success = aParent->SendRegisterChrome(packages, resources, overrides,
   1.483 +                                             mSelectedLocale);
   1.484 +  NS_ENSURE_TRUE_VOID(success);
   1.485 +}
   1.486 +
   1.487 +PLDHashOperator
   1.488 +nsChromeRegistryChrome::CollectPackages(PLDHashTable *table,
   1.489 +                                  PLDHashEntryHdr *entry,
   1.490 +                                  uint32_t number,
   1.491 +                                  void *arg)
   1.492 +{
   1.493 +  EnumerationArgs* args = static_cast<EnumerationArgs*>(arg);
   1.494 +  PackageEntry* package = static_cast<PackageEntry*>(entry);
   1.495 +
   1.496 +  SerializedURI contentURI, localeURI, skinURI;
   1.497 +
   1.498 +  SerializeURI(package->baseURI, contentURI);
   1.499 +  SerializeURI(package->locales.GetBase(args->selectedLocale,
   1.500 +                                        nsProviderArray::LOCALE), localeURI);
   1.501 +  SerializeURI(package->skins.GetBase(args->selectedSkin, nsProviderArray::ANY),
   1.502 +               skinURI);
   1.503 +  
   1.504 +  ChromePackage chromePackage = {
   1.505 +    package->package,
   1.506 +    contentURI,
   1.507 +    localeURI,
   1.508 +    skinURI,
   1.509 +    package->flags
   1.510 +  };
   1.511 +  args->packages.AppendElement(chromePackage);
   1.512 +  return (PLDHashOperator)PL_DHASH_NEXT;
   1.513 +}
   1.514 +
   1.515 +static bool
   1.516 +CanLoadResource(nsIURI* aResourceURI)
   1.517 +{
   1.518 +  bool isLocalResource = false;
   1.519 +  (void)NS_URIChainHasFlags(aResourceURI,
   1.520 +                            nsIProtocolHandler::URI_IS_LOCAL_RESOURCE,
   1.521 +                            &isLocalResource);
   1.522 +  return isLocalResource;
   1.523 +}
   1.524 +
   1.525 +nsIURI*
   1.526 +nsChromeRegistryChrome::GetBaseURIFromPackage(const nsCString& aPackage,
   1.527 +                                              const nsCString& aProvider,
   1.528 +                                              const nsCString& aPath)
   1.529 +{
   1.530 +  PackageEntry* entry =
   1.531 +      static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.532 +                                                      &aPackage,
   1.533 +                                                      PL_DHASH_LOOKUP));
   1.534 +
   1.535 +  if (PL_DHASH_ENTRY_IS_FREE(entry)) {
   1.536 +    if (!mInitialized)
   1.537 +      return nullptr;
   1.538 +
   1.539 +    LogMessage("No chrome package registered for chrome://%s/%s/%s",
   1.540 +               aPackage.get(), aProvider.get(), aPath.get());
   1.541 +
   1.542 +    return nullptr;
   1.543 +  }
   1.544 +
   1.545 +  if (aProvider.EqualsLiteral("locale")) {
   1.546 +    return entry->locales.GetBase(mSelectedLocale, nsProviderArray::LOCALE);
   1.547 +  }
   1.548 +  else if (aProvider.EqualsLiteral("skin")) {
   1.549 +    return entry->skins.GetBase(mSelectedSkin, nsProviderArray::ANY);
   1.550 +  }
   1.551 +  else if (aProvider.EqualsLiteral("content")) {
   1.552 +    return entry->baseURI;
   1.553 +  }
   1.554 +  return nullptr;
   1.555 +}
   1.556 +
   1.557 +nsresult
   1.558 +nsChromeRegistryChrome::GetFlagsFromPackage(const nsCString& aPackage,
   1.559 +                                            uint32_t* aFlags)
   1.560 +{
   1.561 +  PackageEntry* entry =
   1.562 +      static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.563 +                                                      & (nsACString&) aPackage,
   1.564 +                                                      PL_DHASH_LOOKUP));
   1.565 +  if (PL_DHASH_ENTRY_IS_FREE(entry))
   1.566 +    return NS_ERROR_NOT_AVAILABLE;
   1.567 +
   1.568 +  *aFlags = entry->flags;
   1.569 +  return NS_OK;
   1.570 +}
   1.571 +
   1.572 +PLHashNumber
   1.573 +nsChromeRegistryChrome::HashKey(PLDHashTable *table, const void *key)
   1.574 +{
   1.575 +  const nsACString& str = *reinterpret_cast<const nsACString*>(key);
   1.576 +  return HashString(str);
   1.577 +}
   1.578 +
   1.579 +bool
   1.580 +nsChromeRegistryChrome::MatchKey(PLDHashTable *table, const PLDHashEntryHdr *entry,
   1.581 +                           const void *key)
   1.582 +{
   1.583 +  const nsACString& str = *reinterpret_cast<const nsACString*>(key);
   1.584 +  const PackageEntry* pentry = static_cast<const PackageEntry*>(entry);
   1.585 +  return str.Equals(pentry->package);
   1.586 +}
   1.587 +
   1.588 +void
   1.589 +nsChromeRegistryChrome::ClearEntry(PLDHashTable *table, PLDHashEntryHdr *entry)
   1.590 +{
   1.591 +  PackageEntry* pentry = static_cast<PackageEntry*>(entry);
   1.592 +  pentry->~PackageEntry();
   1.593 +}
   1.594 +
   1.595 +bool
   1.596 +nsChromeRegistryChrome::InitEntry(PLDHashTable *table, PLDHashEntryHdr *entry,
   1.597 +                            const void *key)
   1.598 +{
   1.599 +  const nsACString& str = *reinterpret_cast<const nsACString*>(key);
   1.600 +
   1.601 +  new (entry) PackageEntry(str);
   1.602 +  return true;
   1.603 +}
   1.604 +
   1.605 +const PLDHashTableOps
   1.606 +nsChromeRegistryChrome::kTableOps = {
   1.607 +  PL_DHashAllocTable,
   1.608 +  PL_DHashFreeTable,
   1.609 +  HashKey,
   1.610 +  MatchKey,
   1.611 +  PL_DHashMoveEntryStub,
   1.612 +  ClearEntry,
   1.613 +  PL_DHashFinalizeStub,
   1.614 +  InitEntry
   1.615 +};
   1.616 +
   1.617 +nsChromeRegistryChrome::ProviderEntry*
   1.618 +nsChromeRegistryChrome::nsProviderArray::GetProvider(const nsACString& aPreferred, MatchType aType)
   1.619 +{
   1.620 +  int32_t i = mArray.Count();
   1.621 +  if (!i)
   1.622 +    return nullptr;
   1.623 +
   1.624 +  ProviderEntry* found = nullptr;  // Only set if we find a partial-match locale
   1.625 +  ProviderEntry* entry;
   1.626 +
   1.627 +  while (i--) {
   1.628 +    entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
   1.629 +    if (aPreferred.Equals(entry->provider))
   1.630 +      return entry;
   1.631 +
   1.632 +    if (aType != LOCALE)
   1.633 +      continue;
   1.634 +
   1.635 +    if (LanguagesMatch(aPreferred, entry->provider)) {
   1.636 +      found = entry;
   1.637 +      continue;
   1.638 +    }
   1.639 +
   1.640 +    if (!found && entry->provider.EqualsLiteral("en-US"))
   1.641 +      found = entry;
   1.642 +  }
   1.643 +
   1.644 +  if (!found && aType != EXACT)
   1.645 +    return entry;
   1.646 +
   1.647 +  return found;
   1.648 +}
   1.649 +
   1.650 +nsIURI*
   1.651 +nsChromeRegistryChrome::nsProviderArray::GetBase(const nsACString& aPreferred, MatchType aType)
   1.652 +{
   1.653 +  ProviderEntry* provider = GetProvider(aPreferred, aType);
   1.654 +
   1.655 +  if (!provider)
   1.656 +    return nullptr;
   1.657 +
   1.658 +  return provider->baseURI;
   1.659 +}
   1.660 +
   1.661 +const nsACString&
   1.662 +nsChromeRegistryChrome::nsProviderArray::GetSelected(const nsACString& aPreferred, MatchType aType)
   1.663 +{
   1.664 +  ProviderEntry* entry = GetProvider(aPreferred, aType);
   1.665 +
   1.666 +  if (entry)
   1.667 +    return entry->provider;
   1.668 +
   1.669 +  return EmptyCString();
   1.670 +}
   1.671 +
   1.672 +void
   1.673 +nsChromeRegistryChrome::nsProviderArray::SetBase(const nsACString& aProvider, nsIURI* aBaseURL)
   1.674 +{
   1.675 +  ProviderEntry* provider = GetProvider(aProvider, EXACT);
   1.676 +
   1.677 +  if (provider) {
   1.678 +    provider->baseURI = aBaseURL;
   1.679 +    return;
   1.680 +  }
   1.681 +
   1.682 +  // no existing entries, add a new one
   1.683 +  provider = new ProviderEntry(aProvider, aBaseURL);
   1.684 +  if (!provider)
   1.685 +    return; // It's safe to silently fail on OOM
   1.686 +
   1.687 +  mArray.AppendElement(provider);
   1.688 +}
   1.689 +
   1.690 +void
   1.691 +nsChromeRegistryChrome::nsProviderArray::EnumerateToArray(nsTArray<nsCString> *a)
   1.692 +{
   1.693 +  int32_t i = mArray.Count();
   1.694 +  while (i--) {
   1.695 +    ProviderEntry *entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
   1.696 +    a->AppendElement(entry->provider);
   1.697 +  }
   1.698 +}
   1.699 +
   1.700 +void
   1.701 +nsChromeRegistryChrome::nsProviderArray::Clear()
   1.702 +{
   1.703 +  int32_t i = mArray.Count();
   1.704 +  while (i--) {
   1.705 +    ProviderEntry* entry = reinterpret_cast<ProviderEntry*>(mArray[i]);
   1.706 +    delete entry;
   1.707 +  }
   1.708 +
   1.709 +  mArray.Clear();
   1.710 +}
   1.711 +
   1.712 +void
   1.713 +nsChromeRegistryChrome::OverlayListEntry::AddURI(nsIURI* aURI)
   1.714 +{
   1.715 +  int32_t i = mArray.Count();
   1.716 +  while (i--) {
   1.717 +    bool equals;
   1.718 +    if (NS_SUCCEEDED(aURI->Equals(mArray[i], &equals)) && equals)
   1.719 +      return;
   1.720 +  }
   1.721 +
   1.722 +  mArray.AppendObject(aURI);
   1.723 +}
   1.724 +
   1.725 +void
   1.726 +nsChromeRegistryChrome::OverlayListHash::Add(nsIURI* aBase, nsIURI* aOverlay)
   1.727 +{
   1.728 +  OverlayListEntry* entry = mTable.PutEntry(aBase);
   1.729 +  if (entry)
   1.730 +    entry->AddURI(aOverlay);
   1.731 +}
   1.732 +
   1.733 +const nsCOMArray<nsIURI>*
   1.734 +nsChromeRegistryChrome::OverlayListHash::GetArray(nsIURI* aBase)
   1.735 +{
   1.736 +  OverlayListEntry* entry = mTable.GetEntry(aBase);
   1.737 +  if (!entry)
   1.738 +    return nullptr;
   1.739 +
   1.740 +  return &entry->mArray;
   1.741 +}
   1.742 +
   1.743 +#ifdef MOZ_XUL
   1.744 +NS_IMETHODIMP
   1.745 +nsChromeRegistryChrome::GetStyleOverlays(nsIURI *aChromeURL,
   1.746 +                                         nsISimpleEnumerator **aResult)
   1.747 +{
   1.748 +  const nsCOMArray<nsIURI>* parray = mStyleHash.GetArray(aChromeURL);
   1.749 +  if (!parray)
   1.750 +    return NS_NewEmptyEnumerator(aResult);
   1.751 +
   1.752 +  return NS_NewArrayEnumerator(aResult, *parray);
   1.753 +}
   1.754 +
   1.755 +NS_IMETHODIMP
   1.756 +nsChromeRegistryChrome::GetXULOverlays(nsIURI *aChromeURL,
   1.757 +                                       nsISimpleEnumerator **aResult)
   1.758 +{
   1.759 +  const nsCOMArray<nsIURI>* parray = mOverlayHash.GetArray(aChromeURL);
   1.760 +  if (!parray)
   1.761 +    return NS_NewEmptyEnumerator(aResult);
   1.762 +
   1.763 +  return NS_NewArrayEnumerator(aResult, *parray);
   1.764 +}
   1.765 +#endif // MOZ_XUL
   1.766 +
   1.767 +nsIURI*
   1.768 +nsChromeRegistry::ManifestProcessingContext::GetManifestURI()
   1.769 +{
   1.770 +  if (!mManifestURI) {
   1.771 +    nsCString uri;
   1.772 +    mFile.GetURIString(uri);
   1.773 +    NS_NewURI(getter_AddRefs(mManifestURI), uri);
   1.774 +  }
   1.775 +  return mManifestURI;
   1.776 +}
   1.777 +
   1.778 +nsIXPConnect*
   1.779 +nsChromeRegistry::ManifestProcessingContext::GetXPConnect()
   1.780 +{
   1.781 +  if (!mXPConnect)
   1.782 +    mXPConnect = do_GetService("@mozilla.org/js/xpc/XPConnect;1");
   1.783 +
   1.784 +  return mXPConnect;
   1.785 +}
   1.786 +
   1.787 +already_AddRefed<nsIURI>
   1.788 +nsChromeRegistry::ManifestProcessingContext::ResolveURI(const char* uri)
   1.789 +{
   1.790 +  nsIURI* baseuri = GetManifestURI();
   1.791 +  if (!baseuri)
   1.792 +    return nullptr;
   1.793 +
   1.794 +  nsCOMPtr<nsIURI> resolved;
   1.795 +  nsresult rv = NS_NewURI(getter_AddRefs(resolved), uri, baseuri);
   1.796 +  if (NS_FAILED(rv))
   1.797 +    return nullptr;
   1.798 +
   1.799 +  return resolved.forget();
   1.800 +}
   1.801 +
   1.802 +static void
   1.803 +EnsureLowerCase(char *aBuf)
   1.804 +{
   1.805 +  for (; *aBuf; ++aBuf) {
   1.806 +    char ch = *aBuf;
   1.807 +    if (ch >= 'A' && ch <= 'Z')
   1.808 +      *aBuf = ch + 'a' - 'A';
   1.809 +  }
   1.810 +}
   1.811 +
   1.812 +void
   1.813 +nsChromeRegistryChrome::ManifestContent(ManifestProcessingContext& cx, int lineno,
   1.814 +                                        char *const * argv, bool platform,
   1.815 +                                        bool contentaccessible)
   1.816 +{
   1.817 +  char* package = argv[0];
   1.818 +  char* uri = argv[1];
   1.819 +
   1.820 +  EnsureLowerCase(package);
   1.821 +
   1.822 +  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
   1.823 +  if (!resolved) {
   1.824 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.825 +                          "During chrome registration, unable to create URI '%s'.", uri);
   1.826 +    return;
   1.827 +  }
   1.828 +
   1.829 +  if (!CanLoadResource(resolved)) {
   1.830 +    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
   1.831 +                          "During chrome registration, cannot register non-local URI '%s' as content.",
   1.832 +                          uri);
   1.833 +    return;
   1.834 +  }
   1.835 +
   1.836 +  PackageEntry* entry =
   1.837 +    static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.838 +                                                    & (const nsACString&) nsDependentCString(package),
   1.839 +                                                    PL_DHASH_ADD));
   1.840 +  if (!entry)
   1.841 +    return;
   1.842 +
   1.843 +  entry->baseURI = resolved;
   1.844 +
   1.845 +  if (platform)
   1.846 +    entry->flags |= PLATFORM_PACKAGE;
   1.847 +  if (contentaccessible)
   1.848 +    entry->flags |= CONTENT_ACCESSIBLE;
   1.849 +}
   1.850 +
   1.851 +void
   1.852 +nsChromeRegistryChrome::ManifestLocale(ManifestProcessingContext& cx, int lineno,
   1.853 +                                       char *const * argv, bool platform,
   1.854 +                                       bool contentaccessible)
   1.855 +{
   1.856 +  char* package = argv[0];
   1.857 +  char* provider = argv[1];
   1.858 +  char* uri = argv[2];
   1.859 +
   1.860 +  EnsureLowerCase(package);
   1.861 +
   1.862 +  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
   1.863 +  if (!resolved) {
   1.864 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.865 +                          "During chrome registration, unable to create URI '%s'.", uri);
   1.866 +    return;
   1.867 +  }
   1.868 +
   1.869 +  if (!CanLoadResource(resolved)) {
   1.870 +    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
   1.871 +                          "During chrome registration, cannot register non-local URI '%s' as content.",
   1.872 +                          uri);
   1.873 +    return;
   1.874 +  }
   1.875 +
   1.876 +  PackageEntry* entry =
   1.877 +    static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.878 +                                                    & (const nsACString&) nsDependentCString(package),
   1.879 +                                                    PL_DHASH_ADD));
   1.880 +  if (!entry)
   1.881 +    return;
   1.882 +
   1.883 +  entry->locales.SetBase(nsDependentCString(provider), resolved);
   1.884 +}
   1.885 +
   1.886 +void
   1.887 +nsChromeRegistryChrome::ManifestSkin(ManifestProcessingContext& cx, int lineno,
   1.888 +                                     char *const * argv, bool platform,
   1.889 +                                     bool contentaccessible)
   1.890 +{
   1.891 +  char* package = argv[0];
   1.892 +  char* provider = argv[1];
   1.893 +  char* uri = argv[2];
   1.894 +
   1.895 +  EnsureLowerCase(package);
   1.896 +
   1.897 +  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
   1.898 +  if (!resolved) {
   1.899 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.900 +                          "During chrome registration, unable to create URI '%s'.", uri);
   1.901 +    return;
   1.902 +  }
   1.903 +
   1.904 +  if (!CanLoadResource(resolved)) {
   1.905 +    LogMessageWithContext(resolved, lineno, nsIScriptError::warningFlag,
   1.906 +                          "During chrome registration, cannot register non-local URI '%s' as content.",
   1.907 +                          uri);
   1.908 +    return;
   1.909 +  }
   1.910 +
   1.911 +  PackageEntry* entry =
   1.912 +    static_cast<PackageEntry*>(PL_DHashTableOperate(&mPackagesHash,
   1.913 +                                                    & (const nsACString&) nsDependentCString(package),
   1.914 +                                                    PL_DHASH_ADD));
   1.915 +  if (!entry)
   1.916 +    return;
   1.917 +
   1.918 +  entry->skins.SetBase(nsDependentCString(provider), resolved);
   1.919 +}
   1.920 +
   1.921 +void
   1.922 +nsChromeRegistryChrome::ManifestOverlay(ManifestProcessingContext& cx, int lineno,
   1.923 +                                        char *const * argv, bool platform,
   1.924 +                                        bool contentaccessible)
   1.925 +{
   1.926 +  char* base = argv[0];
   1.927 +  char* overlay = argv[1];
   1.928 +
   1.929 +  nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
   1.930 +  nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
   1.931 +  if (!baseuri || !overlayuri) {
   1.932 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.933 +                          "During chrome registration, unable to create URI.");
   1.934 +    return;
   1.935 +  }
   1.936 +
   1.937 +  if (!CanLoadResource(overlayuri)) {
   1.938 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.939 +                          "Cannot register non-local URI '%s' as an overlay.", overlay);
   1.940 +    return;
   1.941 +  }
   1.942 +
   1.943 +  mOverlayHash.Add(baseuri, overlayuri);
   1.944 +}
   1.945 +
   1.946 +void
   1.947 +nsChromeRegistryChrome::ManifestStyle(ManifestProcessingContext& cx, int lineno,
   1.948 +                                      char *const * argv, bool platform,
   1.949 +                                      bool contentaccessible)
   1.950 +{
   1.951 +  char* base = argv[0];
   1.952 +  char* overlay = argv[1];
   1.953 +
   1.954 +  nsCOMPtr<nsIURI> baseuri = cx.ResolveURI(base);
   1.955 +  nsCOMPtr<nsIURI> overlayuri = cx.ResolveURI(overlay);
   1.956 +  if (!baseuri || !overlayuri) {
   1.957 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.958 +                          "During chrome registration, unable to create URI.");
   1.959 +    return;
   1.960 +  }
   1.961 +
   1.962 +  if (!CanLoadResource(overlayuri)) {
   1.963 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.964 +                          "Cannot register non-local URI '%s' as a style overlay.", overlay);
   1.965 +    return;
   1.966 +  }
   1.967 +
   1.968 +  mStyleHash.Add(baseuri, overlayuri);
   1.969 +}
   1.970 +
   1.971 +void
   1.972 +nsChromeRegistryChrome::ManifestOverride(ManifestProcessingContext& cx, int lineno,
   1.973 +                                         char *const * argv, bool platform,
   1.974 +                                         bool contentaccessible)
   1.975 +{
   1.976 +  char* chrome = argv[0];
   1.977 +  char* resolved = argv[1];
   1.978 +
   1.979 +  nsCOMPtr<nsIURI> chromeuri = cx.ResolveURI(chrome);
   1.980 +  nsCOMPtr<nsIURI> resolveduri = cx.ResolveURI(resolved);
   1.981 +  if (!chromeuri || !resolveduri) {
   1.982 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.983 +                          "During chrome registration, unable to create URI.");
   1.984 +    return;
   1.985 +  }
   1.986 +
   1.987 +  if (!CanLoadResource(resolveduri)) {
   1.988 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
   1.989 +                          "Cannot register non-local URI '%s' for an override.", resolved);
   1.990 +    return;
   1.991 +  }
   1.992 +  mOverrideTable.Put(chromeuri, resolveduri);
   1.993 +}
   1.994 +
   1.995 +void
   1.996 +nsChromeRegistryChrome::ManifestResource(ManifestProcessingContext& cx, int lineno,
   1.997 +                                         char *const * argv, bool platform,
   1.998 +                                         bool contentaccessible)
   1.999 +{
  1.1000 +  char* package = argv[0];
  1.1001 +  char* uri = argv[1];
  1.1002 +
  1.1003 +  EnsureLowerCase(package);
  1.1004 +  nsDependentCString host(package);
  1.1005 +
  1.1006 +  nsCOMPtr<nsIIOService> io = mozilla::services::GetIOService();
  1.1007 +  if (!io) {
  1.1008 +    NS_WARNING("No IO service trying to process chrome manifests");
  1.1009 +    return;
  1.1010 +  }
  1.1011 +
  1.1012 +  nsCOMPtr<nsIProtocolHandler> ph;
  1.1013 +  nsresult rv = io->GetProtocolHandler("resource", getter_AddRefs(ph));
  1.1014 +  if (NS_FAILED(rv))
  1.1015 +    return;
  1.1016 +  
  1.1017 +  nsCOMPtr<nsIResProtocolHandler> rph = do_QueryInterface(ph);
  1.1018 +
  1.1019 +  bool exists = false;
  1.1020 +  rv = rph->HasSubstitution(host, &exists);
  1.1021 +  if (exists) {
  1.1022 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
  1.1023 +                          "Duplicate resource declaration for '%s' ignored.", package);
  1.1024 +    return;
  1.1025 +  }
  1.1026 +
  1.1027 +  nsCOMPtr<nsIURI> resolved = cx.ResolveURI(uri);
  1.1028 +  if (!resolved) {
  1.1029 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
  1.1030 +                          "During chrome registration, unable to create URI '%s'.", uri);
  1.1031 +    return;
  1.1032 +  }
  1.1033 +
  1.1034 +  if (!CanLoadResource(resolved)) {
  1.1035 +    LogMessageWithContext(cx.GetManifestURI(), lineno, nsIScriptError::warningFlag,
  1.1036 +                          "Warning: cannot register non-local URI '%s' as a resource.",
  1.1037 +                          uri);
  1.1038 +    return;
  1.1039 +  }
  1.1040 +
  1.1041 +  rph->SetSubstitution(host, resolved);
  1.1042 +}

mercurial