Bug 1300720 - Part 2: Lazily initialize nsScriptSecurityManager::mFileURIWhitelist. r=bholley
MozReview-Commit-ID: GeFVryehKBf
--- a/caps/nsScriptSecurityManager.cpp
+++ b/caps/nsScriptSecurityManager.cpp
@@ -918,18 +918,18 @@ nsScriptSecurityManager::CheckLoadURIFla
// Check for target URI pointing to a file
rv = NS_URIChainHasFlags(aTargetURI,
nsIProtocolHandler::URI_IS_LOCAL_FILE,
&hasFlags);
NS_ENSURE_SUCCESS(rv, rv);
if (hasFlags) {
// Allow domains that were whitelisted in the prefs. In 99.9% of cases,
// this array is empty.
- for (size_t i = 0; i < mFileURIWhitelist.Length(); ++i) {
- if (EqualOrSubdomain(aSourceURI, mFileURIWhitelist[i])) {
+ for (nsIURI* uri : EnsureFileURIWhitelist()) {
+ if (EqualOrSubdomain(aSourceURI, uri)) {
return NS_OK;
}
}
// Allow chrome://
bool isChrome = false;
if (NS_SUCCEEDED(aSourceBaseURI->SchemeIs("chrome", &isChrome)) && isChrome) {
return NS_OK;
@@ -1454,48 +1454,17 @@ uint32_t SkipUntil(const nsCString& str,
inline void
nsScriptSecurityManager::ScriptSecurityPrefChanged()
{
MOZ_ASSERT(mPrefInitialized);
mIsJavaScriptEnabled =
Preferences::GetBool(sJSEnabledPrefName, mIsJavaScriptEnabled);
sStrictFileOriginPolicy =
Preferences::GetBool(sFileOriginPolicyPrefName, false);
-
- //
- // Rebuild the set of principals for which we allow file:// URI loads. This
- // implements a small subset of an old pref-based CAPS people that people
- // have come to depend on. See bug 995943.
- //
-
- mFileURIWhitelist.Clear();
- auto policies = mozilla::Preferences::GetCString("capability.policy.policynames");
- for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0;
- base < policies.Length();
- base = SkipPast<IsWhitespaceOrComma>(policies, bound))
- {
- // Grab the current policy name.
- bound = SkipUntil<IsWhitespaceOrComma>(policies, base);
- auto policyName = Substring(policies, base, bound - base);
-
- // Figure out if this policy allows loading file:// URIs. If not, we can skip it.
- nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") +
- policyName +
- NS_LITERAL_CSTRING(".checkloaduri.enabled");
- if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) {
- continue;
- }
-
- // Grab the list of domains associated with this policy.
- nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") +
- policyName +
- NS_LITERAL_CSTRING(".sites");
- auto siteList = Preferences::GetCString(domainPrefName.get());
- AddSitesToFileURIWhitelist(siteList);
- }
+ mFileURIWhitelist.reset();
}
void
nsScriptSecurityManager::AddSitesToFileURIWhitelist(const nsCString& aSiteList)
{
for (uint32_t base = SkipPast<IsWhitespace>(aSiteList, 0), bound = 0;
base < aSiteList.Length();
base = SkipPast<IsWhitespace>(aSiteList, bound))
@@ -1511,17 +1480,17 @@ nsScriptSecurityManager::AddSitesToFileU
AddSitesToFileURIWhitelist(NS_LITERAL_CSTRING("https://") + site);
continue;
}
// Convert it to a URI and add it to our list.
nsCOMPtr<nsIURI> uri;
nsresult rv = NS_NewURI(getter_AddRefs(uri), site, nullptr, nullptr, sIOService);
if (NS_SUCCEEDED(rv)) {
- mFileURIWhitelist.AppendElement(uri);
+ mFileURIWhitelist.ref().AppendElement(uri);
} else {
nsCOMPtr<nsIConsoleService> console(do_GetService("@mozilla.org/consoleservice;1"));
if (console) {
nsAutoString msg = NS_LITERAL_STRING("Unable to to add site to file:// URI whitelist: ") +
NS_ConvertASCIItoUTF16(site);
console->LogStringMessage(msg.get());
}
}
@@ -1671,8 +1640,50 @@ nsScriptSecurityManager::PolicyAllowsScr
rv = superExceptions->ContainsSuperDomain(aURI, &contains);
NS_ENSURE_SUCCESS(rv, rv);
if (contains) {
*aRv = !*aRv;
}
return NS_OK;
}
+
+const nsTArray<nsCOMPtr<nsIURI>>&
+nsScriptSecurityManager::EnsureFileURIWhitelist()
+{
+ if (mFileURIWhitelist.isSome()) {
+ return mFileURIWhitelist.ref();
+ }
+
+ //
+ // Rebuild the set of principals for which we allow file:// URI loads. This
+ // implements a small subset of an old pref-based CAPS people that people
+ // have come to depend on. See bug 995943.
+ //
+
+ mFileURIWhitelist.emplace();
+ auto policies = mozilla::Preferences::GetCString("capability.policy.policynames");
+ for (uint32_t base = SkipPast<IsWhitespaceOrComma>(policies, 0), bound = 0;
+ base < policies.Length();
+ base = SkipPast<IsWhitespaceOrComma>(policies, bound))
+ {
+ // Grab the current policy name.
+ bound = SkipUntil<IsWhitespaceOrComma>(policies, base);
+ auto policyName = Substring(policies, base, bound - base);
+
+ // Figure out if this policy allows loading file:// URIs. If not, we can skip it.
+ nsCString checkLoadURIPrefName = NS_LITERAL_CSTRING("capability.policy.") +
+ policyName +
+ NS_LITERAL_CSTRING(".checkloaduri.enabled");
+ if (!Preferences::GetString(checkLoadURIPrefName.get()).LowerCaseEqualsLiteral("allaccess")) {
+ continue;
+ }
+
+ // Grab the list of domains associated with this policy.
+ nsCString domainPrefName = NS_LITERAL_CSTRING("capability.policy.") +
+ policyName +
+ NS_LITERAL_CSTRING(".sites");
+ auto siteList = Preferences::GetCString(domainPrefName.get());
+ AddSitesToFileURIWhitelist(siteList);
+ }
+
+ return mFileURIWhitelist.ref();
+}
--- a/caps/nsScriptSecurityManager.h
+++ b/caps/nsScriptSecurityManager.h
@@ -119,20 +119,28 @@ private:
nsresult GetChannelResultPrincipal(nsIChannel* aChannel,
nsIPrincipal** aPrincipal,
bool aIgnoreSandboxing);
nsresult
CheckLoadURIFlags(nsIURI* aSourceURI, nsIURI* aTargetURI, nsIURI* aSourceBaseURI,
nsIURI* aTargetBaseURI, uint32_t aFlags);
+ // Returns the file URI whitelist, initializing it if it has not been
+ // initialized.
+ const nsTArray<nsCOMPtr<nsIURI>>& EnsureFileURIWhitelist();
+
nsCOMPtr<nsIPrincipal> mSystemPrincipal;
bool mPrefInitialized;
bool mIsJavaScriptEnabled;
- nsTArray<nsCOMPtr<nsIURI>> mFileURIWhitelist;
+
+ // List of URIs whose domains and sub-domains are whitelisted to allow
+ // access to file: URIs. Lazily initialized; isNothing() when not yet
+ // initialized.
+ mozilla::Maybe<nsTArray<nsCOMPtr<nsIURI>>> mFileURIWhitelist;
// This machinery controls new-style domain policies. The old-style
// policy machinery will be removed soon.
nsCOMPtr<nsIDomainPolicy> mDomainPolicy;
// Cached addon policy service. We can't generate this in Init() because
// that's too early to get a service.
mozilla::Maybe<nsCOMPtr<nsIAddonPolicyService>> mAddonPolicyService;