diff --git a/caps/src/nsScriptSecurityManager.cpp b/caps/src/nsScriptSecurityManager.cpp index 491dd7c20346..4ad63dd5b376 100644 --- a/caps/src/nsScriptSecurityManager.cpp +++ b/caps/src/nsScriptSecurityManager.cpp @@ -2141,6 +2141,7 @@ nsScriptSecurityManager::CheckConfirmDialog(JSContext* cx, nsIPrincipal* aPrinci PRInt32 buttonPressed = 1; // If the user exits by clicking the close box, assume No (button 1) rv = prompter->ConfirmEx(title.get(), message.get(), + (nsIPrompt::BUTTON_DELAY_ENABLE) + (nsIPrompt::BUTTON_POS_1_DEFAULT) + (nsIPrompt::BUTTON_TITLE_YES * nsIPrompt::BUTTON_POS_0) + (nsIPrompt::BUTTON_TITLE_NO * nsIPrompt::BUTTON_POS_1), diff --git a/embedding/components/windowwatcher/public/nsIPromptService.idl b/embedding/components/windowwatcher/public/nsIPromptService.idl index bf85da3bb4e2..ee31ccbdba2f 100644 --- a/embedding/components/windowwatcher/public/nsIPromptService.idl +++ b/embedding/components/windowwatcher/public/nsIPromptService.idl @@ -133,7 +133,10 @@ interface nsIPromptService : nsISupports const unsigned long BUTTON_POS_0_DEFAULT = 0 << 24; const unsigned long BUTTON_POS_1_DEFAULT = 1 << 24; - const unsigned long BUTTON_POS_2_DEFAULT = 2 << 24; + const unsigned long BUTTON_POS_2_DEFAULT = 2 << 24; + + /* used for security dialogs, buttons are initially disabled */ + const unsigned long BUTTON_DELAY_ENABLE = 1 << 26; const unsigned long STD_OK_CANCEL_BUTTONS = (BUTTON_TITLE_OK * BUTTON_POS_0) + (BUTTON_TITLE_CANCEL * BUTTON_POS_1); diff --git a/embedding/components/windowwatcher/public/nsPIPromptService.idl b/embedding/components/windowwatcher/public/nsPIPromptService.idl index 28ecc6560b90..4c8c42d6b7bc 100644 --- a/embedding/components/windowwatcher/public/nsPIPromptService.idl +++ b/embedding/components/windowwatcher/public/nsPIPromptService.idl @@ -52,7 +52,8 @@ interface nsPIPromptService : nsISupports eButton0Text=8, eButton1Text=9, eButton2Text=10, eButton3Text=11, eDialogTitle=12}; enum {eButtonPressed=0, eCheckboxState=1, eNumberButtons=2, - eNumberEditfields=3, eEditField1Password=4, eDefaultButton=5}; + eNumberEditfields=3, eEditField1Password=4, eDefaultButton=5, + eDelayButtonEnable=6}; %} void doDialog(in nsIDOMWindow aParent, in nsIDialogParamBlock aParamBlock, in string aChromeURL); diff --git a/embedding/components/windowwatcher/src/nsPromptService.cpp b/embedding/components/windowwatcher/src/nsPromptService.cpp index 22042f95a9dd..51891f27f6c3 100644 --- a/embedding/components/windowwatcher/src/nsPromptService.cpp +++ b/embedding/components/windowwatcher/src/nsPromptService.cpp @@ -291,6 +291,8 @@ nsPromptService::ConfirmEx(nsIDOMWindow *parent, #define BUTTON_DEFAULT_MASK 0x03000000 block->SetInt(eDefaultButton, (buttonFlags & BUTTON_DEFAULT_MASK) >> 24); + block->SetInt(eDelayButtonEnable, buttonFlags & BUTTON_DELAY_ENABLE); + PRInt32 numberButtons = 0; for (int i = 0; i < 3; i++) { diff --git a/modules/libpref/src/init/all.js b/modules/libpref/src/init/all.js index 0c6b8c82140d..fecc31d7d50e 100644 --- a/modules/libpref/src/init/all.js +++ b/modules/libpref/src/init/all.js @@ -645,6 +645,8 @@ pref("security.directory", ""); pref("signed.applets.codebase_principal_support", false); pref("security.checkloaduri", true); pref("security.xpconnect.plugin.unrestricted", true); +// security-sensitive dialogs should delay focus. In milliseconds. +pref("security.dialog_enable_delay", 2000); // Modifier key prefs: default to Windows settings, // menu access key = alt, accelerator key = control. diff --git a/netwerk/base/public/nsIPrompt.idl b/netwerk/base/public/nsIPrompt.idl index d5087c7b2d29..97188cc8f704 100644 --- a/netwerk/base/public/nsIPrompt.idl +++ b/netwerk/base/public/nsIPrompt.idl @@ -87,8 +87,11 @@ interface nsIPrompt : nsISupports const unsigned long BUTTON_POS_0_DEFAULT = 0 << 24; const unsigned long BUTTON_POS_1_DEFAULT = 1 << 24; - const unsigned long BUTTON_POS_2_DEFAULT = 2 << 24; - + const unsigned long BUTTON_POS_2_DEFAULT = 2 << 24; + + /* used for security dialogs, buttons are initially disabled */ + const unsigned long BUTTON_DELAY_ENABLE = 1 << 26; + const unsigned long STD_OK_CANCEL_BUTTONS = (BUTTON_TITLE_OK * BUTTON_POS_0) + (BUTTON_TITLE_CANCEL * BUTTON_POS_1); diff --git a/xpfe/global/resources/content/commonDialog.js b/xpfe/global/resources/content/commonDialog.js index eae83751020a..e4924db91f73 100644 --- a/xpfe/global/resources/content/commonDialog.js +++ b/xpfe/global/resources/content/commonDialog.js @@ -163,27 +163,56 @@ function commonDialogOnLoad() if (gCommonDialogParam.GetInt(3) == 0) // If no text fields { + var dButton; var defaultButton = gCommonDialogParam.GetInt(5); switch (defaultButton) { case 3: - document.documentElement.getButton("extra2").focus(); + dButton = document.documentElement.getButton("extra2"); break; case 2: - document.documentElement.getButton("extra1").focus(); + dButton = document.documentElement.getButton("extra1"); break; case 1: - document.documentElement.getButton("cancel").focus(); + dButton = document.documentElement.getButton("cancel"); break; default: case 0: - document.documentElement.getButton("accept").focus(); + dButton = document.documentElement.getButton("accept"); break; } + // move the default attribute and focus from the accept button + // to the one specified in the dialog params + document.documentElement.getButton("accept").setAttribute("default",false); + dButton.setAttribute("default", true); + dButton.focus(); + } + + if (gCommonDialogParam.GetInt(6) != 0) // delay button enable + { + var delayInterval = 2000; + try { + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + delayInterval = prefs.getIntPref("security.dialog_enable_delay"); + } catch (e) {} + + document.documentElement.getButton("accept").disabled = true; + document.documentElement.getButton("extra1").disabled = true; + document.documentElement.getButton("extra2").disabled = true; + + setTimeout(commonDialogReenableButtons, delayInterval); } getAttention(); } +function commonDialogReenableButtons() +{ + document.documentElement.getButton("accept").disabled = false; + document.documentElement.getButton("extra1").disabled = false; + document.documentElement.getButton("extra2").disabled = false; +} + function initTextbox(aName, aLabelIndex, aValueIndex, aAlwaysLabel) { unHideElementById(aName+"Container"); diff --git a/xpinstall/res/content/institems.js b/xpinstall/res/content/institems.js index d6d0d88d0950..d82607ab065d 100644 --- a/xpinstall/res/content/institems.js +++ b/xpinstall/res/content/institems.js @@ -99,9 +99,26 @@ function onLoad() // Move default+focus from |accept| to |cancel| button. var aButton = document.documentElement.getButton("accept"); aButton.setAttribute("default", false); + aButton.setAttribute("label", gBundle.getString("OK")); + aButton.setAttribute("disabled", true); + aButton = document.documentElement.getButton("cancel"); aButton.focus(); aButton.setAttribute("default", true); + + // start timer to re-enable buttons + var delayInterval = 2000; + try { + var prefs = Components.classes["@mozilla.org/preferences-service;1"] + .getService(Components.interfaces.nsIPrefBranch); + delayInterval = prefs.getIntPref("security.dialog_enable_delay"); + } catch (e) {} + setTimeout(reenableInstallButtons, delayInterval); +} + +function reenableInstallButtons() +{ + document.documentElement.getButton("accept").setAttribute("disabled", false); } function onAccept()