diff --git a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js index e88d7bde446e..d4bfa0aabfec 100644 --- a/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js +++ b/dom/browser-element/mochitest/browserElement_SetInputMethodActive.js @@ -9,6 +9,27 @@ SimpleTest.waitForExplicitFinish(); browserElementTestHelpers.setEnabledPref(true); browserElementTestHelpers.addPermission(); +// We'll need to get the appId from the current document, +// it's either SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID when +// we are not running inside an app (e.g. Firefox Desktop), +// or the appId of Mochitest app when we are running inside that app +// (e.g. Emulator). +var currentAppId = SpecialPowers.wrap(document).nodePrincipal.appId; +var inApp = + currentAppId !== SpecialPowers.Ci.nsIScriptSecurityManager.NO_APP_ID; +// We will also need the manifest URL and set it on iframes. +var currentAppManifestURL; + +if (inApp) { + let appsService = SpecialPowers.Cc["@mozilla.org/AppsService;1"] + .getService(SpecialPowers.Ci.nsIAppsService); + + currentAppManifestURL = appsService.getManifestURLByLocalId(currentAppId); +}; + +info('appId=' + currentAppId); +info('manifestURL=' + currentAppManifestURL); + function setup() { let appInfo = SpecialPowers.Cc['@mozilla.org/xre/app-info;1'] .getService(SpecialPowers.Ci.nsIXULAppInfo); @@ -27,110 +48,134 @@ function tearDown() { } function runTest() { - let path = location.pathname; - let imeUrl = location.protocol + '//' + location.host + - path.substring(0, path.lastIndexOf('/')) + - '/file_inputmethod.html'; - SpecialPowers.pushPermissions([{ - type: 'input', - allow: true, - context: { - url: imeUrl, - originAttributes: {inBrowser: true} - } - }], SimpleTest.waitForFocus.bind(SimpleTest, createFrames)); + createFrames(); } -var gFrames = []; +var gInputMethodFrames = []; var gInputFrame; function createFrames() { // Create two input method iframes. let loadendCount = 0; let countLoadend = function() { - if (this === gInputFrame) { - // The frame script running in the frame where the input is hosted. - let appFrameScript = function appFrameScript() { - let input = content.document.body.firstElementChild; - input.oninput = function() { - sendAsyncMessage('test:InputMethod:oninput', { - from: 'input', - value: this.value - }); - }; - - input.onblur = function() { - // "Expected" lost of focus since the test is finished. - if (input.value === '#0#1hello') { - return; - } - - sendAsyncMessage('test:InputMethod:oninput', { - from: 'input', - error: true, - value: 'Unexpected lost of focus on the input frame!' - }); - }; - - input.focus(); - } - - // Inject frame script to receive input. - let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame); - mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); - mm.addMessageListener("test:InputMethod:oninput", next); - } else { - ok(this.setInputMethodActive, 'Can access setInputMethodActive.'); - - // The frame script running in the input method frames. - - let appFrameScript = function appFrameScript() { - content.addEventListener("message", function(evt) { - sendAsyncMessage('test:InputMethod:imFrameMessage', { - from: 'im', - value: evt.data - }); - }); - } - - // Inject frame script to receive message. - let mm = SpecialPowers.getBrowserFrameMessageManager(this); - mm.loadFrameScript('data:,(' + appFrameScript.toString() + ')();', false); - mm.addMessageListener("test:InputMethod:imFrameMessage", next); - } - loadendCount++; if (loadendCount === 3) { - startTest(); + setPermissions(); + } + }; + + // Create an input field to receive string from input method iframes. + gInputFrame = document.createElement('iframe'); + gInputFrame.setAttribute('mozbrowser', 'true'); + gInputFrame.src = + 'data:text/html,' + + '

This is targetted mozbrowser frame.

'; + document.body.appendChild(gInputFrame); + gInputFrame.addEventListener('mozbrowserloadend', countLoadend); + + for (let i = 0; i < 2; i++) { + let frame = gInputMethodFrames[i] = document.createElement('iframe'); + frame.setAttribute('mozbrowser', 'true'); + if (currentAppManifestURL) { + frame.setAttribute('mozapp', currentAppManifestURL); } - }; + frame.src = 'file_empty.html#' + i; + document.body.appendChild(frame); + frame.addEventListener('mozbrowserloadend', countLoadend); + } + } - // Create an input field to receive string from input method iframes. - gInputFrame = document.createElement('iframe'); - gInputFrame.setAttribute('mozbrowser', 'true'); - gInputFrame.src = - 'data:text/html,' + - '

