Bug 944397 - Process SetInputMethodActive request until content window is ready. r=fabrice

--HG--
extra : rebase_source : 330dbbe63646b2b08a3b6eded27c85714361044a
This commit is contained in:
Yuan Xulei 2013-12-20 16:01:18 +08:00
parent 3e8bb4f9f5
commit 397e0cf345
4 changed files with 131 additions and 3 deletions

View File

@ -60,7 +60,7 @@ let CERTIFICATE_ERROR_PAGE_PREF = 'security.alternate_certificate_error_page';
let NS_ERROR_MODULE_BASE_OFFSET = 0x45;
let NS_ERROR_MODULE_SECURITY= 21;
function NS_ERROR_GET_MODULE(err) {
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff)
return ((((err) >> 16) - NS_ERROR_MODULE_BASE_OFFSET) & 0x1fff);
}
function NS_ERROR_GET_CODE(err) {
@ -82,7 +82,7 @@ let SSL_ERROR_BAD_CERT_DOMAIN = (SSL_ERROR_BASE + 12);
function getErrorClass(errorCode) {
let NSPRCode = -1 * NS_ERROR_GET_CODE(errorCode);
switch (NSPRCode) {
case SEC_ERROR_UNKNOWN_ISSUER:
case SEC_ERROR_CA_CERT_INVALID:
@ -129,6 +129,9 @@ function BrowserElementChild() {
this._nextPaintHandler = null;
this._isContentWindowCreated = false;
this._pendingSetInputMethodActive = [];
this._init();
};
@ -566,6 +569,11 @@ BrowserElementChild.prototype = {
this._addMozAfterPaintHandler(function () {
sendAsyncMsg('documentfirstpaint');
});
this._isContentWindowCreated = true;
// Handle pending SetInputMethodActive request.
while (this._pendingSetInputMethodActive.length > 0) {
this._recvSetInputMethodActive(this._pendingSetInputMethodActive.shift());
}
}
},
@ -904,6 +912,17 @@ BrowserElementChild.prototype = {
_recvSetInputMethodActive: function(data) {
let msgData = { id: data.json.id };
if (!this._isContentWindowCreated) {
if (data.json.args.isActive) {
// To activate the input method, we should wait before the content
// window is ready.
this._pendingSetInputMethodActive.push(data);
return;
}
sendAsyncMsg('got-set-input-method-active', msgData);
msgData.successRv = null;
return;
}
// Unwrap to access webpage content.
let nav = XPCNativeWrapper.unwrap(content.document.defaultView.navigator);
if (nav.mozInputMethod) {
@ -977,7 +996,7 @@ BrowserElementChild.prototype = {
return;
}
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
if (NS_ERROR_GET_MODULE(status) == NS_ERROR_MODULE_SECURITY &&
getErrorClass(status) == Ci.nsINSSErrorsService.ERROR_CLASS_BAD_CERT) {
// XXX Is there a point firing the event if the error page is not

View File

@ -0,0 +1,18 @@
<html>
<body>
<script>
var im = navigator.mozInputMethod;
if (im) {
// Automatically append location hash to current input field.
im.oninputcontextchange = function() {
var ctx = im.inputcontext;
if (ctx) {
intervalId = setTimeout(function() {
ctx.replaceSurroundingText(location.hash);
}, 0);
}
};
}
</script>
</body>
</html>

View File

@ -2,6 +2,8 @@
support-files =
inputmethod_common.js
file_test_app.html
file_inputmethod.html
[test_basic.html]
[test_bug944397.html]

View File

@ -0,0 +1,89 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=944397
-->
<head>
<title>Basic test for InputMethod API.</title>
<script type="application/javascript;version=1.7" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="application/javascript;version=1.7" src="inputmethod_common.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=944397">Mozilla Bug 944397</a>
<input type="text" />
<p id="display"></p>
<pre id="test">
<script class="testbody" type="application/javascript;version=1.7">
inputmethod_setup(function() {
runTest();
});
// The frame script running in file_test_app.html.
function appFrameScript() {
let input = content.document.getElementById('test-input');
input.oninput = function() {
sendAsyncMessage('test:InputMethod:oninput', {});
};
}
function runTest() {
var timeoutId = null;
// Create an app frame to recieve keyboard inputs.
let app = document.createElement('iframe');
app.src = 'file_test_app.html';
app.setAttribute('mozbrowser', true);
document.body.appendChild(app);
app.addEventListener('mozbrowserloadend', function() {
let mm = SpecialPowers.getBrowserFrameMessageManager(app);
mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false);
mm.addMessageListener("test:InputMethod:oninput", function() {
ok(true, 'Keyboard input was received.');
clearTimeout(timeoutId);
inputmethod_cleanup();
});
});
// Create a browser frame to load the input method app.
let keyboard = document.createElement('iframe');
keyboard.setAttribute('mozbrowser', true);
document.body.appendChild(keyboard);
let path = location.pathname;
let imeUrl = location.protocol + '//' + location.host +
path.substring(0, path.lastIndexOf('/')) +
'/file_inputmethod.html#data';
SpecialPowers.pushPermissions([{
type: 'input',
allow: true,
context: imeUrl
}], function() {
let req = keyboard.setInputMethodActive(true);
req.onsuccess = function() {
ok(true, 'setInputMethodActive succeeded.');
timeoutId = setTimeout(function() {
inputmethod_cleanup();
ok(false, 'Failed to generate keyboard input.');
}, 60000);
};
req.onerror = function() {
ok(false, 'setInputMethodActive failed: ' + this.error.name);
inputmethod_cleanup();
};
// Loads the input method app to the browser frame after a delay.
setTimeout(function() {
keyboard.src = imeUrl;
}, 100);
});
}
</script>
</pre>
</body>
</html>