зеркало из https://github.com/mozilla/gecko-dev.git
Backed out changeset 03243db46bf0 on CLOSED TREE (bug 1067325)
--HG-- extra : histedit_source : 9ad8ee94f492eeda43a8512988c9b0f57526ec92
This commit is contained in:
Родитель
cf5f5fc965
Коммит
9822493c08
|
@ -54,23 +54,14 @@ ViewSourceBrowser.prototype = {
|
|||
return this._browser;
|
||||
},
|
||||
|
||||
/**
|
||||
* Holds the value of the last line found via the "Go to line"
|
||||
* command, to pre-populate the prompt the next time it is
|
||||
* opened.
|
||||
*/
|
||||
lastLineFound: null,
|
||||
|
||||
/**
|
||||
* These are the messages that ViewSourceBrowser will listen for
|
||||
* from the frame script it injects. Any message names added here
|
||||
* will automatically have ViewSourceBrowser listen for those messages,
|
||||
* and remove the listeners on teardown.
|
||||
*/
|
||||
// TODO: Some messages will appear here in a later patch
|
||||
messages: [
|
||||
"ViewSource:PromptAndGoToLine",
|
||||
"ViewSource:GoToLine:Success",
|
||||
"ViewSource:GoToLine:Failed",
|
||||
],
|
||||
|
||||
/**
|
||||
|
@ -100,16 +91,8 @@ ViewSourceBrowser.prototype = {
|
|||
receiveMessage(message) {
|
||||
let data = message.data;
|
||||
|
||||
// TODO: Some messages will appear here in a later patch
|
||||
switch(message.name) {
|
||||
case "ViewSource:PromptAndGoToLine":
|
||||
this.promptAndGoToLine();
|
||||
break;
|
||||
case "ViewSource:GoToLine:Success":
|
||||
this.onGoToLineSuccess(data.lineNumber);
|
||||
break;
|
||||
case "ViewSource:GoToLine:Failed":
|
||||
this.onGoToLineFailed();
|
||||
break;
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -556,72 +539,4 @@ ViewSourceBrowser.prototype = {
|
|||
|
||||
return str;
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the "Go to line" prompt for a user to hop to a particular line
|
||||
* of the source code they're viewing. This will keep prompting until the
|
||||
* user either cancels out of the prompt, or enters a valid line number.
|
||||
*/
|
||||
promptAndGoToLine() {
|
||||
let input = { value: this.lastLineFound };
|
||||
let window = Services.wm.getMostRecentWindow(null);
|
||||
|
||||
let ok = Services.prompt.prompt(
|
||||
window,
|
||||
this.bundle.GetStringFromName("goToLineTitle"),
|
||||
this.bundle.GetStringFromName("goToLineText"),
|
||||
input,
|
||||
null,
|
||||
{value:0});
|
||||
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
let line = parseInt(input.value, 10);
|
||||
|
||||
if (!(line > 0)) {
|
||||
Services.prompt.alert(window,
|
||||
this.bundle.GetStringFromName("invalidInputTitle"),
|
||||
this.bundle.GetStringFromName("invalidInputText"));
|
||||
this.promptAndGoToLine();
|
||||
} else {
|
||||
this.goToLine(line);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Go to a particular line of the source code. This act is asynchronous.
|
||||
*
|
||||
* @param lineNumber
|
||||
* The line number to try to go to to.
|
||||
*/
|
||||
goToLine(lineNumber) {
|
||||
this.sendAsyncMessage("ViewSource:GoToLine", { lineNumber });
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the frame script reports that a line was successfully gotten
|
||||
* to.
|
||||
*
|
||||
* @param lineNumber
|
||||
* The line number that we successfully got to.
|
||||
*/
|
||||
onGoToLineSuccess(lineNumber) {
|
||||
// We'll pre-populate the "Go to line" prompt with this value the next
|
||||
// time it comes up.
|
||||
this.lastLineFound = lineNumber;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the frame script reports that we failed to go to a particular
|
||||
* line. This informs the user that their selection was likely out of range,
|
||||
* and then reprompts the user to try again.
|
||||
*/
|
||||
onGoToLineFailed() {
|
||||
let window = Services.wm.getMostRecentWindow(null);
|
||||
Services.prompt.alert(window,
|
||||
this.bundle.GetStringFromName("outOfRangeTitle"),
|
||||
this.bundle.GetStringFromName("outOfRangeText"));
|
||||
this.promptAndGoToLine();
|
||||
},
|
||||
};
|
||||
|
|
|
@ -12,7 +12,6 @@ XPCOMUtils.defineLazyModuleGetter(this, "BrowserUtils",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "DeferredTask",
|
||||
"resource://gre/modules/DeferredTask.jsm");
|
||||
|
||||
const NS_XHTML = "http://www.w3.org/1999/xhtml";
|
||||
const BUNDLE_URL = "chrome://global/locale/viewSource.properties";
|
||||
|
||||
// These are markers used to delimit the selection during processing. They
|
||||
|
@ -346,28 +345,16 @@ let ViewSourceContent = {
|
|||
},
|
||||
|
||||
/**
|
||||
* This handler is for click events from:
|
||||
* * error page content, which can show up if the user attempts to view the
|
||||
* source of an attack page.
|
||||
* * in-page context menu actions
|
||||
* This handler is specifically for click events bubbling up from
|
||||
* error page content, which can show up if the user attempts to
|
||||
* view the source of an attack page.
|
||||
*/
|
||||
onClick(event) {
|
||||
let target = event.originalTarget;
|
||||
// Check for content menu actions
|
||||
if (target.id) {
|
||||
this.contextMenuItems.forEach(itemSpec => {
|
||||
if (itemSpec.id !== target.id) {
|
||||
return;
|
||||
}
|
||||
itemSpec.handler.call(this, event);
|
||||
event.stopPropagation();
|
||||
});
|
||||
}
|
||||
|
||||
// Don't trust synthetic events
|
||||
if (!event.isTrusted || event.target.localName != "button")
|
||||
return;
|
||||
|
||||
let target = event.originalTarget;
|
||||
let errorDoc = target.ownerDocument;
|
||||
|
||||
if (/^about:blocked/.test(errorDoc.documentURI)) {
|
||||
|
@ -415,10 +402,6 @@ let ViewSourceContent = {
|
|||
this.drawSelection();
|
||||
}
|
||||
|
||||
if (content.document.body) {
|
||||
this.injectContextMenu();
|
||||
}
|
||||
|
||||
sendAsyncMessage("ViewSource:SourceLoaded");
|
||||
},
|
||||
|
||||
|
@ -676,12 +659,13 @@ let ViewSourceContent = {
|
|||
},
|
||||
|
||||
/**
|
||||
* Toggles the "highlight" class on the document body, which sets whether
|
||||
* or not syntax highlighting is displayed.
|
||||
* Called when the parent has changed the syntax highlighting pref.
|
||||
*/
|
||||
toggleSyntaxHighlighting() {
|
||||
let body = content.document.body;
|
||||
body.classList.toggle("highlight");
|
||||
// The parent process should have set the view_source.syntax_highlight
|
||||
// pref to the desired value. The reload brings that setting into
|
||||
// effect.
|
||||
this.reload();
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -874,80 +858,5 @@ let ViewSourceContent = {
|
|||
findInst.findBackwards = findBackwards;
|
||||
findInst.searchString = searchString;
|
||||
},
|
||||
|
||||
/**
|
||||
* In-page context menu items that are injected after page load.
|
||||
*/
|
||||
contextMenuItems: [
|
||||
{
|
||||
id: "goToLine",
|
||||
handler() {
|
||||
sendAsyncMessage("ViewSource:PromptAndGoToLine");
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "wrapLongLines",
|
||||
get checked() {
|
||||
return Services.prefs.getBoolPref("view_source.wrap_long_lines");
|
||||
},
|
||||
handler() {
|
||||
this.toggleWrapping();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "highlightSyntax",
|
||||
get checked() {
|
||||
return Services.prefs.getBoolPref("view_source.syntax_highlight");
|
||||
},
|
||||
handler() {
|
||||
this.toggleSyntaxHighlighting();
|
||||
}
|
||||
},
|
||||
],
|
||||
|
||||
/**
|
||||
* Add context menu items for view source specific actions.
|
||||
*/
|
||||
injectContextMenu() {
|
||||
let doc = content.document;
|
||||
|
||||
let menu = doc.createElementNS(NS_XHTML, "menu");
|
||||
menu.setAttribute("type", "context");
|
||||
menu.setAttribute("id", "actions");
|
||||
doc.body.appendChild(menu);
|
||||
doc.body.setAttribute("contextmenu", "actions");
|
||||
|
||||
this.contextMenuItems.forEach(itemSpec => {
|
||||
let item = doc.createElementNS(NS_XHTML, "menuitem");
|
||||
item.setAttribute("id", itemSpec.id);
|
||||
let labelName = `context_${itemSpec.id}_label`;
|
||||
let label = this.bundle.GetStringFromName(labelName);
|
||||
item.setAttribute("label", label);
|
||||
if ("checked" in itemSpec) {
|
||||
item.setAttribute("type", "checkbox");
|
||||
}
|
||||
menu.appendChild(item);
|
||||
});
|
||||
|
||||
this.updateContextMenu();
|
||||
},
|
||||
|
||||
/**
|
||||
* Update state of checkbox-style context menu items.
|
||||
*/
|
||||
updateContextMenu() {
|
||||
let doc = content.document;
|
||||
this.contextMenuItems.forEach(itemSpec => {
|
||||
if (!("checked" in itemSpec)) {
|
||||
return;
|
||||
}
|
||||
let item = doc.getElementById(itemSpec.id);
|
||||
if (itemSpec.checked) {
|
||||
item.setAttribute("checked", true);
|
||||
} else {
|
||||
item.removeAttribute("checked");
|
||||
}
|
||||
});
|
||||
},
|
||||
};
|
||||
ViewSourceContent.init();
|
||||
|
|
|
@ -51,6 +51,13 @@ ViewSourceChrome.prototype = {
|
|||
return gBrowser;
|
||||
},
|
||||
|
||||
/**
|
||||
* Holds the value of the last line found via the "Go to line"
|
||||
* command, to pre-populate the prompt the next time it is
|
||||
* opened.
|
||||
*/
|
||||
lastLineFound: null,
|
||||
|
||||
/**
|
||||
* The context menu, when opened from the content process, sends
|
||||
* up a chunk of serialized data describing the items that the
|
||||
|
@ -70,6 +77,8 @@ ViewSourceChrome.prototype = {
|
|||
"ViewSource:SourceUnloaded",
|
||||
"ViewSource:Close",
|
||||
"ViewSource:OpenURL",
|
||||
"ViewSource:GoToLine:Success",
|
||||
"ViewSource:GoToLine:Failed",
|
||||
"ViewSource:UpdateStatus",
|
||||
"ViewSource:ContextMenuOpening",
|
||||
]),
|
||||
|
@ -121,17 +130,6 @@ ViewSourceChrome.prototype = {
|
|||
let data = message.data;
|
||||
|
||||
switch(message.name) {
|
||||
// Begin messages from super class
|
||||
case "ViewSource:PromptAndGoToLine":
|
||||
this.promptAndGoToLine();
|
||||
break;
|
||||
case "ViewSource:GoToLine:Success":
|
||||
this.onGoToLineSuccess(data.lineNumber);
|
||||
break;
|
||||
case "ViewSource:GoToLine:Failed":
|
||||
this.onGoToLineFailed();
|
||||
break;
|
||||
// End messages from super class
|
||||
case "ViewSource:SourceLoaded":
|
||||
this.onSourceLoaded();
|
||||
break;
|
||||
|
@ -144,6 +142,12 @@ ViewSourceChrome.prototype = {
|
|||
case "ViewSource:OpenURL":
|
||||
this.openURL(data.URL);
|
||||
break;
|
||||
case "ViewSource:GoToLine:Failed":
|
||||
this.onGoToLineFailed();
|
||||
break;
|
||||
case "ViewSource:GoToLine:Success":
|
||||
this.onGoToLineSuccess(data.lineNumber);
|
||||
break;
|
||||
case "ViewSource:UpdateStatus":
|
||||
this.updateStatus(data.label);
|
||||
break;
|
||||
|
@ -600,6 +604,47 @@ ViewSourceChrome.prototype = {
|
|||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Opens the "Go to line" prompt for a user to hop to a particular line
|
||||
* of the source code they're viewing. This will keep prompting until the
|
||||
* user either cancels out of the prompt, or enters a valid line number.
|
||||
*/
|
||||
promptAndGoToLine() {
|
||||
let input = { value: this.lastLineFound };
|
||||
|
||||
let ok = Services.prompt.prompt(
|
||||
window,
|
||||
gViewSourceBundle.getString("goToLineTitle"),
|
||||
gViewSourceBundle.getString("goToLineText"),
|
||||
input,
|
||||
null,
|
||||
{value:0});
|
||||
|
||||
if (!ok)
|
||||
return;
|
||||
|
||||
let line = parseInt(input.value, 10);
|
||||
|
||||
if (!(line > 0)) {
|
||||
Services.prompt.alert(window,
|
||||
gViewSourceBundle.getString("invalidInputTitle"),
|
||||
gViewSourceBundle.getString("invalidInputText"));
|
||||
this.promptAndGoToLine();
|
||||
} else {
|
||||
this.goToLine(line);
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Go to a particular line of the source code. This act is asynchronous.
|
||||
*
|
||||
* @param lineNumber
|
||||
* The line number to try to go to to.
|
||||
*/
|
||||
goToLine(lineNumber) {
|
||||
this.sendAsyncMessage("ViewSource:GoToLine", { lineNumber });
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the frame script reports that a line was successfully gotten
|
||||
* to.
|
||||
|
@ -608,11 +653,25 @@ ViewSourceChrome.prototype = {
|
|||
* The line number that we successfully got to.
|
||||
*/
|
||||
onGoToLineSuccess(lineNumber) {
|
||||
ViewSourceBrowser.prototype.onGoToLineSuccess.call(this, lineNumber);
|
||||
// We'll pre-populate the "Go to line" prompt with this value the next
|
||||
// time it comes up.
|
||||
this.lastLineFound = lineNumber;
|
||||
document.getElementById("statusbar-line-col").label =
|
||||
gViewSourceBundle.getFormattedString("statusBarLineCol", [lineNumber, 1]);
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the frame script reports that we failed to go to a particular
|
||||
* line. This informs the user that their selection was likely out of range,
|
||||
* and then reprompts the user to try again.
|
||||
*/
|
||||
onGoToLineFailed() {
|
||||
Services.prompt.alert(window,
|
||||
gViewSourceBundle.getString("outOfRangeTitle"),
|
||||
gViewSourceBundle.getString("outOfRangeText"));
|
||||
this.promptAndGoToLine();
|
||||
},
|
||||
|
||||
/**
|
||||
* Reloads the browser, bypassing the network cache.
|
||||
*/
|
||||
|
@ -648,7 +707,8 @@ ViewSourceChrome.prototype = {
|
|||
toggleSyntaxHighlighting() {
|
||||
this.shouldHighlight = !this.shouldHighlight;
|
||||
// We can't flip this value in the child, since prefs are read-only there.
|
||||
// We flip it here, and then toggle a class in the child.
|
||||
// We flip it here, and then cause a reload in the child to make the change
|
||||
// occur.
|
||||
Services.prefs.setBoolPref("view_source.syntax_highlight",
|
||||
this.shouldHighlight);
|
||||
this.sendAsyncMessage("ViewSource:ToggleSyntaxHighlighting");
|
||||
|
|
|
@ -53,14 +53,21 @@ let exercisePrefs = Task.async(function* (source, highlightable) {
|
|||
yield checkStyle(win, "white-space", "pre");
|
||||
|
||||
// Check that the Syntax Highlighting menu item works.
|
||||
let pageShowPromise = BrowserTestUtils.waitForEvent(win.gBrowser, "pageshow");
|
||||
simulateClick(syntaxMenuItem);
|
||||
yield pageShowPromise;
|
||||
|
||||
is(syntaxMenuItem.hasAttribute("checked"), false, "Syntax menu item unchecked");
|
||||
is(SpecialPowers.getBoolPref("view_source.syntax_highlight"), false, "Syntax highlighting pref set");
|
||||
yield checkHighlight(win, false);
|
||||
|
||||
pageShowPromise = BrowserTestUtils.waitForEvent(win.gBrowser, "pageshow");
|
||||
simulateClick(syntaxMenuItem);
|
||||
yield pageShowPromise;
|
||||
|
||||
is(syntaxMenuItem.hasAttribute("checked"), true, "Syntax menu item checked");
|
||||
is(SpecialPowers.getBoolPref("view_source.syntax_highlight"), true, "Syntax highlighting pref set");
|
||||
|
||||
yield checkHighlight(win, highlightable);
|
||||
yield BrowserTestUtils.closeWindow(win);
|
||||
|
||||
|
@ -120,8 +127,7 @@ let checkHighlight = Task.async(function* (win, expected) {
|
|||
let highlighted = yield ContentTask.spawn(browser, {}, function* () {
|
||||
let spans = content.document.getElementsByTagName("span");
|
||||
return Array.some(spans, (span) => {
|
||||
let style = content.getComputedStyle(span, null);
|
||||
return style.getPropertyValue("color") !== "rgb(0, 0, 0)";
|
||||
return span.className != "";
|
||||
});
|
||||
});
|
||||
is(highlighted, expected, "Syntax highlighting " + (expected ? "on" : "off"));
|
||||
|
|
|
@ -11,7 +11,3 @@ outOfRangeText = The specified line was not found.
|
|||
statusBarLineCol = Line %1$S, Col %2$S
|
||||
viewSelectionSourceTitle = DOM Source of Selection
|
||||
viewMathMLSourceTitle = DOM Source of MathML
|
||||
|
||||
context_goToLine_label = Go to Line…
|
||||
context_wrapLongLines_label = Wrap Long Lines
|
||||
context_highlightSyntax_label = Syntax Highlighting
|
||||
|
|
Загрузка…
Ссылка в новой задаче