This is targetted mozbrowser frame.

'; - document.body.appendChild(gInputFrame); - gInputFrame.addEventListener('mozbrowserloadend', countLoadend); +function setPermissions() { + let permissions = [{ + type: 'input', + allow: true, + context: { + url: SimpleTest.getTestFileURL('/file_empty.html'), + originAttributes: { + appId: currentAppId, + inBrowser: true + } + } + }]; - for (let i = 0; i < 2; i++) { - let frame = gFrames[i] = document.createElement('iframe'); - gFrames[i].setAttribute('mozbrowser', 'true'); - // When the input method iframe is activated, it will send the URL - // hash to current focused element. We set different hash to each - // iframe so that iframes can be differentiated by their hash. - frame.src = 'file_inputmethod.html#' + i; - document.body.appendChild(frame); - frame.addEventListener('mozbrowserloadend', countLoadend); + if (inApp) { + // The current document would also need to be given access for IPC to + // recognize our permission (why)? + permissions.push({ + type: 'input', allow: true, context: document }); } + + SpecialPowers.pushPermissions(permissions, + SimpleTest.waitForFocus.bind(SimpleTest, startTest)); } -function startTest() { - // Set focus to the input field and wait for input methods' inputting. - SpecialPowers.DOMWindowUtils.focus(gInputFrame); + function startTest() { + // The frame script running in the frame where the input is hosted. + let appFrameScript = function appFrameScript() { + let input = content.document.body.firstElementChild; + input.oninput = function() { + sendAsyncMessage('test:InputMethod:oninput', { + from: 'input', + value: this.value + }); + }; - let req0 = gFrames[0].setInputMethodActive(true); + input.onblur = function() { + // "Expected" lost of focus since the test is finished. + if (input.value === '#0#1hello') { + return; + } + + sendAsyncMessage('test:InputMethod:oninput', { + from: 'input', + error: true, + value: 'Unexpected lost of focus on the input frame!' + }); + }; + + input.focus(); + }; + + // Inject frame script to receive input. + let mm = SpecialPowers.getBrowserFrameMessageManager(gInputFrame); + mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); + mm.addMessageListener("test:InputMethod:oninput", next); + + gInputMethodFrames.forEach((frame) => { + ok(frame.setInputMethodActive, 'Can access setInputMethodActive.'); + + // The frame script running in the input method frames. + let appFrameScript = function appFrameScript() { + let im = content.navigator.mozInputMethod; + im.oninputcontextchange = function() { + let ctx = im.inputcontext; + // Report back to parent frame on status of ctx gotten. + // (A setTimeout() here to ensure this always happens after + // DOMRequest succeed.) + content.setTimeout(() => { + sendAsyncMessage('test:InputMethod:imFrameMessage', { + from: 'im', + value: content.location.hash + !!ctx + }); + }); + + // If there is a context, send out the hash. + if (ctx) { + ctx.replaceSurroundingText(content.location.hash); + } + }; + }; + + // Inject frame script to receive message. + let mm = SpecialPowers.getBrowserFrameMessageManager(frame); + mm.loadFrameScript('data:,(' + encodeURIComponent(appFrameScript.toString()) + ')();', false); + mm.addMessageListener("test:InputMethod:imFrameMessage", next); + }); + + // Set focus to the input field and wait for input methods' inputting. + SpecialPowers.DOMWindowUtils.focus(gInputFrame); + + let req0 = gInputMethodFrames[0].setInputMethodActive(true); req0.onsuccess = function() { ok(true, 'setInputMethodActive succeeded (0).'); }; @@ -203,14 +248,14 @@ function next(msg) { gCount++; - let req0 = gFrames[0].setInputMethodActive(false); + let req0 = gInputMethodFrames[0].setInputMethodActive(false); req0.onsuccess = function() { ok(true, 'setInputMethodActive succeeded (0).'); }; req0.onerror = function() { ok(false, 'setInputMethodActive failed (0): ' + this.error.name); }; - let req1 = gFrames[1].setInputMethodActive(true); + let req1 = gInputMethodFrames[1].setInputMethodActive(true); req1.onsuccess = function() { ok(true, 'setInputMethodActive succeeded (1).'); }; @@ -259,7 +304,7 @@ function next(msg) { // Receive the second input from the second iframe. // Deactive the second iframe. - let req3 = gFrames[1].setInputMethodActive(false); + let req3 = gInputMethodFrames[1].setInputMethodActive(false); req3.onsuccess = function() { ok(true, 'setInputMethodActive(false) succeeded (2).'); }; diff --git a/dom/browser-element/mochitest/file_inputmethod.html b/dom/browser-element/mochitest/file_inputmethod.html deleted file mode 100644 index b20be6b00d95..000000000000 --- a/dom/browser-element/mochitest/file_inputmethod.html +++ /dev/null @@ -1,20 +0,0 @@ - - - - -

