Bug 1067325 - Extract view source core to support tabs. r=mconley

This commit is contained in:
J. Ryan Stinnett 2015-05-23 18:17:50 -05:00
parent b4e49ea508
commit 1fde438170
12 changed files with 367 additions and 146 deletions

View File

@ -1921,3 +1921,5 @@ pref("browser.pocket.site", "getpocket.com");
pref("browser.pocket.oAuthConsumerKey", "40249-e88c401e1b1f2242d9e441c4");
pref("browser.pocket.useLocaleList", true);
pref("browser.pocket.enabledLocales", "en-US de es-ES ja ja-JP-mac ru");
pref("view_source.tab", true);

View File

@ -986,6 +986,7 @@ var gBrowserInit = {
mm.loadFrameScript("chrome://browser/content/content.js", true);
mm.loadFrameScript("chrome://browser/content/content-UITour.js", true);
mm.loadFrameScript("chrome://global/content/manifestMessages.js", true);
mm.loadFrameScript("chrome://global/content/viewSource-content.js", true);
window.messageManager.addMessageListener("Browser:LoadURI", RedirectLoad);
@ -2322,11 +2323,11 @@ function readFromClipboard()
* If aArgsOrDocument is an object, that object can take the
* following properties:
*
* browser:
* The browser containing the document that we would like to view the
* source of.
* URL:
* URL (required):
* A string URL for the page we'd like to view the source of.
* browser (optional):
* The browser containing the document that we would like to view the
* source of. This is required if outerWindowID is passed.
* outerWindowID (optional):
* The outerWindowID of the content window containing the document that
* we want to view the source of. You only need to provide this if you
@ -2359,7 +2360,18 @@ function BrowserViewSourceOfDocument(aArgsOrDocument) {
args = aArgsOrDocument;
}
top.gViewSourceUtils.viewSource(args);
let inTab = Services.prefs.getBoolPref("view_source.tab");
if (inTab) {
let viewSourceURL = `view-source:${args.URL}`;
let tab = gBrowser.loadOneTab(viewSourceURL, {
relatedToCurrent: true,
inBackground: false
});
args.viewSourceBrowser = gBrowser.getBrowserForTab(tab);
top.gViewSourceUtils.viewSourceInBrowser(args);
} else {
top.gViewSourceUtils.viewSource(args);
}
}
/**

View File

@ -0,0 +1,161 @@
// -*- indent-tabs-mode: nil; js-indent-level: 2 -*-
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
const { utils: Cu, interfaces: Ci, classes: Cc } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
"resource://gre/modules/Deprecated.jsm");
this.EXPORTED_SYMBOLS = ["ViewSourceBrowser"];
/**
* ViewSourceBrowser manages the view source <browser> from the chrome side.
* It's companion frame script, viewSource-content.js, needs to be loaded as a
* frame script into the browser being managed.
*
* For a view source window using viewSource.xul, the script viewSource.js in
* the window extends an instance of this with more window specific functions.
* The page script takes care of loading the companion frame script.
*
* For a view source tab (or some other non-window case), an instance of this is
* created by viewSourceUtils.js to wrap the <browser>. The caller that manages
* the <browser> is responsible for ensuring the companion frame script has been
* loaded.
*/
this.ViewSourceBrowser = function ViewSourceBrowser(aBrowser) {
this._browser = aBrowser;
this.init();
}
ViewSourceBrowser.prototype = {
/**
* The <browser> that will be displaying the view source content.
*/
get browser() {
return this._browser;
},
/**
* 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: [
],
/**
* This should be called as soon as the script loads. When this function
* executes, we can assume the DOM content has not yet loaded.
*/
init() {
this.messages.forEach((msgName) => {
this.mm.addMessageListener(msgName, this);
});
},
/**
* This should be called when the window is closing. This function should
* clean up event and message listeners.
*/
uninit() {
this.messages.forEach((msgName) => {
this.mm.removeMessageListener(msgName, this);
});
},
/**
* Anything added to the messages array will get handled here, and should
* get dispatched to a specific function for the message name.
*/
receiveMessage(message) {
let data = message.data;
// TODO: Some messages will appear here in a later patch
switch(message.name) {
}
},
/**
* Getter for the message manager of the view source browser.
*/
get mm() {
return this.browser.messageManager;
},
/**
* Send a message to the view source browser.
*/
sendAsyncMessage(...args) {
this.browser.messageManager.sendAsyncMessage(...args);
},
/**
* Loads the source for a URL while applying some optional features if
* enabled.
*
* For the viewSource.xul window, this is called by onXULLoaded above.
* For view source in a specific browser, this is manually called after
* this object is constructed.
*
* This takes a single object argument containing:
*
* URL (required):
* A string URL for the page we'd like to view the source of.
* browser:
* The browser containing the document that we would like to view the
* source of. This argument is optional if outerWindowID is not passed.
* outerWindowID (optional):
* The outerWindowID of the content window containing the document that
* we want to view the source of. This is the only way of attempting to
* load the source out of the network cache.
* lineNumber (optional):
* The line number to focus on once the source is loaded.
*/
loadViewSource({ URL, browser, outerWindowID, lineNumber }) {
if (!URL) {
throw new Error("Must supply a URL when opening view source.");
}
if (browser) {
// If we're dealing with a remote browser, then the browser
// for view source needs to be remote as well.
this.updateBrowserRemoteness(browser.isRemoteBrowser);
} else {
if (outerWindowID) {
throw new Error("Must supply the browser if passing the outerWindowID");
}
}
this.sendAsyncMessage("ViewSource:LoadSource",
{ URL, outerWindowID, lineNumber });
},
/**
* Updates the "remote" attribute of the view source browser. This
* will remove the browser from the DOM, and then re-add it in the
* same place it was taken from.
*
* @param shouldBeRemote
* True if the browser should be made remote. If the browsers
* remoteness already matches this value, this function does
* nothing.
*/
updateBrowserRemoteness(shouldBeRemote) {
if (this.browser.isRemoteBrowser != shouldBeRemote) {
// In this base case, where we are handed a <browser> someone else is
// managing, we don't know for sure that it's safe to toggle remoteness.
// For view source in a window, this is overridden to actually do the
// flip if needed.
throw new Error("View source browser's remoteness mismatch");
}
},
};

