зеркало из https://github.com/mozilla/pjs.git
Bug 757486 - Allow browser frames to bubble some whitelisted key events. r=jlebar
--HG-- extra : rebase_source : 5d8e8c2a4899f37bd01f4eab69238f48b0a2ddeb
This commit is contained in:
Родитель
b565b9e429
Коммит
81fb734285
|
@ -9,6 +9,15 @@ let Ci = Components.interfaces;
|
|||
let Cc = Components.classes;
|
||||
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
|
||||
|
||||
// Event whitelisted for bubbling.
|
||||
let whitelistedEvents = [
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
|
||||
];
|
||||
|
||||
function debug(msg) {
|
||||
//dump("BrowserElementChild - " + msg + "\n");
|
||||
}
|
||||
|
@ -32,6 +41,8 @@ function sendSyncMsg(msg, data) {
|
|||
* the parent process.
|
||||
*/
|
||||
|
||||
var global = this;
|
||||
|
||||
function BrowserElementChild() {
|
||||
this._init();
|
||||
};
|
||||
|
@ -57,7 +68,7 @@ BrowserElementChild.prototype = {
|
|||
// Get the app manifest from the parent, if our frame has one.
|
||||
let appManifestURL = sendSyncMsg('get-mozapp-manifest-url')[0];
|
||||
let windowUtils = content.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Components.interfaces.nsIDOMWindowUtils);
|
||||
.getInterface(Ci.nsIDOMWindowUtils);
|
||||
|
||||
if (!!appManifestURL) {
|
||||
windowUtils.setIsApp(true);
|
||||
|
@ -78,6 +89,21 @@ BrowserElementChild.prototype = {
|
|||
|
||||
addMessageListener("browser-element-api:get-screenshot",
|
||||
this._recvGetScreenshot.bind(this));
|
||||
|
||||
let els = Cc["@mozilla.org/eventlistenerservice;1"]
|
||||
.getService(Ci.nsIEventListenerService);
|
||||
|
||||
// We are using the system group for those events so if something in the
|
||||
// content called .stopPropagation() this will still be called.
|
||||
els.addSystemEventListener(global, 'keydown',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keypress',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
els.addSystemEventListener(global, 'keyup',
|
||||
this._keyEventHandler.bind(this),
|
||||
/* useCapture = */ true);
|
||||
},
|
||||
|
||||
_titleChangedHandler: function(e) {
|
||||
|
@ -129,6 +155,16 @@ BrowserElementChild.prototype = {
|
|||
});
|
||||
},
|
||||
|
||||
_keyEventHandler: function(e) {
|
||||
if (whitelistedEvents.indexOf(e.keyCode) != -1 && !e.defaultPrevented) {
|
||||
sendAsyncMsg('keyevent', {
|
||||
type: e.type,
|
||||
code: e.keyCode,
|
||||
charCode: e.charCode,
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
// The docShell keeps a weak reference to the progress listener, so we need
|
||||
// to keep a strong ref to it ourselves.
|
||||
_progressListener: {
|
||||
|
|
|
@ -106,6 +106,7 @@ BrowserElementParent.prototype = {
|
|||
addMessageListener("titlechange", this._fireEventFromMsg);
|
||||
addMessageListener("iconchange", this._fireEventFromMsg);
|
||||
addMessageListener("get-mozapp-manifest-url", this._sendMozAppManifestURL);
|
||||
addMessageListener("keyevent", this._fireKeyEvent);
|
||||
mm.addMessageListener('browser-element-api:got-screenshot',
|
||||
this._recvGotScreenshot.bind(this));
|
||||
|
||||
|
@ -164,6 +165,18 @@ BrowserElementParent.prototype = {
|
|||
return req;
|
||||
},
|
||||
|
||||
_fireKeyEvent: function(frameElement, data) {
|
||||
let win = frameElement.ownerDocument.defaultView;
|
||||
let evt = frameElement.ownerDocument.createEvent("KeyboardEvent");
|
||||
|
||||
evt.initKeyEvent(data.json.type, true, true, win,
|
||||
false, false, false, false, // modifiers
|
||||
data.json.keyCode,
|
||||
data.json.charCode);
|
||||
|
||||
frameElement.dispatchEvent(evt);
|
||||
},
|
||||
|
||||
observe: function(subject, topic, data) {
|
||||
switch(topic) {
|
||||
case 'app-startup':
|
||||
|
|
|
@ -14,6 +14,7 @@ include $(topsrcdir)/config/rules.mk
|
|||
|
||||
_TEST_FILES = \
|
||||
file_empty.html \
|
||||
file_focus.html \
|
||||
browserFrameHelpers.js \
|
||||
test_browserFrame1.html \
|
||||
test_browserFrame2.html \
|
||||
|
@ -24,6 +25,7 @@ _TEST_FILES = \
|
|||
test_browserFrame7.html \
|
||||
test_browserFrame8.html \
|
||||
test_browserFrame9.html \
|
||||
test_browserFrame_keyEvents.html \
|
||||
$(NULL)
|
||||
|
||||
libs:: $(_TEST_FILES)
|
||||
|
|
|
@ -106,6 +106,9 @@ const browserFrameHelpers = {
|
|||
'emptyPage2': 'http://example.org' +
|
||||
window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
|
||||
'/file_empty.html',
|
||||
'focusPage': 'http://example.org' +
|
||||
window.location.pathname.substring(0, window.location.pathname.lastIndexOf('/')) +
|
||||
'/file_focus.html',
|
||||
};
|
||||
|
||||
browserFrameHelpers.origEnabledPref = browserFrameHelpers.getEnabledPref();
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
<html>
|
||||
<body>
|
||||
|
||||
Aloha! My URL is <span id='url'></span>.
|
||||
<script>
|
||||
document.getElementById('url').innerHTML = window.location;
|
||||
</script>
|
||||
|
||||
<script>
|
||||
// The input element is getting synthesized key events and will prevent
|
||||
// default on the first ESC keydown event.
|
||||
|
||||
var alreadyBlocked = false;
|
||||
|
||||
addEventListener('keydown', function(e) {
|
||||
if (e.keyCode == Components.interfaces.nsIDOMKeyEvent.DOM_VK_ESCAPE &&
|
||||
alreadyBlocked == false) {
|
||||
alreadyBlocked = true;
|
||||
e.preventDefault();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
|
|
@ -0,0 +1,99 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html>
|
||||
<!--
|
||||
https://bugzilla.mozilla.org/show_bug.cgi?id=757486
|
||||
-->
|
||||
<head>
|
||||
<title>Test for Bug 757486</title>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="application/javascript" src="/tests/SimpleTest/EventUtils.js"></script>
|
||||
<script type="application/javascript" src="browserFrameHelpers.js"></script>
|
||||
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
|
||||
</head>
|
||||
<body>
|
||||
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=757486">Mozilla Bug 757486</a>
|
||||
|
||||
<!--
|
||||
Test that an iframe with the |mozbrowser| attribute does bubble some
|
||||
whitelisted key events.
|
||||
-->
|
||||
|
||||
<script type="application/javascript;version=1.7">
|
||||
"use strict";
|
||||
|
||||
let Ci = Components.interfaces;
|
||||
|
||||
let whitelistedEvents = [
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_ESCAPE, // Back button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_CONTEXT_MENU,
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_F5, // Search button.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_UP, // Volume up.
|
||||
Ci.nsIDOMKeyEvent.DOM_VK_PAGE_DOWN // Volume down.
|
||||
];
|
||||
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
browserFrameHelpers.setEnabledPref(true);
|
||||
browserFrameHelpers.addToWhitelist();
|
||||
browserFrameHelpers.setOOPDisabledPref(true); // this is breaking the autofocus.
|
||||
|
||||
var iframe = document.createElement('iframe');
|
||||
iframe.mozbrowser = true;
|
||||
iframe.src = browserFrameHelpers.focusPage;
|
||||
document.body.appendChild(iframe);
|
||||
|
||||
// Number of expected events at which point we will consider the test as done.
|
||||
var nbEvents = 15;
|
||||
|
||||
function eventHandler(e) {
|
||||
ok(((e.type == 'keydown' || e.type == 'keypress' || e.type == 'keyup') &&
|
||||
!e.defaultPrevented &&
|
||||
whitelistedEvents.indexOf(e.keyCode)),
|
||||
"[ " + e.type + "] Handled event should be a non prevented key event in the white list.");
|
||||
|
||||
nbEvents--;
|
||||
|
||||
if (nbEvents == 0) {
|
||||
browserFrameHelpers.restoreOriginalPrefs();
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
|
||||
if (nbEvents < 0) {
|
||||
ok(false, "got an unexpected event! " + e.type + " " + e.keyCode);
|
||||
SimpleTest.finish();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function runTest() {
|
||||
is(document.activeElement, iframe, "iframe should be focused");
|
||||
|
||||
addEventListener('keydown', eventHandler);
|
||||
addEventListener('keypress', eventHandler);
|
||||
addEventListener('keyup', eventHandler);
|
||||
|
||||
// Those event should not be received because not whitelisted.
|
||||
synthesizeKey("VK_A", {});
|
||||
synthesizeKey("VK_B", {});
|
||||
|
||||
// Those events should not be received because prevent default is called.
|
||||
synthesizeKey("VK_ESCAPE", {});
|
||||
|
||||
// Those events should be received.
|
||||
synthesizeKey("VK_F5", {}); // F5 key is going to be canceled by ESC key.
|
||||
synthesizeKey("VK_ESCAPE", {});
|
||||
synthesizeKey("VK_PAGE_UP", {}); // keypress is ignored because .preventDefault() will be called.
|
||||
synthesizeKey("VK_PAGE_DOWN", {}); // keypress is ignored because .preventDefault() will be called.
|
||||
synthesizeKey("VK_CONTEXT_MENU", {});
|
||||
}
|
||||
|
||||
SimpleTest.waitForFocus(function() {
|
||||
iframe.focus();
|
||||
SimpleTest.executeSoon(runTest);
|
||||
});
|
||||
|
||||
</script>
|
||||
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче