зеркало из https://github.com/mozilla/gecko-dev.git
Bug 380637, add a general preference to prevent pages from overriding keyboard shortcuts. If a key doesn't specify the reserved attribute, this preference will be used, r=felipe
This commit is contained in:
Родитель
7d3551d146
Коммит
9bd9459ef2
|
@ -429,6 +429,7 @@ pref("permissions.default.camera", 0);
|
|||
pref("permissions.default.microphone", 0);
|
||||
pref("permissions.default.geo", 0);
|
||||
pref("permissions.default.desktop-notification", 0);
|
||||
pref("permissions.default.shortcuts", 0);
|
||||
|
||||
// handle links targeting new windows
|
||||
// 1=current window/tab, 2=new window, 3=new tab in most recent window
|
||||
|
|
|
@ -5,6 +5,7 @@ support-files=
|
|||
|
||||
[browser_canvas_fingerprinting_resistance.js]
|
||||
[browser_permissions.js]
|
||||
[browser_reservedkey.js]
|
||||
[browser_temporary_permissions.js]
|
||||
support-files =
|
||||
temporary_permissions_subframe.html
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
add_task(async function test_reserved_shortcuts() {
|
||||
/* eslint-disable no-unsanitized/property */
|
||||
let keyset = `<keyset>
|
||||
<key id='kt_reserved' modifiers='shift' key='O' reserved='true' count='0'
|
||||
oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
|
||||
<key id='kt_notreserved' modifiers='shift' key='P' reserved='false' count='0'
|
||||
oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
|
||||
<key id='kt_reserveddefault' modifiers='shift' key='Q' count='0'
|
||||
oncommand='this.setAttribute("count", Number(this.getAttribute("count")) + 1)'/>
|
||||
</keyset>`;
|
||||
|
||||
let container = document.createElement("box");
|
||||
container.innerHTML = keyset;
|
||||
document.documentElement.appendChild(container);
|
||||
/* eslint-enable no-unsanitized/property */
|
||||
|
||||
const pageUrl = "data:text/html,<body onload='document.body.firstChild.focus();'><div onkeydown='event.preventDefault();' tabindex=0>Test</div></body>";
|
||||
let tab = await BrowserTestUtils.openNewForegroundTab(gBrowser, pageUrl);
|
||||
|
||||
EventUtils.synthesizeKey("O", { shiftKey: true });
|
||||
EventUtils.synthesizeKey("P", { shiftKey: true });
|
||||
EventUtils.synthesizeKey("Q", { shiftKey: true });
|
||||
|
||||
is(document.getElementById("kt_reserved").getAttribute("count"), "1", "reserved='true' with preference off");
|
||||
is(document.getElementById("kt_notreserved").getAttribute("count"), "0", "reserved='false' with preference off");
|
||||
is(document.getElementById("kt_reserveddefault").getAttribute("count"), "0", "default reserved with preference off");
|
||||
|
||||
// Now try with reserved shortcut key handling enabled.
|
||||
await new Promise(r => {
|
||||
SpecialPowers.pushPrefEnv({"set": [["permissions.default.shortcuts", 2]]}, r);
|
||||
});
|
||||
|
||||
EventUtils.synthesizeKey("O", { shiftKey: true });
|
||||
EventUtils.synthesizeKey("P", { shiftKey: true });
|
||||
EventUtils.synthesizeKey("Q", { shiftKey: true });
|
||||
|
||||
is(document.getElementById("kt_reserved").getAttribute("count"), "2", "reserved='true' with preference on");
|
||||
is(document.getElementById("kt_notreserved").getAttribute("count"), "0", "reserved='false' with preference on");
|
||||
is(document.getElementById("kt_reserveddefault").getAttribute("count"), "1", "default reserved with preference on");
|
||||
|
||||
document.documentElement.removeChild(container);
|
||||
|
||||
await BrowserTestUtils.removeTab(tab);
|
||||
});
|
|
@ -93,7 +93,7 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
|
|||
uint32_t aLineNumber)
|
||||
: mHandlerText(nullptr),
|
||||
mLineNumber(aLineNumber),
|
||||
mReserved(false),
|
||||
mReserved(XBLReservedKey_False),
|
||||
mNextHandler(nullptr),
|
||||
mPrototypeBinding(aBinding)
|
||||
{
|
||||
|
@ -104,7 +104,7 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(const char16_t* aEvent,
|
|||
aGroup, aPreventDefault, aAllowUntrusted);
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement, bool aReserved)
|
||||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement, XBLReservedKey aReserved)
|
||||
: mHandlerElement(nullptr),
|
||||
mLineNumber(0),
|
||||
mReserved(aReserved),
|
||||
|
@ -120,7 +120,7 @@ nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsIContent* aHandlerElement, bool a
|
|||
nsXBLPrototypeHandler::nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding)
|
||||
: mHandlerText(nullptr),
|
||||
mLineNumber(0),
|
||||
mReserved(false),
|
||||
mReserved(XBLReservedKey_False),
|
||||
mNextHandler(nullptr),
|
||||
mPrototypeBinding(aBinding)
|
||||
{
|
||||
|
|
|
@ -55,6 +55,15 @@ class KeyboardShortcut;
|
|||
#define NS_PHASE_TARGET 2
|
||||
#define NS_PHASE_BUBBLING 3
|
||||
|
||||
// Values of the reserved attribute. When unset, the default value depends on
|
||||
// the permissions.default.shortcuts preference.
|
||||
enum XBLReservedKey : uint8_t
|
||||
{
|
||||
XBLReservedKey_False = 0,
|
||||
XBLReservedKey_True = 1,
|
||||
XBLReservedKey_Unset = 2,
|
||||
};
|
||||
|
||||
class nsXBLPrototypeHandler
|
||||
{
|
||||
typedef mozilla::IgnoreModifierState IgnoreModifierState;
|
||||
|
@ -74,7 +83,7 @@ public:
|
|||
uint32_t aLineNumber);
|
||||
|
||||
// This constructor is used only by XUL key handlers (e.g., <key>)
|
||||
explicit nsXBLPrototypeHandler(nsIContent* aKeyElement, bool aReserved);
|
||||
explicit nsXBLPrototypeHandler(nsIContent* aKeyElement, XBLReservedKey aReserved);
|
||||
|
||||
// This constructor is used for handlers loaded from the cache
|
||||
explicit nsXBLPrototypeHandler(nsXBLPrototypeBinding* aBinding);
|
||||
|
@ -118,7 +127,7 @@ public:
|
|||
|
||||
uint8_t GetPhase() { return mPhase; }
|
||||
uint8_t GetType() { return mType; }
|
||||
bool GetIsReserved() { return mReserved; }
|
||||
XBLReservedKey GetIsReserved() { return mReserved; }
|
||||
|
||||
nsXBLPrototypeHandler* GetNextHandler() { return mNextHandler; }
|
||||
void SetNextHandler(nsXBLPrototypeHandler* aHandler) { mNextHandler = aHandler; }
|
||||
|
@ -233,7 +242,7 @@ protected:
|
|||
// stores whether or not we're a key code or char code.
|
||||
// For mouse events, stores the clickCount.
|
||||
|
||||
bool mReserved; // <key> is reserved for chrome. Not used by handlers.
|
||||
XBLReservedKey mReserved; // <key> is reserved for chrome. Not used by handlers.
|
||||
|
||||
int32_t mKeyMask; // Which modifier keys this event handler expects to have down
|
||||
// in order to be matched.
|
||||
|
|
|
@ -211,8 +211,16 @@ BuildHandlerChain(nsIContent* aContent, nsXBLPrototypeHandler** aResult)
|
|||
valKey.IsEmpty() && valCharCode.IsEmpty() && valKeyCode.IsEmpty())
|
||||
continue;
|
||||
|
||||
bool reserved = key->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
|
||||
nsGkAtoms::_true, eCaseMatters);
|
||||
// reserved="pref" is the default for <key> elements.
|
||||
XBLReservedKey reserved = XBLReservedKey_Unset;
|
||||
if (key->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
|
||||
nsGkAtoms::_true, eCaseMatters)) {
|
||||
reserved = XBLReservedKey_True;
|
||||
} else if (key->AttrValueIs(kNameSpaceID_None, nsGkAtoms::reserved,
|
||||
nsGkAtoms::_false, eCaseMatters)) {
|
||||
reserved = XBLReservedKey_False;
|
||||
}
|
||||
|
||||
nsXBLPrototypeHandler* handler = new nsXBLPrototypeHandler(key, reserved);
|
||||
|
||||
handler->SetNextHandler(*aResult);
|
||||
|
@ -725,7 +733,12 @@ nsXBLWindowKeyHandler::WalkHandlersAndExecute(
|
|||
continue;
|
||||
}
|
||||
|
||||
bool isReserved = handler->GetIsReserved();
|
||||
bool isReserved = handler->GetIsReserved() == XBLReservedKey_True;
|
||||
if (handler->GetIsReserved() == XBLReservedKey_Unset &&
|
||||
Preferences::GetInt("permissions.default.shortcuts") == 2) {
|
||||
isReserved = true;
|
||||
}
|
||||
|
||||
if (aOutReservedForChrome) {
|
||||
*aOutReservedForChrome = isReserved;
|
||||
}
|
||||
|
|
|
@ -135,7 +135,8 @@ static const char* kPermissionsWithDefaults[] = {
|
|||
"camera",
|
||||
"microphone",
|
||||
"geo",
|
||||
"desktop-notification"
|
||||
"desktop-notification",
|
||||
"shortcuts"
|
||||
};
|
||||
|
||||
// NOTE: nullptr can be passed as aType - if it is this function will return
|
||||
|
|
Загрузка…
Ссылка в новой задаче