зеркало из https://github.com/mozilla/gecko-dev.git
Bug 549340 - reorganize ContentAreaClick, give it consistent return values and comments.
r=gavin a=blocking
This commit is contained in:
Родитель
e8ced1d8aa
Коммит
0a69e28c71
|
@ -4988,134 +4988,150 @@ function asyncOpenWebPanel(event)
|
||||||
* - gatherTextUnder
|
* - gatherTextUnder
|
||||||
*/
|
*/
|
||||||
|
|
||||||
// Called whenever the user clicks in the content area,
|
/**
|
||||||
// except when left-clicking on links (special case)
|
* Extracts linkNode and href for the current click target.
|
||||||
// should always return true for click to go through
|
*
|
||||||
function contentAreaClick(event, fieldNormalClicks)
|
* @param event
|
||||||
{
|
* The click event.
|
||||||
if (!event.isTrusted || event.getPreventDefault()) {
|
* @return [href, linkNode].
|
||||||
return true;
|
*
|
||||||
}
|
* @note linkNode will be null if the click wasn't on an anchor
|
||||||
|
* element (or XLink).
|
||||||
|
*/
|
||||||
|
function hrefAndLinkNodeForClickEvent(event)
|
||||||
|
{
|
||||||
|
function isHTMLLink(aNode)
|
||||||
|
{
|
||||||
|
return aNode instanceof HTMLAnchorElement ||
|
||||||
|
aNode instanceof HTMLAreaElement ||
|
||||||
|
aNode instanceof HTMLLinkElement;
|
||||||
|
}
|
||||||
|
|
||||||
var target = event.target;
|
let linkNode;
|
||||||
var linkNode;
|
if (isHTMLLink(event.target)) {
|
||||||
|
// This is a hack to work around Gecko bug 266932.
|
||||||
|
// Walk up the DOM looking for a parent link node, to match the existing
|
||||||
|
// behaviour for left click.
|
||||||
|
// TODO: this is no more needed and should be removed in bug 325652.
|
||||||
|
let node = event.target;
|
||||||
|
while (node) {
|
||||||
|
if (isHTMLLink(node) && node.hasAttribute("href"))
|
||||||
|
linkNode = node;
|
||||||
|
node = node.parentNode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
let node = event.originalTarget;
|
||||||
|
while (node && !(node instanceof HTMLAnchorElement)) {
|
||||||
|
node = node.parentNode;
|
||||||
|
}
|
||||||
|
// <a> cannot be nested. So if we find an anchor without an
|
||||||
|
// href, there is no useful <a> around the target.
|
||||||
|
if (node && node.hasAttribute("href"))
|
||||||
|
linkNode = node;
|
||||||
|
}
|
||||||
|
|
||||||
if (target instanceof HTMLAnchorElement ||
|
if (linkNode)
|
||||||
target instanceof HTMLAreaElement ||
|
return [linkNode.href, linkNode];
|
||||||
target instanceof HTMLLinkElement) {
|
|
||||||
if (target.hasAttribute("href"))
|
|
||||||
linkNode = target;
|
|
||||||
|
|
||||||
// xxxmpc: this is kind of a hack to work around a Gecko bug (see bug 266932)
|
// If there is no linkNode, try simple XLink.
|
||||||
// we're going to walk up the DOM looking for a parent link node,
|
let href, baseURI;
|
||||||
// this shouldn't be necessary, but we're matching the existing behaviour for left click
|
let node = event.target;
|
||||||
var parent = target.parentNode;
|
while (node) {
|
||||||
while (parent) {
|
if (node.nodeType == Node.ELEMENT_NODE) {
|
||||||
if (parent instanceof HTMLAnchorElement ||
|
href = node.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
||||||
parent instanceof HTMLAreaElement ||
|
if (href)
|
||||||
parent instanceof HTMLLinkElement) {
|
baseURI = node.baseURI;
|
||||||
if (parent.hasAttribute("href"))
|
}
|
||||||
linkNode = parent;
|
node = node.parentNode;
|
||||||
}
|
}
|
||||||
parent = parent.parentNode;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
linkNode = event.originalTarget;
|
|
||||||
while (linkNode && !(linkNode instanceof HTMLAnchorElement))
|
|
||||||
linkNode = linkNode.parentNode;
|
|
||||||
// <a> cannot be nested. So if we find an anchor without an
|
|
||||||
// href, there is no useful <a> around the target
|
|
||||||
if (linkNode && !linkNode.hasAttribute("href"))
|
|
||||||
linkNode = null;
|
|
||||||
}
|
|
||||||
var wrapper = null;
|
|
||||||
if (linkNode) {
|
|
||||||
wrapper = linkNode;
|
|
||||||
if (event.button == 0 && !event.ctrlKey && !event.shiftKey &&
|
|
||||||
!event.altKey && !event.metaKey) {
|
|
||||||
// A Web panel's links should target the main content area. Do this
|
|
||||||
// if no modifier keys are down and if there's no target or the target equals
|
|
||||||
// _main (the IE convention) or _content (the Mozilla convention).
|
|
||||||
// XXX Now that markLinkVisited is gone, we may not need to field _main and
|
|
||||||
// _content here.
|
|
||||||
target = wrapper.getAttribute("target");
|
|
||||||
if (fieldNormalClicks &&
|
|
||||||
(!target || target == "_content" || target == "_main"))
|
|
||||||
// IE uses _main, SeaMonkey uses _content, we support both
|
|
||||||
{
|
|
||||||
if (!wrapper.href)
|
|
||||||
return true;
|
|
||||||
if (wrapper.getAttribute("onclick"))
|
|
||||||
return true;
|
|
||||||
// javascript links should be executed in the current browser
|
|
||||||
if (wrapper.href.substr(0, 11) === "javascript:")
|
|
||||||
return true;
|
|
||||||
// data links should be executed in the current browser
|
|
||||||
if (wrapper.href.substr(0, 5) === "data:")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
try {
|
// In case of XLink, we don't return the node we got href from since
|
||||||
urlSecurityCheck(wrapper.href, wrapper.ownerDocument.nodePrincipal);
|
// callers expect <a>-like elements.
|
||||||
}
|
return [href ? makeURLAbsolute(baseURI, href) : null, null];
|
||||||
catch(ex) {
|
}
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
var postData = { };
|
/**
|
||||||
var url = getShortcutOrURI(wrapper.href, postData);
|
* Called whenever the user clicks in the content area.
|
||||||
if (!url)
|
*
|
||||||
return true;
|
* @param event
|
||||||
loadURI(url, null, postData.value, false);
|
* The click event.
|
||||||
event.preventDefault();
|
* @param isPanelClick
|
||||||
return false;
|
* Whether the event comes from a web panel.
|
||||||
}
|
* @note default event is prevented if the click is handled.
|
||||||
else if (linkNode.getAttribute("rel") == "sidebar") {
|
*/
|
||||||
// This is the Opera convention for a special link that - when clicked - allows
|
function contentAreaClick(event, isPanelClick)
|
||||||
// you to add a sidebar panel. We support the Opera convention here. The link's
|
{
|
||||||
// title attribute contains the title that should be used for the sidebar panel.
|
if (!event.isTrusted || event.getPreventDefault() || event.button == 2)
|
||||||
PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(wrapper.href),
|
return true;
|
||||||
wrapper.getAttribute("title"),
|
|
||||||
null, null, true, true);
|
|
||||||
event.preventDefault();
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
handleLinkClick(event, wrapper.href, linkNode);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
let [href, linkNode] = hrefAndLinkNodeForClickEvent(event);
|
||||||
} else {
|
if (!href) {
|
||||||
// Try simple XLink
|
// Not a link, handle middle mouse navigation.
|
||||||
var href, realHref, baseURI;
|
if (event.button == 1 &&
|
||||||
linkNode = target;
|
gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
|
||||||
while (linkNode) {
|
!gPrefService.getBoolPref("general.autoScroll")) {
|
||||||
if (linkNode.nodeType == Node.ELEMENT_NODE) {
|
middleMousePaste(event);
|
||||||
wrapper = linkNode;
|
event.preventDefault();
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
realHref = wrapper.getAttributeNS("http://www.w3.org/1999/xlink", "href");
|
// This code only applies if we have a linkNode (i.e. clicks on real anchor
|
||||||
if (realHref) {
|
// elements, as opposed to XLink).
|
||||||
href = realHref;
|
if (linkNode && event.button == 0 &&
|
||||||
baseURI = wrapper.baseURI
|
!event.ctrlKey && !event.shiftKey && !event.altKey && !event.metaKey) {
|
||||||
}
|
// A Web panel's links should target the main content area. Do this
|
||||||
}
|
// if no modifier keys are down and if there's no target or the target
|
||||||
linkNode = linkNode.parentNode;
|
// equals _main (the IE convention) or _content (the Mozilla convention).
|
||||||
}
|
let target = linkNode.target;
|
||||||
if (href) {
|
let mainTarget = !target || target == "_content" || target == "_main";
|
||||||
href = makeURLAbsolute(baseURI, href);
|
if (isPanelClick && mainTarget) {
|
||||||
handleLinkClick(event, href, null);
|
// javascript and data links should be executed in the current browser.
|
||||||
return true;
|
if (linkNode.getAttribute("onclick") ||
|
||||||
}
|
href.substr(0, 11) === "javascript:" ||
|
||||||
}
|
href.substr(0, 5) === "data:")
|
||||||
if (event.button == 1 &&
|
return true;
|
||||||
gPrefService.getBoolPref("middlemouse.contentLoadURL") &&
|
|
||||||
!gPrefService.getBoolPref("general.autoScroll")) {
|
|
||||||
middleMousePaste(event);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
urlSecurityCheck(href, linkNode.ownerDocument.nodePrincipal);
|
||||||
|
}
|
||||||
|
catch(ex) {
|
||||||
|
// Prevent loading unsecure destinations.
|
||||||
|
event.preventDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
let postData = {};
|
||||||
|
let url = getShortcutOrURI(href, postData);
|
||||||
|
if (!url)
|
||||||
|
return true;
|
||||||
|
loadURI(url, null, postData.value, false);
|
||||||
|
event.preventDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (linkNode.getAttribute("rel") == "sidebar") {
|
||||||
|
// This is the Opera convention for a special link that, when clicked,
|
||||||
|
// allows to add a sidebar panel. The link's title attribute contains
|
||||||
|
// the title that should be used for the sidebar panel.
|
||||||
|
PlacesUIUtils.showMinimalAddBookmarkUI(makeURI(href),
|
||||||
|
linkNode.getAttribute("title"),
|
||||||
|
null, null, true, true);
|
||||||
|
event.preventDefault();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
handleLinkClick(event, href, linkNode);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Handles clicks on links.
|
||||||
|
*
|
||||||
|
* @return true if the click event was handled, false otherwise.
|
||||||
|
*/
|
||||||
function handleLinkClick(event, href, linkNode) {
|
function handleLinkClick(event, href, linkNode) {
|
||||||
if (event.button == 2) // right click
|
if (event.button == 2) // right click
|
||||||
return false;
|
return false;
|
||||||
|
@ -5129,6 +5145,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||||
if (where == "save") {
|
if (where == "save") {
|
||||||
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
saveURL(href, linkNode ? gatherTextUnder(linkNode) : "", null, true,
|
||||||
true, doc.documentURIObject);
|
true, doc.documentURIObject);
|
||||||
|
event.preventDefault();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5136,7 +5153,7 @@ function handleLinkClick(event, href, linkNode) {
|
||||||
openLinkIn(href, where, { fromContent: true,
|
openLinkIn(href, where, { fromContent: true,
|
||||||
referrerURI: doc.documentURIObject,
|
referrerURI: doc.documentURIObject,
|
||||||
charset: doc.characterSet });
|
charset: doc.characterSet });
|
||||||
event.stopPropagation();
|
event.preventDefault();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -221,6 +221,7 @@ _BROWSER_FILES = \
|
||||||
browser_aboutHome.js \
|
browser_aboutHome.js \
|
||||||
app_bug575561.html \
|
app_bug575561.html \
|
||||||
app_subframe_bug575561.html \
|
app_subframe_bug575561.html \
|
||||||
|
browser_contentAreaClick.js \
|
||||||
$(NULL)
|
$(NULL)
|
||||||
|
|
||||||
# compartment-disabled
|
# compartment-disabled
|
||||||
|
|
|
@ -0,0 +1,296 @@
|
||||||
|
/* ***** BEGIN LICENSE BLOCK *****
|
||||||
|
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
|
||||||
|
*
|
||||||
|
* The contents of this file are subject to the Mozilla Public License Version
|
||||||
|
* 1.1 (the "License"); you may not use this file except in compliance with
|
||||||
|
* the License. You may obtain a copy of the License at
|
||||||
|
* http://www.mozilla.org/MPL/
|
||||||
|
*
|
||||||
|
* Software distributed under the License is distributed on an "AS IS" basis,
|
||||||
|
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
|
||||||
|
* for the specific language governing rights and limitations under the
|
||||||
|
* License.
|
||||||
|
*
|
||||||
|
* The Original Code is Firefox Browser Test Code.
|
||||||
|
*
|
||||||
|
* The Initial Developer of the Original Code is the Mozilla Foundation.
|
||||||
|
* Portions created by the Initial Developer are Copyright (C) 2010
|
||||||
|
* the Initial Developer. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Contributor(s):
|
||||||
|
* Marco Bonardo <mak77@bonardo.net>
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms of
|
||||||
|
* either the GNU General Public License Version 2 or later (the "GPL"), or
|
||||||
|
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
|
||||||
|
* in which case the provisions of the GPL or the LGPL are applicable instead
|
||||||
|
* of those above. If you wish to allow use of your version of this file only
|
||||||
|
* under the terms of either the GPL or the LGPL, and not to allow others to
|
||||||
|
* use your version of this file under the terms of the MPL, indicate your
|
||||||
|
* decision by deleting the provisions above and replace them with the notice
|
||||||
|
* and other provisions required by the GPL or the LGPL. If you do not delete
|
||||||
|
* the provisions above, a recipient may use your version of this file under
|
||||||
|
* the terms of any one of the MPL, the GPL or the LGPL.
|
||||||
|
*
|
||||||
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test for bug 549340.
|
||||||
|
* Test for browser.js::contentAreaClick() util.
|
||||||
|
*
|
||||||
|
* The test opens a new browser window, then replaces browser.js methods invoked
|
||||||
|
* by contentAreaClick with a mock function that tracks which methods have been
|
||||||
|
* called.
|
||||||
|
* Each sub-test synthesizes a mouse click event on links injected in content,
|
||||||
|
* the event is collected by a click handler that ensures that contentAreaClick
|
||||||
|
* correctly prevent default events, and follows the correct code path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
let gTests = [
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Simple left click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: {},
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [],
|
||||||
|
preventDefault: false,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Ctrl/Cmd left click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: { ctrlKey: true,
|
||||||
|
metaKey: true },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
// The next test was once handling feedService.forcePreview(). Now it should
|
||||||
|
// just be like Alt click.
|
||||||
|
{
|
||||||
|
desc: "Shift+Alt left click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: { shiftKey: true,
|
||||||
|
altKey: true },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Shift click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: { shiftKey: true },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Alt click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: { altKey: true },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "gatherTextUnder", "saveURL" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Panel click",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: {},
|
||||||
|
target: "panellink",
|
||||||
|
expectedInvokedMethods: [ "urlSecurityCheck", "getShortcutOrURI", "loadURI" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Simple middle click opentab",
|
||||||
|
setup: function() {},
|
||||||
|
clean: function() {},
|
||||||
|
event: { button: 1 },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Simple middle click openwin",
|
||||||
|
setup: function() {
|
||||||
|
gPrefService.setBoolPref("browser.tabs.opentabfor.middleclick", false);
|
||||||
|
},
|
||||||
|
clean: function() {
|
||||||
|
try {
|
||||||
|
gPrefService.clearUserPref("browser.tabs.opentabfor.middleclick");
|
||||||
|
} catch(ex) {}
|
||||||
|
},
|
||||||
|
event: { button: 1 },
|
||||||
|
target: "commonlink",
|
||||||
|
expectedInvokedMethods: [ "urlSecurityCheck", "openLinkIn" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
{
|
||||||
|
desc: "Middle mouse paste",
|
||||||
|
setup: function() {
|
||||||
|
gPrefService.setBoolPref("middlemouse.contentLoadURL", true);
|
||||||
|
gPrefService.setBoolPref("general.autoScroll", false);
|
||||||
|
},
|
||||||
|
clean: function() {
|
||||||
|
try {
|
||||||
|
gPrefService.clearUserPref("middlemouse.contentLoadURL");
|
||||||
|
} catch(ex) {}
|
||||||
|
try {
|
||||||
|
gPrefService.clearUserPref("general.autoScroll");
|
||||||
|
} catch(ex) {}
|
||||||
|
},
|
||||||
|
event: { button: 1 },
|
||||||
|
target: "emptylink",
|
||||||
|
expectedInvokedMethods: [ "middleMousePaste" ],
|
||||||
|
preventDefault: true,
|
||||||
|
},
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
|
// Array of method names that will be replaced in the new window.
|
||||||
|
let gReplacedMethods = [
|
||||||
|
"middleMousePaste",
|
||||||
|
"urlSecurityCheck",
|
||||||
|
"loadURI",
|
||||||
|
"gatherTextUnder",
|
||||||
|
"saveURL",
|
||||||
|
"openLinkIn",
|
||||||
|
"getShortcutOrURI",
|
||||||
|
];
|
||||||
|
|
||||||
|
// Reference to the new window.
|
||||||
|
let gTestWin = null;
|
||||||
|
|
||||||
|
// List of methods invoked by a specific call to contentAreaClick.
|
||||||
|
let gInvokedMethods = [];
|
||||||
|
|
||||||
|
// The test currently running.
|
||||||
|
let gCurrentTest = null;
|
||||||
|
|
||||||
|
function test() {
|
||||||
|
waitForExplicitFinish();
|
||||||
|
|
||||||
|
gTestWin = openDialog(location, "", "chrome,all,dialog=no", "about:blank");
|
||||||
|
gTestWin.addEventListener("load", function (event) {
|
||||||
|
info("Window loaded.");
|
||||||
|
gTestWin.removeEventListener("load", arguments.callee, false);
|
||||||
|
waitForFocus(function() {
|
||||||
|
info("Setting up browser...");
|
||||||
|
setupTestBrowserWindow();
|
||||||
|
info("Running tests...");
|
||||||
|
executeSoon(runNextTest);
|
||||||
|
}, gTestWin.content, true);
|
||||||
|
}, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Click handler used to steal click events.
|
||||||
|
let gClickHandler = {
|
||||||
|
handleEvent: function (event) {
|
||||||
|
let linkId = event.target.id;
|
||||||
|
is(event.type, "click",
|
||||||
|
gCurrentTest.desc + ":Handler received a click event on " + linkId);
|
||||||
|
|
||||||
|
let isPanelClick = linkId == "panellink";
|
||||||
|
let returnValue = gTestWin.contentAreaClick(event, isPanelClick);
|
||||||
|
let prevent = event.getPreventDefault();
|
||||||
|
is(prevent, gCurrentTest.preventDefault,
|
||||||
|
gCurrentTest.desc + ": event.getPreventDefault() is correct (" + prevent + ")")
|
||||||
|
|
||||||
|
// Check that all required methods have been called.
|
||||||
|
gCurrentTest.expectedInvokedMethods.forEach(function(aExpectedMethodName) {
|
||||||
|
isnot(gInvokedMethods.indexOf(aExpectedMethodName), -1,
|
||||||
|
gCurrentTest.desc + ":" + aExpectedMethodName + " was invoked");
|
||||||
|
});
|
||||||
|
|
||||||
|
if (gInvokedMethods.length != gCurrentTest.expectedInvokedMethods.length) {
|
||||||
|
is(false, "More than the expected methods have been called");
|
||||||
|
gInvokedMethods.forEach(function (method) info(method + " was invoked"));
|
||||||
|
}
|
||||||
|
|
||||||
|
event.preventDefault();
|
||||||
|
event.stopPropagation();
|
||||||
|
|
||||||
|
executeSoon(runNextTest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Wraps around the methods' replacement mock function.
|
||||||
|
function wrapperMethod(aInvokedMethods, aMethodName) {
|
||||||
|
return function () {
|
||||||
|
aInvokedMethods.push(aMethodName);
|
||||||
|
// At least getShortcutOrURI requires to return url that is the first param.
|
||||||
|
return arguments[0];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function setupTestBrowserWindow() {
|
||||||
|
// Steal click events and don't propagate them.
|
||||||
|
gTestWin.addEventListener("click", gClickHandler, true);
|
||||||
|
|
||||||
|
// Replace methods.
|
||||||
|
gReplacedMethods.forEach(function (aMethodName) {
|
||||||
|
gTestWin["old_" + aMethodName] = gTestWin[aMethodName];
|
||||||
|
gTestWin[aMethodName] = wrapperMethod(gInvokedMethods, aMethodName);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Inject links in content.
|
||||||
|
let doc = gTestWin.content.document;
|
||||||
|
let mainDiv = doc.createElement("div");
|
||||||
|
mainDiv.innerHTML =
|
||||||
|
'<a id="commonlink" href="http://mochi.test/moz/">Common link</a>' +
|
||||||
|
'<a id="panellink" href="http://mochi.test/moz/">Panel link</a>' +
|
||||||
|
'<a id="emptylink">Empty link</a>';
|
||||||
|
doc.body.appendChild(mainDiv);
|
||||||
|
}
|
||||||
|
|
||||||
|
function runNextTest() {
|
||||||
|
if (gCurrentTest) {
|
||||||
|
info(gCurrentTest.desc + ": cleaning up...")
|
||||||
|
gCurrentTest.clean();
|
||||||
|
gInvokedMethods.length = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (gTests.length > 0) {
|
||||||
|
gCurrentTest = gTests.shift();
|
||||||
|
|
||||||
|
info(gCurrentTest.desc + ": starting...");
|
||||||
|
// Prepare for test.
|
||||||
|
gCurrentTest.setup();
|
||||||
|
|
||||||
|
// Fire click event.
|
||||||
|
let target = gTestWin.content.document.getElementById(gCurrentTest.target);
|
||||||
|
ok(target, gCurrentTest.desc + ": target is valid (" + target.id + ")");
|
||||||
|
EventUtils.synthesizeMouse(target, 2, 2, gCurrentTest.event, gTestWin.content);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// No more tests to run.
|
||||||
|
finishTest()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function finishTest() {
|
||||||
|
info("Restoring browser...");
|
||||||
|
gTestWin.removeEventListener("click", gClickHandler, true);
|
||||||
|
|
||||||
|
// Restore original methods.
|
||||||
|
gReplacedMethods.forEach(function (aMethodName) {
|
||||||
|
gTestWin[aMethodName] = gTestWin["old_" + aMethodName];
|
||||||
|
delete gTestWin["old_" + aMethodName];
|
||||||
|
});
|
||||||
|
|
||||||
|
gTestWin.close();
|
||||||
|
finish();
|
||||||
|
}
|
Загрузка…
Ссылка в новой задаче