<!DOCTYPE HTML> <html> <!-- https://bugzilla.mozilla.org/show_bug.cgi?id=1201407 --> <head> <title>Test addinputrequest and removeinputrequest event</title> <script type="application/javascript;version=1.7" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script> <script type="application/javascript;version=1.7" src="inputmethod_common.js"></script> <link rel="stylesheet" type="text/css" href="chrome://mochikit/content/tests/SimpleTest/test.css"/> </head> <body> <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1201407">Mozilla Bug 1201407</a> <p id="display"></p> <pre id="test"> <script class="testbody" type="application/javascript;version=1.7"> let appFrameMM; let nextStep; function setupInputAppFrame() { info('setupInputAppFrame'); return new Promise((resolve, reject) => { let appFrameScript = function appFrameScript() { let im = content.navigator.mozInputMethod; addMessageListener('test:callAddInput', function() { im.addInput('foo', { launch_path: 'bar.html', name: 'Foo', description: 'foobar', types: ['text', 'password'] }) .then((r) => { sendAsyncMessage('test:resolved', { resolved: true, result: r }); }, (e) => { sendAsyncMessage('test:rejected', { rejected: true, error: e }); }); }); addMessageListener('test:callRemoveInput', function() { im.removeInput('foo') .then((r) => { sendAsyncMessage('test:resolved', { resolved: true, result: r }); }, (e) => { sendAsyncMessage('test:rejected', { rejected: true, error: e }); }); }); im.mgmt.onaddinputrequest = im.mgmt.onremoveinputrequest = function(evt) { sendAsyncMessage('test:appEvent', { type: evt.type }); }; content.document.body.textContent = 'I am a input app'; }; let path = location.pathname; let basePath = location.protocol + '//' + location.host + path.substring(0, path.lastIndexOf('/')); let imeUrl = basePath + '/file_blank.html'; let inputAppFrame = document.createElement('iframe'); inputAppFrame.setAttribute('mozbrowser', true); // FIXME: Bug 1270790 inputAppFrame.setAttribute('remote', true); inputAppFrame.src = imeUrl; document.body.appendChild(inputAppFrame); let mm = appFrameMM = SpecialPowers.getBrowserFrameMessageManager(inputAppFrame); inputAppFrame.addEventListener('mozbrowserloadend', function() { mm.addMessageListener('test:appEvent', function(msg) { ok(false, 'Input app should not receive ' + msg.data.type + ' event.'); }); mm.addMessageListener('test:resolved', function(msg) { nextStep && nextStep(msg.data); }); mm.addMessageListener('test:rejected', function(msg) { nextStep && nextStep(msg.data); }); mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); resolve(); }); }); } function Deferred() { this.promise = new Promise((res, rej) => { this.resolve = res; this.reject = rej; }); return this; } function deepAssertObject(obj, expectedObj, desc) { for (let prop in expectedObj) { if (typeof expectedObj[prop] === 'object') { deepAssertObject(obj[prop], expectedObj[prop], desc + '.' + prop); } else { is(obj[prop], expectedObj[prop], desc + '.' + prop); } } } function setupTestRunner() { let im = navigator.mozInputMethod; let d; let i = -1; nextStep = function next(evt) { i++; info('Step ' + i); switch (i) { case 0: appFrameMM.sendAsyncMessage('test:callAddInput'); break; case 1: is(evt.type, 'addinputrequest', 'evt.type'); deepAssertObject(evt.detail, { inputId: 'foo', manifestURL: null, // todo inputManifest: { launch_path: 'bar.html', name: 'Foo', description: 'foobar', types: ['text', 'password'] } }, 'detail'); d = new Deferred(); evt.detail.waitUntil(d.promise); evt.preventDefault(); Promise.resolve().then(next); break; case 2: d.resolve(); d = null; break; case 3: ok(evt.resolved, 'resolved'); appFrameMM.sendAsyncMessage('test:callAddInput'); break; case 4: is(evt.type, 'addinputrequest', 'evt.type'); d = new Deferred(); evt.detail.waitUntil(d.promise); evt.preventDefault(); Promise.resolve().then(next); break; case 5: d.reject('Foo Error'); d = null; break; case 6: ok(evt.rejected, 'rejected'); is(evt.error, 'Foo Error', 'rejected'); appFrameMM.sendAsyncMessage('test:callRemoveInput'); break; case 7: is(evt.type, 'removeinputrequest', 'evt.type'); deepAssertObject(evt.detail, { inputId: 'foo', manifestURL: null // todo }, 'detail'); d = new Deferred(); evt.detail.waitUntil(d.promise); evt.preventDefault(); Promise.resolve().then(next); break; case 8: d.resolve(); d = null; break; case 9: ok(evt.resolved, 'resolved'); appFrameMM.sendAsyncMessage('test:callRemoveInput'); break; case 10: is(evt.type, 'removeinputrequest', 'evt.type'); d = new Deferred(); evt.detail.waitUntil(d.promise); evt.preventDefault(); Promise.resolve().then(next); break; case 11: d.reject('Foo Error'); d = null; break; case 12: ok(evt.rejected, 'rejected'); is(evt.error, 'Foo Error', 'rejected'); inputmethod_cleanup(); break; default: ok(false, 'received extra call.'); inputmethod_cleanup(); break; } } im.mgmt.onaddinputrequest = im.mgmt.onremoveinputrequest = nextStep; } inputmethod_setup(function() { Promise.resolve() .then(() => setupTestRunner()) .then(() => setupInputAppFrame()) .then(() => nextStep()) .catch((e) => { ok(false, 'Error' + e.toString()); console.error(e); }); }); </script> </pre> </body> </html>