michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: /** michael@0: * Test for bug 549340. michael@0: * Test for browser.js::contentAreaClick() util. michael@0: * michael@0: * The test opens a new browser window, then replaces browser.js methods invoked michael@0: * by contentAreaClick with a mock function that tracks which methods have been michael@0: * called. michael@0: * Each sub-test synthesizes a mouse click event on links injected in content, michael@0: * the event is collected by a click handler that ensures that contentAreaClick michael@0: * correctly prevent default events, and follows the correct code path. michael@0: */ michael@0: michael@0: let gTests = [ michael@0: michael@0: { michael@0: desc: "Simple left click", michael@0: setup: function() {}, michael@0: clean: function() {}, michael@0: event: {}, michael@0: targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], michael@0: expectedInvokedMethods: [], michael@0: preventDefault: false, michael@0: }, michael@0: michael@0: { michael@0: desc: "Ctrl/Cmd left click", michael@0: setup: function() {}, michael@0: clean: function() {}, michael@0: event: { ctrlKey: true, michael@0: metaKey: true }, michael@0: targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], michael@0: expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: // The next test was once handling feedService.forcePreview(). Now it should michael@0: // just be like Alt click. michael@0: { michael@0: desc: "Shift+Alt left click", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("browser.altClickSave", true); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("browser.altClickSave"); michael@0: }, michael@0: event: { shiftKey: true, michael@0: altKey: true }, michael@0: targets: [ "commonlink", "maplink" ], michael@0: expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Shift+Alt left click on XLinks", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("browser.altClickSave", true); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("browser.altClickSave"); michael@0: }, michael@0: event: { shiftKey: true, michael@0: altKey: true }, michael@0: targets: [ "mathxlink", "svgxlink"], michael@0: expectedInvokedMethods: [ "saveURL" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Shift click", michael@0: setup: function() {}, michael@0: clean: function() {}, michael@0: event: { shiftKey: true }, michael@0: targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], michael@0: expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Alt click", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("browser.altClickSave", true); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("browser.altClickSave"); michael@0: }, michael@0: event: { altKey: true }, michael@0: targets: [ "commonlink", "maplink" ], michael@0: expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Alt click on XLinks", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("browser.altClickSave", true); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("browser.altClickSave"); michael@0: }, michael@0: event: { altKey: true }, michael@0: targets: [ "mathxlink", "svgxlink" ], michael@0: expectedInvokedMethods: [ "saveURL" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Panel click", michael@0: setup: function() {}, michael@0: clean: function() {}, michael@0: event: {}, michael@0: targets: [ "panellink" ], michael@0: expectedInvokedMethods: [ "urlSecurityCheck", "loadURI" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Simple middle click opentab", michael@0: setup: function() {}, michael@0: clean: function() {}, michael@0: event: { button: 1 }, michael@0: targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], michael@0: expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Simple middle click openwin", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("browser.tabs.opentabfor.middleclick", false); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick"); michael@0: }, michael@0: event: { button: 1 }, michael@0: targets: [ "commonlink", "mathxlink", "svgxlink", "maplink" ], michael@0: expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: { michael@0: desc: "Middle mouse paste", michael@0: setup: function() { michael@0: gPrefService.setBoolPref("middlemouse.contentLoadURL", true); michael@0: gPrefService.setBoolPref("general.autoScroll", false); michael@0: }, michael@0: clean: function() { michael@0: gPrefService.clearUserPref("middlemouse.contentLoadURL"); michael@0: gPrefService.clearUserPref("general.autoScroll"); michael@0: }, michael@0: event: { button: 1 }, michael@0: targets: [ "emptylink" ], michael@0: expectedInvokedMethods: [ "middleMousePaste" ], michael@0: preventDefault: true, michael@0: }, michael@0: michael@0: ]; michael@0: michael@0: // Array of method names that will be replaced in the new window. michael@0: let gReplacedMethods = [ michael@0: "middleMousePaste", michael@0: "urlSecurityCheck", michael@0: "loadURI", michael@0: "gatherTextUnder", michael@0: "saveURL", michael@0: "openLinkIn", michael@0: "getShortcutOrURIAndPostData", michael@0: ]; michael@0: michael@0: // Reference to the new window. michael@0: let gTestWin = null; michael@0: michael@0: // List of methods invoked by a specific call to contentAreaClick. michael@0: let gInvokedMethods = []; michael@0: michael@0: // The test currently running. michael@0: let gCurrentTest = null; michael@0: michael@0: function test() { michael@0: waitForExplicitFinish(); michael@0: michael@0: gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank"); michael@0: whenDelayedStartupFinished(gTestWin, function () { michael@0: info("Browser window opened"); michael@0: waitForFocus(function() { michael@0: info("Browser window focused"); michael@0: waitForFocus(function() { michael@0: info("Setting up browser..."); michael@0: setupTestBrowserWindow(); michael@0: info("Running tests..."); michael@0: executeSoon(runNextTest); michael@0: }, gTestWin.content, true); michael@0: }, gTestWin); michael@0: }); michael@0: } michael@0: michael@0: // Click handler used to steal click events. michael@0: let gClickHandler = { michael@0: handleEvent: function (event) { michael@0: let linkId = event.target.id || event.target.localName; michael@0: is(event.type, "click", michael@0: gCurrentTest.desc + ":Handler received a click event on " + linkId); michael@0: michael@0: let isPanelClick = linkId == "panellink"; michael@0: gTestWin.contentAreaClick(event, isPanelClick); michael@0: let prevent = event.defaultPrevented; michael@0: is(prevent, gCurrentTest.preventDefault, michael@0: gCurrentTest.desc + ": event.defaultPrevented is correct (" + prevent + ")") michael@0: michael@0: // Check that all required methods have been called. michael@0: gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) { michael@0: isnot(gInvokedMethods.indexOf(aExpectedMethodName), -1, michael@0: gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked"); michael@0: }); michael@0: michael@0: if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) { michael@0: ok(false, "Wrong number of invoked methods"); michael@0: gInvokedMethods.forEach(function (method) info(method + " was invoked")); michael@0: } michael@0: michael@0: event.preventDefault(); michael@0: event.stopPropagation(); michael@0: michael@0: executeSoon(runNextTest); michael@0: } michael@0: } michael@0: michael@0: // Wraps around the methods' replacement mock function. michael@0: function wrapperMethod(aInvokedMethods, aMethodName) { michael@0: return function () { michael@0: aInvokedMethods.push(aMethodName); michael@0: // At least getShortcutOrURIAndPostData requires to return url michael@0: return (aMethodName == "getShortcutOrURIAndPostData") ? arguments.url : arguments[0]; michael@0: } michael@0: } michael@0: michael@0: function setupTestBrowserWindow() { michael@0: // Steal click events and don't propagate them. michael@0: gTestWin.addEventListener("click", gClickHandler, true); michael@0: michael@0: // Replace methods. michael@0: gReplacedMethods.forEach(function (aMethodName) { michael@0: gTestWin["old_" + aMethodName] = gTestWin[aMethodName]; michael@0: gTestWin[aMethodName] = wrapperMethod(gInvokedMethods, aMethodName); michael@0: }); michael@0: michael@0: // Inject links in content. michael@0: let doc = gTestWin.content.document; michael@0: let mainDiv = doc.createElement("div"); michael@0: mainDiv.innerHTML = michael@0: '
' + michael@0: '' + michael@0: '' + michael@0: '' + michael@0: '' + michael@0: '