michael@0: /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- michael@0: * michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #include "nsSecurityWarningDialogs.h" michael@0: #include "nsIComponentManager.h" michael@0: #include "nsIServiceManager.h" michael@0: #include "nsReadableUtils.h" michael@0: #include "nsString.h" michael@0: #include "nsIPrompt.h" michael@0: #include "nsIInterfaceRequestor.h" michael@0: #include "nsIInterfaceRequestorUtils.h" michael@0: #include "nsIPrefService.h" michael@0: #include "nsIPrefBranch.h" michael@0: #include "nsThreadUtils.h" michael@0: michael@0: #include "mozilla/Telemetry.h" michael@0: #include "nsISecurityUITelemetry.h" michael@0: michael@0: NS_IMPL_ISUPPORTS(nsSecurityWarningDialogs, nsISecurityWarningDialogs) michael@0: michael@0: #define STRING_BUNDLE_URL "chrome://pipnss/locale/security.properties" michael@0: michael@0: nsSecurityWarningDialogs::nsSecurityWarningDialogs() michael@0: { michael@0: } michael@0: michael@0: nsSecurityWarningDialogs::~nsSecurityWarningDialogs() michael@0: { michael@0: } michael@0: michael@0: nsresult michael@0: nsSecurityWarningDialogs::Init() michael@0: { michael@0: nsresult rv; michael@0: michael@0: mPrefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: nsCOMPtr service = michael@0: do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv); michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: rv = service->CreateBundle(STRING_BUNDLE_URL, michael@0: getter_AddRefs(mStringBundle)); michael@0: return rv; michael@0: } michael@0: michael@0: NS_IMETHODIMP michael@0: nsSecurityWarningDialogs::ConfirmPostToInsecureFromSecure(nsIInterfaceRequestor *ctx, bool* _result) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // The Telemetry clickthrough constant is 1 more than the constant for the dialog. michael@0: rv = ConfirmDialog(ctx, nullptr, // No preference for this one - it's too important michael@0: MOZ_UTF16("PostToInsecureFromSecureMessage"), michael@0: nullptr, michael@0: nsISecurityUITelemetry::WARNING_CONFIRM_POST_TO_INSECURE_FROM_SECURE, michael@0: _result); michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: nsresult michael@0: nsSecurityWarningDialogs::ConfirmDialog(nsIInterfaceRequestor *ctx, const char *prefName, michael@0: const char16_t *messageName, michael@0: const char16_t *showAgainName, michael@0: const uint32_t aBucket, michael@0: bool* _result) michael@0: { michael@0: nsresult rv; michael@0: michael@0: // Get user's preference for this alert michael@0: // prefName, showAgainName are null if there is no preference for this dialog michael@0: bool prefValue = true; michael@0: michael@0: if (prefName) { michael@0: rv = mPrefBranch->GetBoolPref(prefName, &prefValue); michael@0: if (NS_FAILED(rv)) prefValue = true; michael@0: } michael@0: michael@0: // Stop if confirm is not requested michael@0: if (!prefValue) { michael@0: *_result = true; michael@0: return NS_OK; michael@0: } michael@0: michael@0: MOZ_ASSERT(NS_IsMainThread()); michael@0: mozilla::Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI, aBucket); michael@0: // See AlertDialog() for a description of how showOnce works. michael@0: nsAutoCString showOncePref(prefName); michael@0: showOncePref += ".show_once"; michael@0: michael@0: bool showOnce = false; michael@0: mPrefBranch->GetBoolPref(showOncePref.get(), &showOnce); michael@0: michael@0: if (showOnce) michael@0: prefValue = false; michael@0: michael@0: // Get Prompt to use michael@0: nsCOMPtr prompt = do_GetInterface(ctx); michael@0: if (!prompt) return NS_ERROR_FAILURE; michael@0: michael@0: // Get messages strings from localization file michael@0: nsXPIDLString windowTitle, message, alertMe, cont; michael@0: michael@0: mStringBundle->GetStringFromName(MOZ_UTF16("Title"), michael@0: getter_Copies(windowTitle)); michael@0: mStringBundle->GetStringFromName(messageName, michael@0: getter_Copies(message)); michael@0: if (showAgainName) { michael@0: mStringBundle->GetStringFromName(showAgainName, michael@0: getter_Copies(alertMe)); michael@0: } michael@0: mStringBundle->GetStringFromName(MOZ_UTF16("Continue"), michael@0: getter_Copies(cont)); michael@0: // alertMe is allowed to be null michael@0: if (!windowTitle || !message || !cont) return NS_ERROR_FAILURE; michael@0: michael@0: // Replace # characters with newlines to lay out the dialog. michael@0: char16_t* msgchars = message.BeginWriting(); michael@0: michael@0: uint32_t i = 0; michael@0: for (i = 0; msgchars[i] != '\0'; i++) { michael@0: if (msgchars[i] == '#') { michael@0: msgchars[i] = '\n'; michael@0: } michael@0: } michael@0: michael@0: int32_t buttonPressed; michael@0: michael@0: rv = prompt->ConfirmEx(windowTitle, michael@0: message, michael@0: (nsIPrompt::BUTTON_TITLE_IS_STRING * nsIPrompt::BUTTON_POS_0) + michael@0: (nsIPrompt::BUTTON_TITLE_CANCEL * nsIPrompt::BUTTON_POS_1), michael@0: cont, michael@0: nullptr, michael@0: nullptr, michael@0: alertMe, michael@0: &prefValue, michael@0: &buttonPressed); michael@0: michael@0: if (NS_FAILED(rv)) return rv; michael@0: michael@0: *_result = (buttonPressed != 1); michael@0: if (*_result) { michael@0: // For confirmation dialogs, the clickthrough constant is 1 more michael@0: // than the constant for the dialog. michael@0: mozilla::Telemetry::Accumulate(mozilla::Telemetry::SECURITY_UI, aBucket + 1); michael@0: } michael@0: michael@0: if (!prefValue && prefName) { michael@0: mPrefBranch->SetBoolPref(prefName, false); michael@0: } else if (prefValue && showOnce) { michael@0: mPrefBranch->SetBoolPref(showOncePref.get(), false); michael@0: } michael@0: michael@0: return rv; michael@0: } michael@0: