diff --git a/caps/nsScriptSecurityManager.cpp b/caps/nsScriptSecurityManager.cpp index 32b885f07a32..1171e1827bfa 100644 --- a/caps/nsScriptSecurityManager.cpp +++ b/caps/nsScriptSecurityManager.cpp @@ -77,10 +77,76 @@ using namespace mozilla; using namespace mozilla::dom; nsIIOService *nsScriptSecurityManager::sIOService = nullptr; -nsIStringBundle *nsScriptSecurityManager::sStrBundle = nullptr; JSContext *nsScriptSecurityManager::sContext = nullptr; bool nsScriptSecurityManager::sStrictFileOriginPolicy = true; +namespace { + +class BundleHelper +{ +public: + NS_INLINE_DECL_REFCOUNTING(BundleHelper) + + static nsIStringBundle* + GetOrCreate() + { + MOZ_ASSERT(!sShutdown); + + // Already shutting down. Nothing should require the use of the string + // bundle when shutting down. + if (sShutdown) { + return nullptr; + } + + if (!sSelf) { + sSelf = new BundleHelper(); + } + + return sSelf->GetOrCreateInternal(); + } + + static void + Shutdown() + { + sSelf = nullptr; + sShutdown = true; + } + +private: + ~BundleHelper() = default; + + nsIStringBundle* + GetOrCreateInternal() + { + if (!mBundle) { + nsCOMPtr bundleService = + mozilla::services::GetStringBundleService(); + if (NS_WARN_IF(!bundleService)) { + return nullptr; + } + + nsresult rv = + bundleService->CreateBundle("chrome://global/locale/security/caps.properties", + getter_AddRefs(mBundle)); + if (NS_WARN_IF(NS_FAILED(rv))) { + return nullptr; + } + } + + return mBundle; + } + + nsCOMPtr mBundle; + + static StaticRefPtr sSelf; + static bool sShutdown; +}; + +StaticRefPtr BundleHelper::sSelf; +bool BundleHelper::sShutdown = false; + +} // anonymous + /////////////////////////// // Convenience Functions // /////////////////////////// @@ -981,20 +1047,22 @@ nsScriptSecurityManager::CheckLoadURIFlags(nsIURI *aSourceURI, &hasSubsumersFlag); NS_ENSURE_SUCCESS(rv, rv); if (!hasFlags && !hasSubsumersFlag) { - nsAutoString message; - NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme); - const char16_t* formatStrings[] = { ucsTargetScheme.get() }; - rv = sStrBundle-> - FormatStringFromName("ProtocolFlagError", - formatStrings, - ArrayLength(formatStrings), - message); - if (NS_SUCCEEDED(rv)) { - nsCOMPtr console( - do_GetService("@mozilla.org/consoleservice;1")); - NS_ENSURE_TRUE(console, NS_ERROR_FAILURE); + nsCOMPtr bundle = BundleHelper::GetOrCreate(); + if (bundle) { + nsAutoString message; + NS_ConvertASCIItoUTF16 ucsTargetScheme(targetScheme); + const char16_t* formatStrings[] = { ucsTargetScheme.get() }; + rv = bundle->FormatStringFromName("ProtocolFlagError", + formatStrings, + ArrayLength(formatStrings), + message); + if (NS_SUCCEEDED(rv)) { + nsCOMPtr console( + do_GetService("@mozilla.org/consoleservice;1")); + NS_ENSURE_TRUE(console, NS_ERROR_FAILURE); - console->LogStringMessage(message.get()); + console->LogStringMessage(message.get()); + } } } @@ -1018,15 +1086,20 @@ nsScriptSecurityManager::ReportError(JSContext* cx, const char* aMessageTag, rv = aTarget->GetAsciiSpec(targetSpec); NS_ENSURE_SUCCESS(rv, rv); + nsCOMPtr bundle = BundleHelper::GetOrCreate(); + if (NS_WARN_IF(!bundle)) { + return NS_OK; + } + // Localize the error message nsAutoString message; NS_ConvertASCIItoUTF16 ucsSourceSpec(sourceSpec); NS_ConvertASCIItoUTF16 ucsTargetSpec(targetSpec); const char16_t *formatStrings[] = { ucsSourceSpec.get(), ucsTargetSpec.get() }; - rv = sStrBundle->FormatStringFromName(aMessageTag, - formatStrings, - ArrayLength(formatStrings), - message); + rv = bundle->FormatStringFromName(aMessageTag, + formatStrings, + ArrayLength(formatStrings), + message); NS_ENSURE_SUCCESS(rv, rv); // If a JS context was passed in, set a JS exception. @@ -1237,22 +1310,28 @@ nsScriptSecurityManager::CanCreateWrapper(JSContext *cx, if (classInfoNameUTF8.IsEmpty()) { classInfoNameUTF8.AssignLiteral("UnnamedClass"); } + + nsCOMPtr bundle = BundleHelper::GetOrCreate(); + if (NS_WARN_IF(!bundle)) { + return NS_OK; + } + NS_ConvertUTF8toUTF16 classInfoUTF16(classInfoNameUTF8); nsresult rv; nsAutoString errorMsg; if (originUTF16.IsEmpty()) { const char16_t* formatStrings[] = { classInfoUTF16.get() }; - rv = sStrBundle->FormatStringFromName("CreateWrapperDenied", - formatStrings, - 1, - errorMsg); + rv = bundle->FormatStringFromName("CreateWrapperDenied", + formatStrings, + 1, + errorMsg); } else { const char16_t* formatStrings[] = { classInfoUTF16.get(), originUTF16.get() }; - rv = sStrBundle->FormatStringFromName("CreateWrapperDeniedForOrigin", - formatStrings, - 2, - errorMsg); + rv = bundle->FormatStringFromName("CreateWrapperDeniedForOrigin", + formatStrings, + 2, + errorMsg); } NS_ENSURE_SUCCESS(rv, rv); @@ -1336,14 +1415,6 @@ nsresult nsScriptSecurityManager::Init() InitPrefs(); - nsCOMPtr bundleService = - mozilla::services::GetStringBundleService(); - if (!bundleService) - return NS_ERROR_FAILURE; - - rv = bundleService->CreateBundle("chrome://global/locale/security/caps.properties", &sStrBundle); - NS_ENSURE_SUCCESS(rv, rv); - // Create our system principal singleton RefPtr system = SystemPrincipal::Create(); @@ -1392,7 +1463,7 @@ nsScriptSecurityManager::Shutdown() } NS_IF_RELEASE(sIOService); - NS_IF_RELEASE(sStrBundle); + BundleHelper::Shutdown(); } nsScriptSecurityManager *