fune/chrome/nsChromeRegistry.cpp
Dorel Luca 4bbd01493b Backed out 43 changesets (bug 1561724, bug 1561150, bug 1541557, bug 1561122, bug 1560400, bug 1558298, bug 1561999, bug 1532795, bug 1561061) for multiple failures. CLOSED TREE
Backed out changeset 1a4fe24a016c (bug 1541557)
Backed out changeset 6fc41e51bcee (bug 1561061)
Backed out changeset d916d89a5c90 (bug 1561122)
Backed out changeset 757d285aafdd (bug 1560400)
Backed out changeset a7eab5ca061d (bug 1541557)
Backed out changeset d972bbdfe039 (bug 1541557)
Backed out changeset 8802daac6779 (bug 1541557)
Backed out changeset 92c01418b96f (bug 1561150)
Backed out changeset fa5e186e1635 (bug 1561061)
Backed out changeset aa2bee0b18c3 (bug 1560400)
Backed out changeset adf832af8e48 (bug 1561150)
Backed out changeset 72630a7c6e67 (bug 1561999)
Backed out changeset c35aff2a9336 (bug 1561724)
Backed out changeset 19e0edc92077 (bug 1561150)
Backed out changeset 0b3e2164f128 (bug 1561150)
Backed out changeset 43211ebfe738 (bug 1561122)
Backed out changeset c2d0956f41d8 (bug 1561061)
Backed out changeset bf0f0e95c61c (bug 1560400)
Backed out changeset 84633034590f (bug 1560400)
Backed out changeset d5415970da5f (bug 1532795)
Backed out changeset 119caddcb066 (bug 1532795)
Backed out changeset fbbe113aeef2 (bug 1532795)
Backed out changeset 8a3d311c7fac (bug 1532795)
Backed out changeset 1471732eca80 (bug 1532795)
Backed out changeset 46ff845a7b0c (bug 1541557)
Backed out changeset c2697f04d38c (bug 1541557)
Backed out changeset 75ebd6fce136 (bug 1541557)
Backed out changeset 189dc8a35981 (bug 1541557)
Backed out changeset b4ed40bea269 (bug 1541557)
Backed out changeset 158a4000c44b (bug 1541557)
Backed out changeset 61fa2745733f (bug 1541557)
Backed out changeset d2ee912c5189 (bug 1558298)
Backed out changeset 7a0aab00327b (bug 1558298)
Backed out changeset fddf2808fedf (bug 1558298)
Backed out changeset 0f6b382f0626 (bug 1558298)
Backed out changeset 6ccaa25367f2 (bug 1558298)
Backed out changeset d27574cfbb0e (bug 1558298)
Backed out changeset 162bc1fc2730 (bug 1558298)
Backed out changeset f94500dd11e3 (bug 1558298)
Backed out changeset fb67ac962bc5 (bug 1558298)
Backed out changeset c634099abb9d (bug 1558298)
Backed out changeset 8d4419c439e1 (bug 1558298)
Backed out changeset d8b7ed5e149f (bug 1558298)

--HG--
rename : testing/mochitest/tests/SimpleTest/MozillaLogger.js => testing/specialpowers/content/MozillaLogger.js
rename : testing/specialpowers/content/SpecialPowersParent.jsm => testing/specialpowers/content/SpecialPowersObserver.jsm
rename : testing/specialpowers/content/SpecialPowersAPIParent.jsm => testing/specialpowers/content/SpecialPowersObserverAPI.js
rename : testing/specialpowers/content/SpecialPowersChild.jsm => testing/specialpowers/content/specialpowers.js
rename : testing/specialpowers/content/SpecialPowersAPI.jsm => testing/specialpowers/content/specialpowersAPI.js
2019-07-02 10:51:56 +03:00

441 lines
12 KiB
C++