View File

@ -40,11 +40,6 @@ function onLoadViewPartialSource()
else
viewPartialSourceForFragment(window.arguments[2], window.arguments[3]);
gBrowser.droppedLinkHandler = function (event, url, name) {
viewSource(url)
event.preventDefault();
}
window.content.focus();
}
@ -174,7 +169,7 @@ function viewPartialSourceForSelection(selection)
// all our content is held by the data:URI and URIs are internally stored as utf-8 (see nsIURI.idl)
var loadFlags = Components.interfaces.nsIWebNavigation.LOAD_FLAGS_NONE;
var referrerPolicy = Components.interfaces.nsIHttpChannel.REFERRER_POLICY_DEFAULT;
ViewSourceChrome.webNav.loadURIWithOptions((isHTML ?
viewSourceChrome.webNav.loadURIWithOptions((isHTML ?
"view-source:data:text/html;charset=utf-8," :
"view-source:data:application/xml;charset=utf-8,")
+ encodeURIComponent(tmpNode.innerHTML),

View File

@ -50,9 +50,9 @@
oncommand="document.getElementById('FindToolbar').onFindAgainCommand(false);"/>
<command id="cmd_findPrevious"
oncommand="document.getElementById('FindToolbar').onFindAgainCommand(true);"/>
<command id="cmd_goToLine" oncommand="ViewSourceChrome.promptAndGoToLine();" disabled="true"/>
<command id="cmd_highlightSyntax" oncommand="ViewSourceChrome.toggleSyntaxHighlighting();"/>
<command id="cmd_wrapLongLines" oncommand="ViewSourceChrome.toggleWrapping();"/>
<command id="cmd_goToLine" oncommand="viewSourceChrome.promptAndGoToLine();" disabled="true"/>
<command id="cmd_highlightSyntax" oncommand="viewSourceChrome.toggleSyntaxHighlighting();"/>
<command id="cmd_wrapLongLines" oncommand="viewSourceChrome.toggleWrapping();"/>
<command id="cmd_textZoomReduce" oncommand="ZoomManager.reduce();"/>
<command id="cmd_textZoomEnlarge" oncommand="ZoomManager.enlarge();"/>
<command id="cmd_textZoomReset" oncommand="ZoomManager.reset();"/>
@ -80,11 +80,11 @@
<menuitem id="context-copyLink"
label="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
oncommand="ViewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
oncommand="viewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
<menuitem id="context-copyEmail"
label="&copyEmailCmd.label;"
accesskey="&copyEmailCmd.accesskey;"
oncommand="ViewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
oncommand="viewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
<menuseparator/>
<menuitem id="cMenu_selectAll"/>
</menupopup>

View File

@ -51,6 +51,16 @@ let ViewSourceContent = {
*/
selectionListenerAttached: false,
get isViewSource() {
let uri = content.document.documentURI;
return uri.startsWith("view-source:");
},
get isAboutBlank() {
let uri = content.document.documentURI;
return uri == "about:blank";
},
/**
* This should be called as soon as this frame script has loaded.
*/
@ -93,6 +103,9 @@ let ViewSourceContent = {
* get dispatched to a specific function for the message name.
*/
receiveMessage(msg) {
if (!this.isViewSource && !this.isAboutBlank) {
return;
}
let data = msg.data;
let objects = msg.objects;
switch(msg.name) {
@ -124,6 +137,9 @@ let ViewSourceContent = {
* a specific function for the event type.
*/
handleEvent(event) {
if (!this.isViewSource) {
return;
}
switch(event.type) {
case "pagehide":
this.onPageHide(event);
@ -250,8 +266,13 @@ let ViewSourceContent = {
docShell.charset = forcedCharSet;
}
if (lineNumber) {
if (lineNumber && lineNumber > 0) {
let doneLoading = (event) => {
// Ignore possible initial load of about:blank
if (this.isAboutBlank ||
!content.document.body) {
return;
}
this.goToLine(lineNumber);
removeEventListener("pageshow", doneLoading);
};
@ -341,11 +362,12 @@ let ViewSourceContent = {
* The pageshow event being handled.
*/
onPageShow(event) {
content.getSelection()
.QueryInterface(Ci.nsISelectionPrivate)
.addSelectionListener(this);
this.selectionListenerAttached = true;
let selection = content.getSelection();
if (selection) {
selection.QueryInterface(Ci.nsISelectionPrivate)
.addSelectionListener(this);
this.selectionListenerAttached = true;
}
content.focus();
sendAsyncMessage("ViewSource:SourceLoaded");
},

View File

@ -7,6 +7,7 @@
const { utils: Cu, interfaces: Ci, classes: Cc } = Components;
Cu.import("resource://gre/modules/XPCOMUtils.jsm");
Cu.import("resource://gre/modules/ViewSourceBrowser.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
@ -31,9 +32,25 @@ XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
/**
* ViewSourceChrome is the primary interface for interacting with
* the view source browser. It initializes itself on script load.
* the view source browser from a self-contained window. It extends
* ViewSourceBrowser with additional things needed inside the special window.
*
* It initializes itself on script load.
*/
let ViewSourceChrome = {
function ViewSourceChrome() {
ViewSourceBrowser.call(this);
}
ViewSourceChrome.prototype = {
__proto__: ViewSourceBrowser.prototype,
/**
* The <browser> that will be displaying the view source content.
*/
get browser() {
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
@ -55,7 +72,7 @@ let ViewSourceChrome = {
* will automatically have ViewSourceChrome listen for those messages,
* and remove the listeners on teardown.
*/
messages: [
messages: ViewSourceBrowser.prototype.messages.concat([
"ViewSource:SourceLoaded",
"ViewSource:SourceUnloaded",
"ViewSource:Close",
@ -64,22 +81,15 @@ let ViewSourceChrome = {
"ViewSource:GoToLine:Failed",
"ViewSource:UpdateStatus",
"ViewSource:ContextMenuOpening",
],
]),
/**
* This should be called as soon as the script loads. When this function
* executes, we can assume the DOM content has not yet loaded.
* This called via ViewSourceBrowser's constructor. This should be called as
* soon as the script loads. When this function executes, we can assume the
* DOM content has not yet loaded.
*/
init() {
// We use the window message manager so that if we switch remoteness of the
// browser (which we might do if we're attempting to load the document
// source out of the network cache), we automatically re-load the frame
// script.
let wMM = window.messageManager;
wMM.loadFrameScript("chrome://global/content/viewSource-content.js", true);
this.messages.forEach((msgName) => {
wMM.addMessageListener(msgName, this);
});
this.mm.loadFrameScript("chrome://global/content/viewSource-content.js", true);
this.shouldWrap = Services.prefs.getBoolPref("view_source.wrap_long_lines");
this.shouldHighlight =
@ -89,6 +99,8 @@ let ViewSourceChrome = {
addEventListener("unload", this);
addEventListener("AppCommand", this, true);
addEventListener("MozSwipeGesture", this, true);
ViewSourceBrowser.prototype.init.call(this);
},
/**
@ -96,10 +108,7 @@ let ViewSourceChrome = {
* clean up event and message listeners.
*/
uninit() {
let wMM = window.messageManager;
this.messages.forEach((msgName) => {
wMM.removeMessageListener(msgName, this);
});
ViewSourceBrowser.prototype.uninit.call(this);
// "load" event listener is removed in its handler, to
// ensure we only fire it once.
@ -108,8 +117,9 @@ let ViewSourceChrome = {
removeEventListener("MozSwipeGesture", this, true);
gContextMenu.removeEventListener("popupshowing", this);
gContextMenu.removeEventListener("popuphidden", this);
Services.els.removeSystemEventListener(gBrowser, "dragover", this, true);
Services.els.removeSystemEventListener(gBrowser, "drop", this, true);
Services.els.removeSystemEventListener(this.browser, "dragover", this,
true);
Services.els.removeSystemEventListener(this.browser, "drop", this, true);
},
/**
@ -143,7 +153,7 @@ let ViewSourceChrome = {
break;
case "ViewSource:ContextMenuOpening":
this.onContextMenuOpening(data.isLink, data.isEmail, data.href);
if (gBrowser.isRemoteBrowser) {
if (this.browser.isRemoteBrowser) {
this.openContextMenu(data.screenX, data.screenY);
}
break;
@ -188,35 +198,42 @@ let ViewSourceChrome = {
* has history enabled on it.
*/
get historyEnabled() {
return !gBrowser.hasAttribute("disablehistory");
return !this.browser.hasAttribute("disablehistory");
},
/**
* Getter for the message manager of the view source browser.
* Getter for the message manager used to communicate with the view source
* browser.
*
* In this window version of view source, we use the window message manager
* for loading scripts and listening for messages so that if we switch
* remoteness of the browser (which we might do if we're attempting to load
* the document source out of the network cache), we automatically re-load
* the frame script.
*/
get mm() {
return gBrowser.messageManager;
return window.messageManager;
},
/**
* Getter for the nsIWebNavigation of the view source browser.
*/
get webNav() {
return gBrowser.webNavigation;
return this.browser.webNavigation;
},
/**
* Send the browser forward in its history.
*/
goForward() {
gBrowser.goForward();
this.browser.goForward();
},
/**
* Send the browser backward in its history.
*/
goBack() {
gBrowser.goBack();
this.browser.goBack();
},
/**
@ -267,8 +284,8 @@ let ViewSourceChrome = {
gContextMenu.addEventListener("popupshowing", this);
gContextMenu.addEventListener("popuphidden", this);
Services.els.addSystemEventListener(gBrowser, "dragover", this, true);
Services.els.addSystemEventListener(gBrowser, "drop", this, true);
Services.els.addSystemEventListener(this.browser, "dragover", this, true);
Services.els.addSystemEventListener(this.browser, "drop", this, true);
if (!this.historyEnabled) {
// Disable the BACK and FORWARD commands and hide the related menu items.
@ -279,12 +296,6 @@ let ViewSourceChrome = {
}
}
// This will only work with non-remote browsers. See bug 1158377.
gBrowser.droppedLinkHandler = function (event, url, name) {
ViewSourceChrome.loadURL(url);
event.preventDefault();
};
// We require the first argument to do any loading of source.
// otherwise, we're done.
if (!window.arguments[0]) {
@ -293,39 +304,20 @@ let ViewSourceChrome = {
if (typeof window.arguments[0] == "string") {
// We're using the deprecated API
return ViewSourceChrome._loadViewSourceDeprecated();
return this._loadViewSourceDeprecated(window.arguments);
}
// We're using the modern API, which allows us to view the
// source of documents from out of process browsers.
let args = window.arguments[0];
if (!args.URL) {
throw new Error("Must supply a URL when opening view source.");
}
if (args.browser) {
// If we're dealing with a remote browser, then the browser
// for view source needs to be remote as well.
this.updateBrowserRemoteness(args.browser.isRemoteBrowser);
} else {
if (args.outerWindowID) {
throw new Error("Must supply the browser if passing the outerWindowID");
}
}
this.mm.sendAsyncMessage("ViewSource:LoadSource", {
URL: args.URL,
outerWindowID: args.outerWindowID,
lineNumber: args.lineNumber,
});
this.loadViewSource(args);
},
/**
* This is the deprecated API for viewSource.xul, for old-timer consumers.
* This API might eventually go away.
*/
_loadViewSourceDeprecated() {
_loadViewSourceDeprecated(aArguments) {
Deprecated.warning("The arguments you're passing to viewSource.xul " +
"are using an out-of-date API.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
@ -336,34 +328,34 @@ let ViewSourceChrome = {
// arg[3] - Line number to go to.
// arg[4] - Whether charset was forced by the user
if (window.arguments[3] == "selection" ||
window.arguments[3] == "mathml") {
if (aArguments[3] == "selection" ||
aArguments[3] == "mathml") {
// viewPartialSource.js will take care of loading the content.
return;
}
if (window.arguments[2]) {
let pageDescriptor = window.arguments[2];
if (aArguments[2]) {
let pageDescriptor = aArguments[2];
if (Cu.isCrossProcessWrapper(pageDescriptor)) {
throw new Error("Cannot pass a CPOW as the page descriptor to viewSource.xul.");
}
}
if (gBrowser.isRemoteBrowser) {
if (this.browser.isRemoteBrowser) {
throw new Error("Deprecated view source API should not use a remote browser.");
}
let forcedCharSet;
if (window.arguments[4] && window.arguments[1].startsWith("charset=")) {
forcedCharSet = window.arguments[1].split("=")[1];
if (aArguments[4] && aArguments[1].startsWith("charset=")) {
forcedCharSet = aArguments[1].split("=")[1];
}
gBrowser.messageManager.sendAsyncMessage("ViewSource:LoadSourceDeprecated", {
URL: window.arguments[0],
lineNumber: window.arguments[3],
this.sendAsyncMessage("ViewSource:LoadSourceDeprecated", {
URL: aArguments[0],
lineNumber: aArguments[3],
forcedCharSet,
}, {
pageDescriptor: window.arguments[2],
pageDescriptor: aArguments[2],
});
},
@ -420,7 +412,7 @@ let ViewSourceChrome = {
this.updateCommands();
}
gBrowser.focus();
this.browser.focus();
},
/**
@ -446,13 +438,14 @@ let ViewSourceChrome = {
// If we don't have history enabled, we have to do a reload in order to
// show the character set change. See bug 136322.
this.mm.sendAsyncMessage("ViewSource:SetCharacterSet", {
this.sendAsyncMessage("ViewSource:SetCharacterSet", {
charset: charset,
doPageLoad: this.historyEnabled,
});
if (this.historyEnabled) {
gBrowser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
this.browser
.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
}
}
},
@ -583,7 +576,7 @@ let ViewSourceChrome = {
* A URL string to be opened in the view source browser.
*/
loadURL(URL) {
this.mm.sendAsyncMessage("ViewSource:LoadSource", { URL });
this.sendAsyncMessage("ViewSource:LoadSource", { URL });
},
/**
@ -656,7 +649,7 @@ let ViewSourceChrome = {
* The line number to try to go to to.
*/
goToLine(lineNumber) {
this.mm.sendAsyncMessage("ViewSource:GoToLine", { lineNumber });
this.sendAsyncMessage("ViewSource:GoToLine", { lineNumber });
},
/**
@ -690,8 +683,8 @@ let ViewSourceChrome = {
* Reloads the browser, bypassing the network cache.
*/
reload() {
gBrowser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
this.browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
},
/**
@ -710,7 +703,7 @@ let ViewSourceChrome = {
this.shouldWrap = !this.shouldWrap;
Services.prefs.setBoolPref("view_source.wrap_long_lines",
this.shouldWrap);
this.mm.sendAsyncMessage("ViewSource:ToggleWrapping");
this.sendAsyncMessage("ViewSource:ToggleWrapping");
},
/**
@ -725,7 +718,7 @@ let ViewSourceChrome = {
// occur.
Services.prefs.setBoolPref("view_source.syntax_highlight",
this.shouldHighlight);
this.mm.sendAsyncMessage("ViewSource:ToggleSyntaxHighlighting");
this.sendAsyncMessage("ViewSource:ToggleSyntaxHighlighting");
},
/**
@ -739,22 +732,22 @@ let ViewSourceChrome = {
* nothing.
*/
updateBrowserRemoteness(shouldBeRemote) {
if (gBrowser.isRemoteBrowser == shouldBeRemote) {
if (this.browser.isRemoteBrowser == shouldBeRemote) {
return;
}
let parentNode = gBrowser.parentNode;
let nextSibling = gBrowser.nextSibling;
let parentNode = this.browser.parentNode;
let nextSibling = this.browser.nextSibling;
gBrowser.remove();
this.browser.remove();
if (shouldBeRemote) {
gBrowser.setAttribute("remote", "true");
this.browser.setAttribute("remote", "true");
} else {
gBrowser.removeAttribute("remote");
this.browser.removeAttribute("remote");
}
// If nextSibling was null, this will put the browser at
// the end of the list.
parentNode.insertBefore(gBrowser, nextSibling);
parentNode.insertBefore(this.browser, nextSibling);
if (shouldBeRemote) {
// We're going to send a message down to the remote browser
@ -764,14 +757,14 @@ let ViewSourceChrome = {
// RemoteWebProgress, which is lazily loaded. We only need
// contentWindowAsCPOW for the printing support, and this
// should go away once bug 1146454 is fixed, since we can
// then just pass the outerWindowID of the gBrowser to
// then just pass the outerWindowID of the this.browser to
// PrintUtils.
gBrowser.webProgress;
this.browser.webProgress;
}
},
};
ViewSourceChrome.init();
let viewSourceChrome = new ViewSourceChrome();
/**
* PrintUtils uses this to make Print Preview work.
@ -820,7 +813,7 @@ function getBrowser() {
}
this.__defineGetter__("gPageLoader", function () {
var webnav = ViewSourceChrome.webNav;
var webnav = viewSourceChrome.webNav;
if (!webnav)
return null;
delete this.gPageLoader;
@ -843,48 +836,48 @@ function ViewSourceSavePage()
this.__defineGetter__("gLastLineFound", function () {
Deprecated.warning("gLastLineFound is deprecated - please use " +
"ViewSourceChrome.lastLineFound instead.",
"viewSourceChrome.lastLineFound instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
return ViewSourceChrome.lastLineFound;
return viewSourceChrome.lastLineFound;
});
function onLoadViewSource() {
Deprecated.warning("onLoadViewSource() is deprecated - please use " +
"ViewSourceChrome.onXULLoaded() instead.",
"viewSourceChrome.onXULLoaded() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.onXULLoaded();
viewSourceChrome.onXULLoaded();
}
function isHistoryEnabled() {
Deprecated.warning("isHistoryEnabled() is deprecated - please use " +
"ViewSourceChrome.historyEnabled instead.",
"viewSourceChrome.historyEnabled instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
return ViewSourceChrome.historyEnabled;
return viewSourceChrome.historyEnabled;
}
function ViewSourceClose() {
Deprecated.warning("ViewSourceClose() is deprecated - please use " +
"ViewSourceChrome.close() instead.",
"viewSourceChrome.close() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.close();
viewSourceChrome.close();
}
function ViewSourceReload() {
Deprecated.warning("ViewSourceReload() is deprecated - please use " +
"ViewSourceChrome.reload() instead.",
"viewSourceChrome.reload() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.reload();
viewSourceChrome.reload();
}
function getWebNavigation()
{
Deprecated.warning("getWebNavigation() is deprecated - please use " +
"ViewSourceChrome.webNav instead.",
"viewSourceChrome.webNav instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
// The original implementation returned null if anything threw during
// the getting of the webNavigation.
try {
return ViewSourceChrome.webNav;
return viewSourceChrome.webNav;
} catch (e) {
return null;
}
@ -892,44 +885,44 @@ function getWebNavigation()
function viewSource(url) {
Deprecated.warning("viewSource() is deprecated - please use " +
"ViewSourceChrome.loadURL() instead.",
"viewSourceChrome.loadURL() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.loadURL(url);
viewSourceChrome.loadURL(url);
}
function ViewSourceGoToLine()
{
Deprecated.warning("ViewSourceGoToLine() is deprecated - please use " +
"ViewSourceChrome.promptAndGoToLine() instead.",
"viewSourceChrome.promptAndGoToLine() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.promptAndGoToLine();
viewSourceChrome.promptAndGoToLine();
}
function goToLine(line)
{
Deprecated.warning("goToLine() is deprecated - please use " +
"ViewSourceChrome.goToLine() instead.",
"viewSourceChrome.goToLine() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.goToLine(line);
viewSourceChrome.goToLine(line);
}
function BrowserForward(aEvent) {
Deprecated.warning("BrowserForward() is deprecated - please use " +
"ViewSourceChrome.goForward() instead.",
"viewSourceChrome.goForward() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.goForward();
viewSourceChrome.goForward();
}
function BrowserBack(aEvent) {
Deprecated.warning("BrowserBack() is deprecated - please use " +
"ViewSourceChrome.goBack() instead.",
"viewSourceChrome.goBack() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.goBack();
viewSourceChrome.goBack();
}
function UpdateBackForwardCommands() {
Deprecated.warning("UpdateBackForwardCommands() is deprecated - please use " +
"ViewSourceChrome.updateCommands() instead.",
"viewSourceChrome.updateCommands() instead.",
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
ViewSourceChrome.updateCommands();
viewSourceChrome.updateCommands();
}

View File

@ -54,16 +54,16 @@
<command id="cmd_findSelection"
oncommand="document.getElementById('FindToolbar').onFindSelectionCommand();"/>
#endif
<command id="cmd_reload" oncommand="ViewSourceChrome.reload();"/>
<command id="cmd_goToLine" oncommand="ViewSourceChrome.promptAndGoToLine();" disabled="true"/>
<command id="cmd_highlightSyntax" oncommand="ViewSourceChrome.toggleSyntaxHighlighting();"/>
<command id="cmd_wrapLongLines" oncommand="ViewSourceChrome.toggleWrapping();"/>
<command id="cmd_reload" oncommand="viewSourceChrome.reload();"/>
<command id="cmd_goToLine" oncommand="viewSourceChrome.promptAndGoToLine();" disabled="true"/>
<command id="cmd_highlightSyntax" oncommand="viewSourceChrome.toggleSyntaxHighlighting();"/>
<command id="cmd_wrapLongLines" oncommand="viewSourceChrome.toggleWrapping();"/>
<command id="cmd_textZoomReduce" oncommand="ZoomManager.reduce();"/>
<command id="cmd_textZoomEnlarge" oncommand="ZoomManager.enlarge();"/>
<command id="cmd_textZoomReset" oncommand="ZoomManager.reset();"/>
<command id="Browser:Back" oncommand="ViewSourceChrome.goBack()" observes="viewSourceNavigation"/>
<command id="Browser:Forward" oncommand="ViewSourceChrome.goForward()" observes="viewSourceNavigation"/>
<command id="Browser:Back" oncommand="viewSourceChrome.goBack()" observes="viewSourceNavigation"/>
<command id="Browser:Forward" oncommand="viewSourceChrome.goForward()" observes="viewSourceNavigation"/>
<broadcaster id="viewSourceNavigation"/>
@ -131,11 +131,11 @@
<menuitem id="context-copyLink"
label="&copyLinkCmd.label;"
accesskey="&copyLinkCmd.accesskey;"
oncommand="ViewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
oncommand="viewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
<menuitem id="context-copyEmail"
label="&copyEmailCmd.label;"
accesskey="&copyEmailCmd.accesskey;"
oncommand="ViewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
oncommand="viewSourceChrome.onContextMenuCopyLinkOrEmail();"/>
<menuseparator/>
<menuitem id="cMenu_selectAll"/>
</menupopup>
@ -206,7 +206,7 @@
<menu id="charsetMenu"
label="&charsetMenu2.label;"
accesskey="&charsetMenu2.accesskey;"
oncommand="ViewSourceChrome.onSetCharacterSet(event);"
oncommand="viewSourceChrome.onSetCharacterSet(event);"
onpopupshowing="CharsetMenu.build(event.target);"
onpopupshown="CharsetMenu.update(event.target, content.document.characterSet);">
<menupopup/>

View File

@ -12,6 +12,10 @@
* getDefaultFileName, getNormalizedLeafName and getDefaultExtension
*/
Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "ViewSourceBrowser",
"resource://gre/modules/ViewSourceBrowser.jsm");
var gViewSourceUtils = {
mnsIWebBrowserPersist: Components.interfaces.nsIWebBrowserPersist,
@ -60,6 +64,34 @@ var gViewSourceUtils = {
}
},
/**
* Displays view source in the provided <browser>. This allows for non-window
* display methods, such as a tab from Firefox. The caller that manages
* the <browser> is responsible for ensuring the companion frame script,
* viewSource-content.js, has been loaded for the <browser>.
*
* @param aArgs
* An object with the following properties:
*
* URL (required):
* A string URL for the page we'd like to view the source of.
* viewSourceBrowser (required):
* The browser to display the view source in.
* browser (optional):
* The browser containing the document that we would like to view the
* source of. This is required if outerWindowID is passed.
* outerWindowID (optional):
* The outerWindowID of the content window containing the document that
* we want to view the source of. Pass this if you want to attempt to
* load the document source out of the network cache.
* lineNumber (optional):
* The line number to focus on once the source is loaded.
*/
viewSourceInBrowser: function(aArgs) {
let viewSourceBrowser = new ViewSourceBrowser(aArgs.viewSourceBrowser);
viewSourceBrowser.loadViewSource(aArgs);
},
// Opens the interval view source viewer
_openInInternalViewer: function(aArgsOrURL, aPageDescriptor, aDocument, aLineNumber)
{

View File

@ -9,4 +9,4 @@ toolkit.jar:
content/global/viewPartialSource.js (content/viewPartialSource.js)
* content/global/viewPartialSource.xul (content/viewPartialSource.xul)
content/global/viewSourceUtils.js (content/viewSourceUtils.js)
content/global/viewSource-content.js (content/viewSource-content.js)
content/global/viewSource-content.js (content/viewSource-content.js)

View File

@ -9,5 +9,9 @@ MOCHITEST_CHROME_MANIFESTS += ['test/chrome.ini']
JAR_MANIFESTS += ['jar.mn']
EXTRA_JS_MODULES += [
'ViewSourceBrowser.jsm',
]
with Files('**'):
BUG_COMPONENT = ('Toolkit', 'View Source')

View File

@ -24,7 +24,7 @@ let checkViewSource = Task.async(function* (aWindow) {
is(statusPanel.getAttribute("label"), "", "Correct status bar text");
for (let i = 1; i <= 3; i++) {
aWindow.ViewSourceChrome.goToLine(i);
aWindow.viewSourceChrome.goToLine(i);
let result = yield ContentTask.spawn(aWindow.gBrowser, i, function*(i) {
let selection = content.getSelection();
return (selection.toString() == "line " + i);