This frame represents the input method frame.

- - diff --git a/dom/browser-element/mochitest/mochitest-oop.ini b/dom/browser-element/mochitest/mochitest-oop.ini index 9885661de8cf..795a4c58ddf2 100644 --- a/dom/browser-element/mochitest/mochitest-oop.ini +++ b/dom/browser-element/mochitest/mochitest-oop.ini @@ -76,8 +76,10 @@ skip-if = (toolkit == 'gonk') # Disabled on emulator. See bug 1144015 comment 8 [test_browserElement_oop_PrivateBrowsing.html] [test_browserElement_oop_PromptCheck.html] [test_browserElement_oop_PromptConfirm.html] +# Disabled on B2G Emulator because permission cannot be asserted in content process, +# need to fix either bug 1094055 or bug 1020135. [test_browserElement_oop_Proxy.html] -skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163 +skip-if = (toolkit == 'gonk') [test_browserElement_oop_PurgeHistory.html] [test_browserElement_oop_Reload.html] [test_browserElement_oop_ReloadPostRequest.html] @@ -89,7 +91,7 @@ skip-if = toolkit == 'android' || (toolkit == 'gonk' && !debug) #TIMED_OUT, bug skip-if = (toolkit == 'gonk') # Disabled on b2g due to bug 1097419 [test_browserElement_oop_SendEvent.html] [test_browserElement_oop_SetInputMethodActive.html] -skip-if = (os == "android") || (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163 +skip-if = (os == "android") [test_browserElement_oop_SetVisible.html] [test_browserElement_oop_SetVisibleFrames.html] [test_browserElement_oop_SetVisibleFrames2.html] diff --git a/dom/browser-element/mochitest/mochitest.ini b/dom/browser-element/mochitest/mochitest.ini index 4e84bb5e826a..065e2a564fc5 100644 --- a/dom/browser-element/mochitest/mochitest.ini +++ b/dom/browser-element/mochitest/mochitest.ini @@ -129,12 +129,10 @@ support-files = file_focus.html file_http_401_response.sjs file_http_407_response.sjs - file_inputmethod.html file_microdata.html file_microdata_bad_itemref.html file_microdata_itemref.html file_microformats.html - file_inputmethod.html file_post_request.html file_wyciwyg.html file_audio.html @@ -213,8 +211,10 @@ skip-if = (toolkit == 'gonk' && !debug) [test_browserElement_inproc_PrivateBrowsing.html] [test_browserElement_inproc_PromptCheck.html] [test_browserElement_inproc_PromptConfirm.html] +# Disabled on B2G Emulator because permission cannot be asserted in content process, +# need to fix either bug 1094055 or bug 1020135. [test_browserElement_inproc_Proxy.html] -skip-if = (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163 +skip-if = (toolkit == 'gonk') [test_browserElement_inproc_PurgeHistory.html] [test_browserElement_inproc_ReloadPostRequest.html] [test_browserElement_inproc_RemoveBrowserElement.html] @@ -226,7 +226,7 @@ skip-if = (toolkit == 'gonk') # Disabled on b2g due to bug 1097419 [test_browserElement_inproc_SendEvent.html] # The setInputMethodActive() tests will timed out on Android [test_browserElement_inproc_SetInputMethodActive.html] -skip-if = (os == "android") || (toolkit == 'gonk') # Disabled on B2G Emulator bug 1198163 +skip-if = (os == "android") [test_browserElement_inproc_SetVisible.html] [test_browserElement_inproc_SetVisibleFrames.html] [test_browserElement_inproc_SetVisibleFrames2.html] diff --git a/dom/inputmethod/Keyboard.jsm b/dom/inputmethod/Keyboard.jsm index 84d8db1c920a..feb774e6fd3c 100644 --- a/dom/inputmethod/Keyboard.jsm +++ b/dom/inputmethod/Keyboard.jsm @@ -199,7 +199,7 @@ this.Keyboard = { } if (!Utils.checkPermissionForMM(mm, permName)) { dump("Keyboard.jsm: Message " + msg.name + - " from a content process with no '" + permName + "' privileges."); + " from a content process with no '" + permName + "' privileges.\n"); return; } }