/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=2 sw=2 et tw=78: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsChromeRegistry.h"
#include "nsChromeRegistryChrome.h"
#include "nsChromeRegistryContent.h"
#include "nsCOMPtr.h"
#include "nsError.h"
#include "nsEscape.h"
#include "nsNetUtil.h"
#include "nsString.h"
#include "nsQueryObject.h"
#include "mozilla/dom/URL.h"
#include "nsDOMWindowList.h"
#include "nsIConsoleService.h"
#include "mozilla/dom/Document.h"
#include "nsIDOMWindow.h"
#include "nsIObserverService.h"
#include "nsIScriptError.h"
#include "nsIWindowMediator.h"
#include "nsIPrefService.h"
#include "mozilla/Preferences.h"
#include "mozilla/PresShell.h"
#include "mozilla/Printf.h"
#include "mozilla/StyleSheet.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/dom/Location.h"
#include "nsIURIMutator.h"
#include "unicode/uloc.h"
nsChromeRegistry* nsChromeRegistry::gChromeRegistry;
// DO NOT use namespace mozilla; it'll break due to a naming conflict between
// mozilla::TextRange and a TextRange in OSX headers.
using mozilla::PresShell;
using mozilla::StyleSheet;
using mozilla::dom::Document;
using mozilla::dom::Location;
////////////////////////////////////////////////////////////////////////////////
void nsChromeRegistry::LogMessage(const char* aMsg, ...) {
nsCOMPtr<nsIConsoleService> console(
do_GetService(NS_CONSOLESERVICE_CONTRACTID));
if (!console) return;
va_list args;
va_start(args, aMsg);
mozilla::SmprintfPointer formatted = mozilla::Vsmprintf(aMsg, args);
va_end(args);
if (!formatted) return;
console->LogStringMessage(NS_ConvertUTF8toUTF16(formatted.get()).get());
}
void nsChromeRegistry::LogMessageWithContext(nsIURI* aURL, uint32_t aLineNumber,
uint32_t flags, const char* aMsg,
...) {
nsresult rv;
nsCOMPtr<nsIConsoleService> console(
do_GetService(NS_CONSOLESERVICE_CONTRACTID));
nsCOMPtr<nsIScriptError> error(do_CreateInstance(NS_SCRIPTERROR_CONTRACTID));
if (!console || !error) return;
va_list args;
va_start(args, aMsg);
mozilla::SmprintfPointer formatted = mozilla::Vsmprintf(aMsg, args);
va_end(args);
if (!formatted) return;
nsCString spec;
if (aURL) aURL->GetSpec(spec);
rv = error->Init(
NS_ConvertUTF8toUTF16(formatted.get()), NS_ConvertUTF8toUTF16(spec),
EmptyString(), aLineNumber, 0, flags, "chrome registration",
false /* from private window */, true /* from chrome context */);
if (NS_FAILED(rv)) return;
console->LogMessage(error);
}
nsChromeRegistry::~nsChromeRegistry() { gChromeRegistry = nullptr; }
NS_INTERFACE_MAP_BEGIN(nsChromeRegistry)
NS_INTERFACE_MAP_ENTRY(nsIChromeRegistry)
NS_INTERFACE_MAP_ENTRY(nsIXULChromeRegistry)
NS_INTERFACE_MAP_ENTRY(nsIToolkitChromeRegistry)
NS_INTERFACE_MAP_ENTRY(nsIObserver)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIChromeRegistry)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsChromeRegistry)
NS_IMPL_RELEASE(nsChromeRegistry)
////////////////////////////////////////////////////////////////////////////////
// nsIChromeRegistry methods:
already_AddRefed<nsIChromeRegistry> nsChromeRegistry::GetService() {
if (!gChromeRegistry) {
// We don't actually want this ref, we just want the service to
// initialize if it hasn't already.
nsCOMPtr<nsIChromeRegistry> reg(
do_GetService(NS_CHROMEREGISTRY_CONTRACTID));
if (!gChromeRegistry) return nullptr;
}
nsCOMPtr<nsIChromeRegistry> registry = gChromeRegistry;
return registry.forget();
}
nsresult nsChromeRegistry::Init() {
// This initialization process is fairly complicated and may cause reentrant
// getservice calls to resolve chrome URIs (especially locale files). We
// don't want that, so we inform the protocol handler about our existence
// before we are actually fully initialized.
gChromeRegistry = this;
mInitialized = true;
return NS_OK;
}
nsresult nsChromeRegistry::GetProviderAndPath(nsIURI* aChromeURL,
nsACString& aProvider,
nsACString& aPath) {
nsresult rv;
#ifdef DEBUG
bool isChrome;
aChromeURL->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI?");
#endif
nsAutoCString path;
rv = aChromeURL->GetPathQueryRef(path);
NS_ENSURE_SUCCESS(rv, rv);
if (path.Length() < 3) {
LogMessage("Invalid chrome URI: %s", path.get());
return NS_ERROR_FAILURE;
}
path.SetLength(nsUnescapeCount(path.BeginWriting()));
NS_ASSERTION(path.First() == '/', "Path should always begin with a slash!");
int32_t slash = path.FindChar('/', 1);
if (slash == 1) {
LogMessage("Invalid chrome URI: %s", path.get());
return NS_ERROR_FAILURE;
}
if (slash == -1) {
aPath.Truncate();
} else {
if (slash == (int32_t)path.Length() - 1)
aPath.Truncate();
else
aPath.Assign(path.get() + slash + 1, path.Length() - slash - 1);
--slash;
}
aProvider.Assign(path.get() + 1, slash);
return NS_OK;
}
nsresult nsChromeRegistry::Canonify(nsCOMPtr<nsIURI>& aChromeURL) {
NS_NAMED_LITERAL_CSTRING(kSlash, "/");
nsresult rv;
nsAutoCString provider, path;
rv = GetProviderAndPath(aChromeURL, provider, path);
NS_ENSURE_SUCCESS(rv, rv);
if (path.IsEmpty()) {
nsAutoCString package;
rv = aChromeURL->GetHost(package);
NS_ENSURE_SUCCESS(rv, rv);
// we re-use the "path" local string to build a new URL path
path.Assign(kSlash + provider + kSlash + package);
if (provider.EqualsLiteral("content")) {
path.AppendLiteral(".xul");
} else if (provider.EqualsLiteral("locale")) {
path.AppendLiteral(".dtd");
} else if (provider.EqualsLiteral("skin")) {
path.AppendLiteral(".css");
} else {
return NS_ERROR_INVALID_ARG;
}
return NS_MutateURI(aChromeURL).SetPathQueryRef(path).Finalize(aChromeURL);
} else {
// prevent directory traversals ("..")
// path is already unescaped once, but uris can get unescaped twice
const char* pos = path.BeginReading();
const char* end = path.EndReading();
// Must start with [a-zA-Z0-9].
if (!('a' <= *pos && *pos <= 'z') && !('A' <= *pos && *pos <= 'Z') &&
!('0' <= *pos && *pos <= '9')) {
return NS_ERROR_DOM_BAD_URI;
}
while (pos < end) {
switch (*pos) {
case ':':
return NS_ERROR_DOM_BAD_URI;
case '.':
if (pos[1] == '.') return NS_ERROR_DOM_BAD_URI;
break;
case '%':
// chrome: URIs with double-escapes are trying to trick us.
// watch for %2e, and %25 in case someone triple unescapes
if (pos[1] == '2' &&
(pos[2] == 'e' || pos[2] == 'E' || pos[2] == '5'))
return NS_ERROR_DOM_BAD_URI;
break;
case '?':
case '#':
pos = end;
continue;
}
++pos;
}
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::ConvertChromeURL(nsIURI* aChromeURI, nsIURI** aResult) {
nsresult rv;
if (NS_WARN_IF(!aChromeURI)) {
return NS_ERROR_INVALID_ARG;
}
if (mOverrideTable.Get(aChromeURI, aResult)) return NS_OK;
nsCOMPtr<nsIURL> chromeURL(do_QueryInterface(aChromeURI));
NS_ENSURE_TRUE(chromeURL, NS_NOINTERFACE);
nsAutoCString package, provider, path;
rv = chromeURL->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
rv = GetProviderAndPath(chromeURL, provider, path);
NS_ENSURE_SUCCESS(rv, rv);
nsIURI* baseURI = GetBaseURIFromPackage(package, provider, path);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_FAILED(rv)) return rv;
if (!baseURI) {
LogMessage("No chrome package registered for chrome://%s/%s/%s",
package.get(), provider.get(), path.get());
return NS_ERROR_FILE_NOT_FOUND;
}
return NS_NewURI(aResult, path, nullptr, baseURI);
}
////////////////////////////////////////////////////////////////////////
void nsChromeRegistry::FlushAllCaches() {
nsCOMPtr<nsIObserverService> obsSvc = mozilla::services::GetObserverService();
NS_ASSERTION(obsSvc, "Couldn't get observer service.");
obsSvc->NotifyObservers((nsIChromeRegistry*)this, NS_CHROME_FLUSH_TOPIC,
nullptr);
}
NS_IMETHODIMP
nsChromeRegistry::AllowScriptsForPackage(nsIURI* aChromeURI, bool* aResult) {
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aChromeURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowScriptsForPackage!");
#endif
nsCOMPtr<nsIURL> url(do_QueryInterface(aChromeURI));
NS_ENSURE_TRUE(url, NS_NOINTERFACE);
nsAutoCString provider, file;
rv = GetProviderAndPath(url, provider, file);
NS_ENSURE_SUCCESS(rv, rv);
if (!provider.EqualsLiteral("skin")) *aResult = true;
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::AllowContentToAccess(nsIURI* aURI, bool* aResult) {
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to AllowContentToAccess!");
#endif
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
NS_ERROR("Chrome URL doesn't implement nsIURL.");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString package;
rv = url->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_SUCCEEDED(rv)) {
*aResult = !!(flags & CONTENT_ACCESSIBLE);
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::CanLoadURLRemotely(nsIURI* aURI, bool* aResult) {
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to CanLoadURLRemotely!");
#endif
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
NS_ERROR("Chrome URL doesn't implement nsIURL.");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString package;
rv = url->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_SUCCEEDED(rv)) {
*aResult = !!(flags & REMOTE_ALLOWED);
}
return NS_OK;
}
NS_IMETHODIMP
nsChromeRegistry::MustLoadURLRemotely(nsIURI* aURI, bool* aResult) {
nsresult rv;
*aResult = false;
#ifdef DEBUG
bool isChrome;
aURI->SchemeIs("chrome", &isChrome);
NS_ASSERTION(isChrome, "Non-chrome URI passed to MustLoadURLRemotely!");
#endif
nsCOMPtr<nsIURL> url = do_QueryInterface(aURI);
if (!url) {
NS_ERROR("Chrome URL doesn't implement nsIURL.");
return NS_ERROR_UNEXPECTED;
}
nsAutoCString package;
rv = url->GetHostPort(package);
NS_ENSURE_SUCCESS(rv, rv);
uint32_t flags;
rv = GetFlagsFromPackage(package, &flags);
if (NS_SUCCEEDED(rv)) {
*aResult = !!(flags & REMOTE_REQUIRED);
}
return NS_OK;
}
bool nsChromeRegistry::GetDirectionForLocale(const nsACString& aLocale) {
int pref = mozilla::Preferences::GetInt("intl.uidirection", -1);
if (pref >= 0) {
return (pref > 0);
}
nsAutoCString locale(aLocale);
SanitizeForBCP47(locale);
return uloc_isRightToLeft(locale.get());
}
already_AddRefed<nsChromeRegistry> nsChromeRegistry::GetSingleton() {
if (gChromeRegistry) {
RefPtr<nsChromeRegistry> registry = gChromeRegistry;
return registry.forget();
}
RefPtr<nsChromeRegistry> cr;
if (GeckoProcessType_Content == XRE_GetProcessType())
cr = new nsChromeRegistryContent();
else
cr = new nsChromeRegistryChrome();
if (NS_FAILED(cr->Init())) return nullptr;
return cr.forget();
}
void nsChromeRegistry::SanitizeForBCP47(nsACString& aLocale) {
// Currently, the only locale code we use that's not BCP47-conformant is
// "ja-JP-mac" on OS X, but let's try to be more general than just
// hard-coding that here.
const int32_t LANG_TAG_CAPACITY = 128;
char langTag[LANG_TAG_CAPACITY];
nsAutoCString locale(aLocale);
UErrorCode err = U_ZERO_ERROR;
// This is a fail-safe method that will set langTag to "und" if it cannot
// match any part of the input locale code.
int32_t len =
uloc_toLanguageTag(locale.get(), langTag, LANG_TAG_CAPACITY, false, &err);
if (U_SUCCESS(err) && len > 0) {
aLocale.Assign(langTag, len);
}
}