Bug 515512 - Text urls that don't have the leading protocol should have the link context menu options when selected. r=dao

This commit is contained in:
Nochum Sossonko 2009-10-31 08:59:23 +01:00
parent 62eb5c6518
commit e6acb87371
3 changed files with 152 additions and 10 deletions

View File

@ -144,18 +144,64 @@ nsContextMenu.prototype = {
(mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
}
// time to do some bad things and see if we've highlighted a URL that isn't actually linked
// Time to do some bad things and see if we've highlighted a URL that
// isn't actually linked.
var onPlainTextLink = false;
if (this.isTextSelected) {
// ok, we have some text, let's figure out if it looks like a URL
var someText = document.commandDispatcher.focusedWindow
.getSelection().toString();
try {
var uri = makeURI(someText);
// Ok, we have some text, let's figure out if it looks like a URL.
let selection = document.commandDispatcher.focusedWindow
.getSelection();
let linkText = selection.toString().trim();
let uri;
if (/^(?:https?|ftp):/i.test(linkText)) {
try {
uri = makeURI(linkText);
} catch (ex) {}
}
catch (ex) { }
var onPlainTextLink = false;
if (uri && /^(https?|ftp)$/i.test(uri.scheme) && uri.host) {
// Check if this could be a valid url, just missing the protocol.
else if (/^(?:\w+\.)+\D\S*$/.test(linkText)) {
// Now let's see if this is an intentional link selection. Our guess is
// based on whether the selection begins/ends with whitespace or is
// preceded/followed by a non-word character.
// selection.toString() trims trailing whitespace, so we look for
// that explicitly in the first and last ranges.
let beginRange = selection.getRangeAt(0);
let delimitedAtStart = /^\s/.test(beginRange);
if (!delimitedAtStart) {
let container = beginRange.startContainer;
let offset = beginRange.startOffset;
if (container.nodeType == Node.TEXT_NODE && offset > 0)
delimitedAtStart = /\W/.test(container.textContent[offset - 1]);
else
delimitedAtStart = true;
}
let delimitedAtEnd = false;
if (delimitedAtStart) {
let endRange = selection.getRangeAt(selection.rangeCount - 1);
delimitedAtEnd = /\s$/.test(endRange);
if (!delimitedAtEnd) {
let container = endRange.endContainer;
let offset = endRange.endOffset;
if (container.nodeType == Node.TEXT_NODE &&
offset < container.textContent.length)
delimitedAtEnd = /\W/.test(container.textContent[offset]);
else
delimitedAtEnd = true;
}
}
if (delimitedAtStart && delimitedAtEnd) {
let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
.getService(Ci.nsIURIFixup);
try {
uri = uriFixup.createFixupURI(linkText, uriFixup.FIXUP_FLAG_NONE);
} catch (ex) {}
}
}
if (uri && uri.host) {
this.linkURI = uri;
this.linkURL = this.linkURI.spec;
onPlainTextLink = true;

View File

@ -139,6 +139,7 @@ _BROWSER_FILES = \
browser_bug304198.js \
browser_drag.js \
browser_relatedTabs.js \
browser_plainTextLinks.js \
browser_contextSearchTabPosition.js \
browser_NetworkPrioritizer.js \
$(NULL)

View File

@ -0,0 +1,95 @@
let doc, range, selection;
function setSelection(el1, el2, index1, index2) {
selection.removeAllRanges();
range.setStart(el1, index1);
range.setEnd(el2, index2);
selection.addRange(range);
}
function initContextMenu() {
document.popupNode = doc.getElementsByTagName("DIV")[0];
let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
let contextMenu = new nsContextMenu(contentAreaContextMenu, gBrowser);
return contextMenu;
}
function testExpected(expected, msg) {
initContextMenu();
let linkMenuItem = document.getElementById("context-openlinkincurrent");
is(linkMenuItem.hidden, expected, msg);
}
function testLinkExpected(expected, msg) {
let contextMenu = initContextMenu();
is(contextMenu.linkURL, expected, msg);
}
function runSelectionTests() {
let mainDiv = doc.createElement("div");
let div = doc.createElement("div");
let div2 = doc.createElement("div");
let span1 = doc.createElement("span");
let span2 = doc.createElement("span");
let span3 = doc.createElement("span");
let p1 = doc.createElement("p");
let p2 = doc.createElement("p");
span1.textContent = "http://index.";
span2.textContent = "example.com example.com";
span3.textContent = " - Test";
p1.textContent = "mailto:test.com ftp.example.com";
p2.textContent = "example.com -";
div.appendChild(span1);
div.appendChild(span2);
div.appendChild(span3);
div.appendChild(p1);
div.appendChild(p2);
let p3 = doc.createElement("p");
p3.textContent = "main.example.com";
div2.appendChild(p3);
mainDiv.appendChild(div);
mainDiv.appendChild(div2);
doc.body.appendChild(mainDiv);
setSelection(span1.firstChild, span2.firstChild, 0, 11);
testExpected(false, "The link context menu should show for http://www.example.com");
setSelection(span1.firstChild, span2.firstChild, 7, 11);
testExpected(false, "The link context menu should show for www.example.com");
setSelection(span1.firstChild, span2.firstChild, 8, 11);
testExpected(true, "The link context menu should not show for ww.example.com");
setSelection(span2.firstChild, span2.firstChild, 0, 11);
testExpected(false, "The link context menu should show for example.com");
testLinkExpected("http://example.com/", "url for example.com selection should not prepend www");
setSelection(span2.firstChild, span2.firstChild, 11, 23);
testExpected(false, "The link context menu should show for example.com");
setSelection(span2.firstChild, span2.firstChild, 0, 10);
testExpected(true, "Link options should not show for selection that's not at a word boundary");
setSelection(span2.firstChild, span3.firstChild, 12, 7);
testExpected(true, "Link options should not show for selection that has whitespace");
setSelection(span2.firstChild, span2.firstChild, 12, 19);
testExpected(true, "Link options should not show unless a url is selected");
setSelection(p1.firstChild, p1.firstChild, 0, 15);
testExpected(true, "Link options should not show for mailto: links");
setSelection(p1.firstChild, p1.firstChild, 16, 31);
testExpected(false, "Link options should show for ftp.example.com");
testLinkExpected("ftp://ftp.example.com/", "ftp.example.com should be preceeded with ftp://");
setSelection(p2.firstChild, p2.firstChild, 0, 14);
testExpected(false, "Link options should show for www.example.com ");
selection.selectAllChildren(div2);
testExpected(false, "Link options should show for triple-click selections");
gBrowser.removeCurrentTab();
finish();
}
function test() {
waitForExplicitFinish();
gBrowser.selectedTab = gBrowser.addTab();
gBrowser.selectedBrowser.addEventListener("load", function() {
gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
doc = content.document;
range = doc.createRange();
selection = content.getSelection();
waitForFocus(runSelectionTests, content);
}, true);
content.location =
"data:text/html,Test For Non-Hyperlinked url selection";
}