mirror of
https://github.com/classilla/tenfourfox.git
synced 2025-01-28 21:31:38 +00:00
869 lines
27 KiB
JavaScript
869 lines
27 KiB
JavaScript
// -*- 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/. */
|
|
|
|
var { 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");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
|
|
"resource://gre/modules/CharsetMenu.jsm");
|
|
XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
|
|
"resource://gre/modules/Deprecated.jsm");
|
|
|
|
[
|
|
["gBrowser", "content"],
|
|
["gViewSourceBundle", "viewSourceBundle"],
|
|
["gContextMenu", "viewSourceContextMenu"]
|
|
].forEach(function ([name, id]) {
|
|
window.__defineGetter__(name, function () {
|
|
var element = document.getElementById(id);
|
|
if (!element)
|
|
return null;
|
|
delete window[name];
|
|
return window[name] = element;
|
|
});
|
|
});
|
|
|
|
/**
|
|
* ViewSourceChrome is the primary interface for interacting with
|
|
* 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.
|
|
*/
|
|
function ViewSourceChrome() {
|
|
ViewSourceBrowser.call(this);
|
|
}
|
|
|
|
ViewSourceChrome.prototype = {
|
|
__proto__: ViewSourceBrowser.prototype,
|
|
|
|
/**
|
|
* The <browser> that will be displaying the view source content.
|
|
*/
|
|
get browser() {
|
|
return gBrowser;
|
|
},
|
|
|
|
/**
|
|
* The context menu, when opened from the content process, sends
|
|
* up a chunk of serialized data describing the items that the
|
|
* context menu is being opened on. This allows us to avoid using
|
|
* CPOWs.
|
|
*/
|
|
contextMenuData: {},
|
|
|
|
/**
|
|
* These are the messages that ViewSourceChrome will listen for
|
|
* from the frame script it injects. Any message names added here
|
|
* will automatically have ViewSourceChrome listen for those messages,
|
|
* and remove the listeners on teardown.
|
|
*/
|
|
messages: ViewSourceBrowser.prototype.messages.concat([
|
|
"ViewSource:SourceLoaded",
|
|
"ViewSource:SourceUnloaded",
|
|
"ViewSource:Close",
|
|
"ViewSource:OpenURL",
|
|
"ViewSource:UpdateStatus",
|
|
"ViewSource:ContextMenuOpening",
|
|
]),
|
|
|
|
/**
|
|
* 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() {
|
|
this.mm.loadFrameScript("chrome://global/content/viewSource-content.js", true);
|
|
|
|
this.shouldWrap = Services.prefs.getBoolPref("view_source.wrap_long_lines");
|
|
this.shouldHighlight =
|
|
Services.prefs.getBoolPref("view_source.syntax_highlight");
|
|
|
|
addEventListener("load", this);
|
|
addEventListener("unload", this);
|
|
addEventListener("AppCommand", this, true);
|
|
addEventListener("MozSwipeGesture", this, true);
|
|
|
|
ViewSourceBrowser.prototype.init.call(this);
|
|
},
|
|
|
|
/**
|
|
* This should be called when the window is closing. This function should
|
|
* clean up event and message listeners.
|
|
*/
|
|
uninit() {
|
|
ViewSourceBrowser.prototype.uninit.call(this);
|
|
|
|
// "load" event listener is removed in its handler, to
|
|
// ensure we only fire it once.
|
|
removeEventListener("unload", this);
|
|
removeEventListener("AppCommand", this, true);
|
|
removeEventListener("MozSwipeGesture", this, true);
|
|
gContextMenu.removeEventListener("popupshowing", this);
|
|
gContextMenu.removeEventListener("popuphidden", this);
|
|
Services.els.removeSystemEventListener(this.browser, "dragover", this,
|
|
true);
|
|
Services.els.removeSystemEventListener(this.browser, "drop", this, true);
|
|
},
|
|
|
|
/**
|
|
* 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;
|
|
|
|
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;
|
|
case "ViewSource:StoreWrapping":
|
|
this.storeWrapping(data.state);
|
|
break;
|
|
case "ViewSource:StoreSyntaxHighlighting":
|
|
this.storeSyntaxHighlighting(data.state);
|
|
break;
|
|
// End messages from super class
|
|
case "ViewSource:SourceLoaded":
|
|
this.onSourceLoaded();
|
|
break;
|
|
case "ViewSource:SourceUnloaded":
|
|
this.onSourceUnloaded();
|
|
break;
|
|
case "ViewSource:Close":
|
|
this.close();
|
|
break;
|
|
case "ViewSource:OpenURL":
|
|
this.openURL(data.URL);
|
|
break;
|
|
case "ViewSource:UpdateStatus":
|
|
this.updateStatus(data.label);
|
|
break;
|
|
case "ViewSource:ContextMenuOpening":
|
|
this.onContextMenuOpening(data.isLink, data.isEmail, data.href);
|
|
if (this.browser.isRemoteBrowser) {
|
|
this.openContextMenu(data.screenX, data.screenY);
|
|
}
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Any events should get handled here, and should get dispatched to
|
|
* a specific function for the event type.
|
|
*/
|
|
handleEvent(event) {
|
|
switch(event.type) {
|
|
case "unload":
|
|
this.uninit();
|
|
break;
|
|
case "load":
|
|
this.onXULLoaded();
|
|
break;
|
|
case "AppCommand":
|
|
this.onAppCommand(event);
|
|
break;
|
|
case "MozSwipeGesture":
|
|
this.onSwipeGesture(event);
|
|
break;
|
|
case "popupshowing":
|
|
this.onContextMenuShowing(event);
|
|
break;
|
|
case "popuphidden":
|
|
this.onContextMenuHidden(event);
|
|
break;
|
|
case "dragover":
|
|
this.onDragOver(event);
|
|
break;
|
|
case "drop":
|
|
this.onDrop(event);
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Getter that returns whether or not the view source browser
|
|
* has history enabled on it.
|
|
*/
|
|
get historyEnabled() {
|
|
return !this.browser.hasAttribute("disablehistory");
|
|
},
|
|
|
|
/**
|
|
* 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 window.messageManager;
|
|
},
|
|
|
|
/**
|
|
* Getter for the nsIWebNavigation of the view source browser.
|
|
*/
|
|
get webNav() {
|
|
return this.browser.webNavigation;
|
|
},
|
|
|
|
/**
|
|
* Send the browser forward in its history.
|
|
*/
|
|
goForward() {
|
|
this.browser.goForward();
|
|
},
|
|
|
|
/**
|
|
* Send the browser backward in its history.
|
|
*/
|
|
goBack() {
|
|
this.browser.goBack();
|
|
},
|
|
|
|
/**
|
|
* This should be called once when the DOM has finished loading. Here we
|
|
* set the state of various menu items, and add event listeners to
|
|
* DOM nodes.
|
|
*
|
|
* This is also the place where we handle any arguments that have been
|
|
* passed to viewSource.xul.
|
|
*
|
|
* Modern consumers should pass a single object argument to viewSource.xul:
|
|
*
|
|
* 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.
|
|
*
|
|
* The deprecated API has the opener pass in a number of arguments:
|
|
*
|
|
* arg[0] - URL string.
|
|
* arg[1] - Charset value string in the form 'charset=xxx'.
|
|
* arg[2] - Page descriptor from nsIWebPageDescriptor used to load content
|
|
* from the cache.
|
|
* arg[3] - Line number to go to.
|
|
* arg[4] - Boolean for whether charset was forced by the user
|
|
*/
|
|
onXULLoaded() {
|
|
// This handler should only ever run the first time the XUL is loaded.
|
|
removeEventListener("load", this);
|
|
|
|
let wrapMenuItem = document.getElementById("menu_wrapLongLines");
|
|
if (this.shouldWrap) {
|
|
wrapMenuItem.setAttribute("checked", "true");
|
|
}
|
|
|
|
let highlightMenuItem = document.getElementById("menu_highlightSyntax");
|
|
if (this.shouldHighlight) {
|
|
highlightMenuItem.setAttribute("checked", "true");
|
|
}
|
|
|
|
gContextMenu.addEventListener("popupshowing", this);
|
|
gContextMenu.addEventListener("popuphidden", this);
|
|
|
|
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.
|
|
let viewSourceNavigation = document.getElementById("viewSourceNavigation");
|
|
if (viewSourceNavigation) {
|
|
viewSourceNavigation.setAttribute("disabled", "true");
|
|
viewSourceNavigation.setAttribute("hidden", "true");
|
|
}
|
|
}
|
|
|
|
// We require the first argument to do any loading of source.
|
|
// otherwise, we're done.
|
|
if (!window.arguments[0]) {
|
|
return;
|
|
}
|
|
|
|
if (typeof window.arguments[0] == "string") {
|
|
// We're using the deprecated API
|
|
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];
|
|
|
|
// viewPartialSource.js will take care of loading the content in partial mode.
|
|
if (!args.partial) {
|
|
this.loadViewSource(args);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* This is the deprecated API for viewSource.xul, for old-timer consumers.
|
|
* This API might eventually go away.
|
|
*/
|
|
_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");
|
|
// Parse the 'arguments' supplied with the dialog.
|
|
// arg[0] - URL string.
|
|
// arg[1] - Charset value in the form 'charset=xxx'.
|
|
// arg[2] - Page descriptor used to load content from the cache.
|
|
// arg[3] - Line number to go to.
|
|
// arg[4] - Whether charset was forced by the user
|
|
|
|
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 (this.browser.isRemoteBrowser) {
|
|
throw new Error("Deprecated view source API should not use a remote browser.");
|
|
}
|
|
|
|
let forcedCharSet;
|
|
if (aArguments[4] && aArguments[1].startsWith("charset=")) {
|
|
forcedCharSet = aArguments[1].split("=")[1];
|
|
}
|
|
|
|
this.sendAsyncMessage("ViewSource:LoadSourceDeprecated", {
|
|
URL: aArguments[0],
|
|
lineNumber: aArguments[3],
|
|
forcedCharSet,
|
|
}, {
|
|
pageDescriptor: aArguments[2],
|
|
});
|
|
},
|
|
|
|
/**
|
|
* Handler for the AppCommand event.
|
|
*
|
|
* @param event
|
|
* The AppCommand event being handled.
|
|
*/
|
|
onAppCommand(event) {
|
|
event.stopPropagation();
|
|
switch (event.command) {
|
|
case "Back":
|
|
this.goBack();
|
|
break;
|
|
case "Forward":
|
|
this.goForward();
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Handler for the MozSwipeGesture event.
|
|
*
|
|
* @param event
|
|
* The MozSwipeGesture event being handled.
|
|
*/
|
|
onSwipeGesture(event) {
|
|
event.stopPropagation();
|
|
switch (event.direction) {
|
|
case SimpleGestureEvent.DIRECTION_LEFT:
|
|
this.goBack();
|
|
break;
|
|
case SimpleGestureEvent.DIRECTION_RIGHT:
|
|
this.goForward();
|
|
break;
|
|
case SimpleGestureEvent.DIRECTION_UP:
|
|
goDoCommand("cmd_scrollTop");
|
|
break;
|
|
case SimpleGestureEvent.DIRECTION_DOWN:
|
|
goDoCommand("cmd_scrollBottom");
|
|
break;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called as soon as the frame script reports that some source
|
|
* code has been loaded in the browser.
|
|
*/
|
|
onSourceLoaded() {
|
|
document.getElementById("cmd_goToLine").removeAttribute("disabled");
|
|
|
|
if (this.historyEnabled) {
|
|
this.updateCommands();
|
|
}
|
|
|
|
this.browser.focus();
|
|
},
|
|
|
|
/**
|
|
* Called as soon as the frame script reports that some source
|
|
* code has been unloaded from the browser.
|
|
*/
|
|
onSourceUnloaded() {
|
|
// Disable "go to line" while reloading due to e.g. change of charset
|
|
// or toggling of syntax highlighting.
|
|
document.getElementById("cmd_goToLine").setAttribute("disabled", "true");
|
|
},
|
|
|
|
/**
|
|
* Called by clicks on a menu populated by CharsetMenu.jsm to
|
|
* change the selected character set.
|
|
*
|
|
* @param event
|
|
* The click event on a character set menuitem.
|
|
*/
|
|
onSetCharacterSet(event) {
|
|
if (event.target.hasAttribute("charset")) {
|
|
let charset = event.target.getAttribute("charset");
|
|
|
|
// 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.sendAsyncMessage("ViewSource:SetCharacterSet", {
|
|
charset: charset,
|
|
doPageLoad: this.historyEnabled,
|
|
});
|
|
|
|
if (!this.historyEnabled) {
|
|
this.browser
|
|
.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
|
|
}
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called from the frame script when the context menu is about to
|
|
* open. This tells ViewSourceChrome things about the item that
|
|
* the context menu is being opened on. This should be called before
|
|
* the popupshowing event handler fires.
|
|
*/
|
|
onContextMenuOpening(isLink, isEmail, href) {
|
|
this.contextMenuData = { isLink, isEmail, href, isOpen: true };
|
|
},
|
|
|
|
/**
|
|
* Event handler for the popupshowing event on the context menu.
|
|
* This handler is responsible for setting the state on various
|
|
* menu items in the context menu, and reads values that were sent
|
|
* up from the frame script and stashed into this.contextMenuData.
|
|
*
|
|
* @param event
|
|
* The popupshowing event for the context menu.
|
|
*/
|
|
onContextMenuShowing(event) {
|
|
let copyLinkMenuItem = document.getElementById("context-copyLink");
|
|
copyLinkMenuItem.hidden = !this.contextMenuData.isLink;
|
|
|
|
let copyEmailMenuItem = document.getElementById("context-copyEmail");
|
|
copyEmailMenuItem.hidden = !this.contextMenuData.isEmail;
|
|
},
|
|
|
|
/**
|
|
* Called when the user chooses the "Copy Link" or "Copy Email"
|
|
* menu items in the context menu. Copies the relevant selection
|
|
* into the system clipboard.
|
|
*/
|
|
onContextMenuCopyLinkOrEmail() {
|
|
// It doesn't make any sense to call this if the context menu
|
|
// isn't open...
|
|
if (!this.contextMenuData.isOpen) {
|
|
return;
|
|
}
|
|
|
|
let clipboard = Cc["@mozilla.org/widget/clipboardhelper;1"]
|
|
.getService(Ci.nsIClipboardHelper);
|
|
clipboard.copyString(this.contextMenuData.href);
|
|
},
|
|
|
|
/**
|
|
* Called when the context menu closes, and invalidates any data
|
|
* that the frame script might have sent up about what the context
|
|
* menu was opened on.
|
|
*/
|
|
onContextMenuHidden(event) {
|
|
this.contextMenuData = {
|
|
isOpen: false,
|
|
};
|
|
},
|
|
|
|
/**
|
|
* Called when the user drags something over the content browser.
|
|
*/
|
|
onDragOver(event) {
|
|
// For drags that appear to be internal text (for example, tab drags),
|
|
// set the dropEffect to 'none'. This prevents the drop even if some
|
|
// other listener cancelled the event.
|
|
let types = event.dataTransfer.types;
|
|
if (types.contains("text/x-moz-text-internal") && !types.contains("text/plain")) {
|
|
event.dataTransfer.dropEffect = "none";
|
|
event.stopPropagation();
|
|
event.preventDefault();
|
|
}
|
|
|
|
let linkHandler = Cc["@mozilla.org/content/dropped-link-handler;1"]
|
|
.getService(Ci.nsIDroppedLinkHandler);
|
|
|
|
if (linkHandler.canDropLink(event, false)) {
|
|
event.preventDefault();
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Called twhen the user drops something onto the content browser.
|
|
*/
|
|
onDrop(event) {
|
|
if (event.defaultPrevented)
|
|
return;
|
|
|
|
let name = { };
|
|
let linkHandler = Cc["@mozilla.org/content/dropped-link-handler;1"]
|
|
.getService(Ci.nsIDroppedLinkHandler);
|
|
let uri;
|
|
try {
|
|
// Pass true to prevent the dropping of javascript:/data: URIs
|
|
uri = linkHandler.dropLink(event, name, true);
|
|
} catch (e) {
|
|
return;
|
|
}
|
|
|
|
if (uri) {
|
|
this.loadURL(uri);
|
|
}
|
|
},
|
|
|
|
/**
|
|
* For remote browsers, the contextmenu event is received in the
|
|
* content process, and a message is sent up from the frame script
|
|
* to ViewSourceChrome, but then it stops. The event does not bubble
|
|
* up to the point that the popup is opened in the parent process.
|
|
* ViewSourceChrome is responsible for opening up the context menu in
|
|
* that case. This is called when we receive the contextmenu message
|
|
* from the child, and we know that the browser is currently remote.
|
|
*
|
|
* @param screenX
|
|
* The screenX coordinate to open the popup at.
|
|
* @param screenY
|
|
* The screenY coordinate to open the popup at.
|
|
*/
|
|
openContextMenu(screenX, screenY) {
|
|
gContextMenu.openPopupAtScreen(screenX, screenY, true);
|
|
},
|
|
|
|
/**
|
|
* Loads the source of a URL. This will probably end up hitting the
|
|
* network.
|
|
*
|
|
* @param URL
|
|
* A URL string to be opened in the view source browser.
|
|
*/
|
|
loadURL(URL) {
|
|
this.sendAsyncMessage("ViewSource:LoadSource", { URL });
|
|
},
|
|
|
|
/**
|
|
* Updates any commands that are dependant on command broadcasters.
|
|
*/
|
|
updateCommands() {
|
|
let backBroadcaster = document.getElementById("Browser:Back");
|
|
let forwardBroadcaster = document.getElementById("Browser:Forward");
|
|
|
|
if (this.webNav.canGoBack) {
|
|
backBroadcaster.removeAttribute("disabled");
|
|
} else {
|
|
backBroadcaster.setAttribute("disabled", "true");
|
|
}
|
|
if (this.webNav.canGoForward) {
|
|
forwardBroadcaster.removeAttribute("disabled");
|
|
} else {
|
|
forwardBroadcaster.setAttribute("disabled", "true");
|
|
}
|
|
},
|
|
|
|
/**
|
|
* Updates the status displayed in the status bar of the view source window.
|
|
*
|
|
* @param label
|
|
* The string to be displayed in the statusbar-lin-col element.
|
|
*/
|
|
updateStatus(label) {
|
|
let statusBarField = document.getElementById("statusbar-line-col");
|
|
if (statusBarField) {
|
|
statusBarField.label = label;
|
|
}
|
|
},
|
|
|
|
/**
|
|
* 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) {
|
|
ViewSourceBrowser.prototype.onGoToLineSuccess.call(this, lineNumber);
|
|
document.getElementById("statusbar-line-col").label =
|
|
gViewSourceBundle.getFormattedString("statusBarLineCol", [lineNumber, 1]);
|
|
},
|
|
|
|
/**
|
|
* Reloads the browser, bypassing the network cache.
|
|
*/
|
|
reload() {
|
|
this.browser.reloadWithFlags(Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY |
|
|
Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE);
|
|
},
|
|
|
|
/**
|
|
* Closes the view source window.
|
|
*/
|
|
close() {
|
|
window.close();
|
|
},
|
|
|
|
/**
|
|
* Called when the user clicks on the "Wrap Long Lines" menu item.
|
|
*/
|
|
toggleWrapping() {
|
|
this.shouldWrap = !this.shouldWrap;
|
|
this.sendAsyncMessage("ViewSource:ToggleWrapping");
|
|
},
|
|
|
|
/**
|
|
* Called when the user clicks on the "Syntax Highlighting" menu item.
|
|
*/
|
|
toggleSyntaxHighlighting() {
|
|
this.shouldHighlight = !this.shouldHighlight;
|
|
this.sendAsyncMessage("ViewSource:ToggleSyntaxHighlighting");
|
|
},
|
|
|
|
/**
|
|
* 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) {
|
|
return;
|
|
}
|
|
|
|
let parentNode = this.browser.parentNode;
|
|
let nextSibling = this.browser.nextSibling;
|
|
|
|
this.browser.remove();
|
|
if (shouldBeRemote) {
|
|
this.browser.setAttribute("remote", "true");
|
|
} else {
|
|
this.browser.removeAttribute("remote");
|
|
}
|
|
// If nextSibling was null, this will put the browser at
|
|
// the end of the list.
|
|
parentNode.insertBefore(this.browser, nextSibling);
|
|
|
|
if (shouldBeRemote) {
|
|
// We're going to send a message down to the remote browser
|
|
// to load the source content - however, in order for the
|
|
// contentWindowAsCPOW and contentDocumentAsCPOW values on
|
|
// the remote browser to be set, we must set up the
|
|
// 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 this.browser to
|
|
// PrintUtils.
|
|
this.browser.webProgress;
|
|
}
|
|
},
|
|
};
|
|
|
|
var viewSourceChrome = new ViewSourceChrome();
|
|
|
|
/**
|
|
* PrintUtils uses this to make Print Preview work.
|
|
*/
|
|
var PrintPreviewListener = {
|
|
_ppBrowser: null,
|
|
|
|
getPrintPreviewBrowser() {
|
|
if (!this._ppBrowser) {
|
|
this._ppBrowser = document.createElement("browser");
|
|
this._ppBrowser.setAttribute("flex", "1");
|
|
this._ppBrowser.setAttribute("type", "content");
|
|
}
|
|
|
|
if (gBrowser.isRemoteBrowser) {
|
|
this._ppBrowser.setAttribute("remote", "true");
|
|
} else {
|
|
this._ppBrowser.removeAttribute("remote");
|
|
}
|
|
|
|
let findBar = document.getElementById("FindToolbar");
|
|
document.getElementById("appcontent")
|
|
.insertBefore(this._ppBrowser, findBar);
|
|
|
|
return this._ppBrowser;
|
|
},
|
|
|
|
getSourceBrowser() {
|
|
return gBrowser;
|
|
},
|
|
|
|
getNavToolbox() {
|
|
return document.getElementById("appcontent");
|
|
},
|
|
|
|
onEnter() {
|
|
let toolbox = document.getElementById("viewSource-toolbox");
|
|
toolbox.hidden = true;
|
|
gBrowser.collapsed = true;
|
|
},
|
|
|
|
onExit() {
|
|
this._ppBrowser.remove();
|
|
gBrowser.collapsed = false;
|
|
document.getElementById("viewSource-toolbox").hidden = false;
|
|
},
|
|
};
|
|
|
|
// viewZoomOverlay.js uses this
|
|
function getBrowser() {
|
|
return gBrowser;
|
|
}
|
|
|
|
this.__defineGetter__("gPageLoader", function () {
|
|
var webnav = viewSourceChrome.webNav;
|
|
if (!webnav)
|
|
return null;
|
|
delete this.gPageLoader;
|
|
this.gPageLoader = (webnav instanceof Ci.nsIWebPageDescriptor) ? webnav
|
|
: null;
|
|
return this.gPageLoader;
|
|
});
|
|
|
|
// Strips the |view-source:| for internalSave()
|
|
function ViewSourceSavePage()
|
|
{
|
|
internalSave(gBrowser.currentURI.spec.replace(/^view-source:/i, ""),
|
|
null, null, null, null, null, "SaveLinkTitle",
|
|
null, null, gBrowser.contentDocumentAsCPOW, null,
|
|
gPageLoader);
|
|
}
|
|
|
|
// Below are old deprecated functions and variables left behind for
|
|
// compatibility reasons. These will be removed soon via bug 1159293.
|
|
|
|
this.__defineGetter__("gLastLineFound", function () {
|
|
Deprecated.warning("gLastLineFound is deprecated - please use " +
|
|
"viewSourceChrome.lastLineFound instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
return viewSourceChrome.lastLineFound;
|
|
});
|
|
|
|
function onLoadViewSource() {
|
|
Deprecated.warning("onLoadViewSource() is deprecated - please use " +
|
|
"viewSourceChrome.onXULLoaded() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.onXULLoaded();
|
|
}
|
|
|
|
function isHistoryEnabled() {
|
|
Deprecated.warning("isHistoryEnabled() is deprecated - please use " +
|
|
"viewSourceChrome.historyEnabled instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
return viewSourceChrome.historyEnabled;
|
|
}
|
|
|
|
function ViewSourceClose() {
|
|
Deprecated.warning("ViewSourceClose() is deprecated - please use " +
|
|
"viewSourceChrome.close() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.close();
|
|
}
|
|
|
|
function ViewSourceReload() {
|
|
Deprecated.warning("ViewSourceReload() is deprecated - please use " +
|
|
"viewSourceChrome.reload() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.reload();
|
|
}
|
|
|
|
function getWebNavigation()
|
|
{
|
|
Deprecated.warning("getWebNavigation() is deprecated - please use " +
|
|
"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;
|
|
} catch (e) {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function viewSource(url) {
|
|
Deprecated.warning("viewSource() is deprecated - please use " +
|
|
"viewSourceChrome.loadURL() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.loadURL(url);
|
|
}
|
|
|
|
function ViewSourceGoToLine()
|
|
{
|
|
Deprecated.warning("ViewSourceGoToLine() is deprecated - please use " +
|
|
"viewSourceChrome.promptAndGoToLine() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.promptAndGoToLine();
|
|
}
|
|
|
|
function goToLine(line)
|
|
{
|
|
Deprecated.warning("goToLine() is deprecated - please use " +
|
|
"viewSourceChrome.goToLine() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.goToLine(line);
|
|
}
|
|
|
|
function BrowserForward(aEvent) {
|
|
Deprecated.warning("BrowserForward() is deprecated - please use " +
|
|
"viewSourceChrome.goForward() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.goForward();
|
|
}
|
|
|
|
function BrowserBack(aEvent) {
|
|
Deprecated.warning("BrowserBack() is deprecated - please use " +
|
|
"viewSourceChrome.goBack() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.goBack();
|
|
}
|
|
|
|
function UpdateBackForwardCommands() {
|
|
Deprecated.warning("UpdateBackForwardCommands() is deprecated - please use " +
|
|
"viewSourceChrome.updateCommands() instead.",
|
|
"https://developer.mozilla.org/en-US/Add-ons/Code_snippets/View_Source_for_XUL_Applications");
|
|
viewSourceChrome.updateCommands();
|
|
}
|