michael@0: # -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: # This Source Code Form is subject to the terms of the Mozilla Public michael@0: # License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: # file, You can obtain one at http://mozilla.org/MPL/2.0/. michael@0: michael@0: // Services = object with smart getters for common XPCOM services michael@0: Components.utils.import("resource://gre/modules/Services.jsm"); michael@0: Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm"); michael@0: Components.utils.import("resource:///modules/RecentWindow.jsm"); michael@0: michael@0: XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () { michael@0: const PREF = "browser.newtab.url"; michael@0: michael@0: function getNewTabPageURL() { michael@0: if (!Services.prefs.prefHasUserValue(PREF)) { michael@0: if (PrivateBrowsingUtils.isWindowPrivate(window) && michael@0: !PrivateBrowsingUtils.permanentPrivateBrowsing) michael@0: return "about:privatebrowsing"; michael@0: } michael@0: let url = Services.prefs.getComplexValue(PREF, Ci.nsISupportsString).data; michael@0: return url || "about:blank"; michael@0: } michael@0: michael@0: function update() { michael@0: BROWSER_NEW_TAB_URL = getNewTabPageURL(); michael@0: } michael@0: michael@0: Services.prefs.addObserver(PREF, update, false); michael@0: michael@0: addEventListener("unload", function onUnload() { michael@0: removeEventListener("unload", onUnload); michael@0: Services.prefs.removeObserver(PREF, update); michael@0: }); michael@0: michael@0: return getNewTabPageURL(); michael@0: }); michael@0: michael@0: var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab"; michael@0: michael@0: var gBidiUI = false; michael@0: michael@0: /** michael@0: * Determines whether the given url is considered a special URL for new tabs. michael@0: */ michael@0: function isBlankPageURL(aURL) { michael@0: return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL; michael@0: } michael@0: michael@0: function getBrowserURL() michael@0: { michael@0: return "chrome://browser/content/browser.xul"; michael@0: } michael@0: michael@0: function getTopWin(skipPopups) { michael@0: // If this is called in a browser window, use that window regardless of michael@0: // whether it's the frontmost window, since commands can be executed in michael@0: // background windows (bug 626148). michael@0: if (top.document.documentElement.getAttribute("windowtype") == "navigator:browser" && michael@0: (!skipPopups || top.toolbar.visible)) michael@0: return top; michael@0: michael@0: let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window); michael@0: return RecentWindow.getMostRecentBrowserWindow({private: isPrivate, michael@0: allowPopups: !skipPopups}); michael@0: } michael@0: michael@0: function openTopWin(url) { michael@0: /* deprecated */ michael@0: openUILinkIn(url, "current"); michael@0: } michael@0: michael@0: function getBoolPref(prefname, def) michael@0: { michael@0: try { michael@0: return Services.prefs.getBoolPref(prefname); michael@0: } michael@0: catch(er) { michael@0: return def; michael@0: } michael@0: } michael@0: michael@0: /* openUILink handles clicks on UI elements that cause URLs to load. michael@0: * michael@0: * As the third argument, you may pass an object with the same properties as michael@0: * accepted by openUILinkIn, plus "ignoreButton" and "ignoreAlt". michael@0: */ michael@0: function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup, michael@0: aPostData, aReferrerURI) { michael@0: let params; michael@0: michael@0: if (aIgnoreButton && typeof aIgnoreButton == "object") { michael@0: params = aIgnoreButton; michael@0: michael@0: // don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn michael@0: aIgnoreButton = params.ignoreButton; michael@0: aIgnoreAlt = params.ignoreAlt; michael@0: delete params.ignoreButton; michael@0: delete params.ignoreAlt; michael@0: } else { michael@0: params = { michael@0: allowThirdPartyFixup: aAllowThirdPartyFixup, michael@0: postData: aPostData, michael@0: referrerURI: aReferrerURI, michael@0: initiatingDoc: event ? event.target.ownerDocument : null michael@0: }; michael@0: } michael@0: michael@0: let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt); michael@0: openUILinkIn(url, where, params); michael@0: } michael@0: michael@0: michael@0: /* whereToOpenLink() looks at an event to decide where to open a link. michael@0: * michael@0: * The event may be a mouse event (click, double-click, middle-click) or keypress event (enter). michael@0: * michael@0: * On Windows, the modifiers are: michael@0: * Ctrl new tab, selected michael@0: * Shift new window michael@0: * Ctrl+Shift new tab, in background michael@0: * Alt save michael@0: * michael@0: * Middle-clicking is the same as Ctrl+clicking (it opens a new tab). michael@0: * michael@0: * Exceptions: michael@0: * - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff. michael@0: * (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.) michael@0: * - Alt is hard to use in context menus, because pressing Alt closes the menu. michael@0: * - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable". michael@0: * - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click. michael@0: */ michael@0: function whereToOpenLink( e, ignoreButton, ignoreAlt ) michael@0: { michael@0: // This method must treat a null event like a left click without modifier keys (i.e. michael@0: // e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 }) michael@0: // for compatibility purposes. michael@0: if (!e) michael@0: return "current"; michael@0: michael@0: var shift = e.shiftKey; michael@0: var ctrl = e.ctrlKey; michael@0: var meta = e.metaKey; michael@0: var alt = e.altKey && !ignoreAlt; michael@0: michael@0: // ignoreButton allows "middle-click paste" to use function without always opening in a new window. michael@0: var middle = !ignoreButton && e.button == 1; michael@0: var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true); michael@0: michael@0: // Don't do anything special with right-mouse clicks. They're probably clicks on context menu items. michael@0: michael@0: #ifdef XP_MACOSX michael@0: if (meta || (middle && middleUsesTabs)) michael@0: #else michael@0: if (ctrl || (middle && middleUsesTabs)) michael@0: #endif michael@0: return shift ? "tabshifted" : "tab"; michael@0: michael@0: if (alt && getBoolPref("browser.altClickSave", false)) michael@0: return "save"; michael@0: michael@0: if (shift || (middle && !middleUsesTabs)) michael@0: return "window"; michael@0: michael@0: return "current"; michael@0: } michael@0: michael@0: /* openUILinkIn opens a URL in a place specified by the parameter |where|. michael@0: * michael@0: * |where| can be: michael@0: * "current" current tab (if there aren't any browser windows, then in a new window instead) michael@0: * "tab" new tab (if there aren't any browser windows, then in a new window instead) michael@0: * "tabshifted" same as "tab" but in background if default is to select new tabs, and vice versa michael@0: * "window" new window michael@0: * "save" save to disk (with no filename hint!) michael@0: * michael@0: * aAllowThirdPartyFixup controls whether third party services such as Google's michael@0: * I Feel Lucky are allowed to interpret this URL. This parameter may be michael@0: * undefined, which is treated as false. michael@0: * michael@0: * Instead of aAllowThirdPartyFixup, you may also pass an object with any of michael@0: * these properties: michael@0: * allowThirdPartyFixup (boolean) michael@0: * postData (nsIInputStream) michael@0: * referrerURI (nsIURI) michael@0: * relatedToCurrent (boolean) michael@0: * skipTabAnimation (boolean) michael@0: */ michael@0: function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) { michael@0: var params; michael@0: michael@0: if (arguments.length == 3 && typeof arguments[2] == "object") { michael@0: params = aAllowThirdPartyFixup; michael@0: } else { michael@0: params = { michael@0: allowThirdPartyFixup: aAllowThirdPartyFixup, michael@0: postData: aPostData, michael@0: referrerURI: aReferrerURI michael@0: }; michael@0: } michael@0: michael@0: params.fromChrome = true; michael@0: michael@0: openLinkIn(url, where, params); michael@0: } michael@0: michael@0: function openLinkIn(url, where, params) { michael@0: if (!where || !url) michael@0: return; michael@0: michael@0: var aFromChrome = params.fromChrome; michael@0: var aAllowThirdPartyFixup = params.allowThirdPartyFixup; michael@0: var aPostData = params.postData; michael@0: var aCharset = params.charset; michael@0: var aReferrerURI = params.referrerURI; michael@0: var aRelatedToCurrent = params.relatedToCurrent; michael@0: var aDisableMCB = params.disableMCB; michael@0: var aInBackground = params.inBackground; michael@0: var aDisallowInheritPrincipal = params.disallowInheritPrincipal; michael@0: var aInitiatingDoc = params.initiatingDoc; michael@0: var aIsPrivate = params.private; michael@0: var aSkipTabAnimation = params.skipTabAnimation; michael@0: michael@0: if (where == "save") { michael@0: if (!aInitiatingDoc) { michael@0: Components.utils.reportError("openUILink/openLinkIn was called with " + michael@0: "where == 'save' but without initiatingDoc. See bug 814264."); michael@0: return; michael@0: } michael@0: saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc); michael@0: return; michael@0: } michael@0: const Cc = Components.classes; michael@0: const Ci = Components.interfaces; michael@0: michael@0: var w = getTopWin(); michael@0: if ((where == "tab" || where == "tabshifted") && michael@0: w && !w.toolbar.visible) { michael@0: w = getTopWin(true); michael@0: aRelatedToCurrent = false; michael@0: } michael@0: michael@0: if (!w || where == "window") { michael@0: var sa = Cc["@mozilla.org/supports-array;1"]. michael@0: createInstance(Ci.nsISupportsArray); michael@0: michael@0: var wuri = Cc["@mozilla.org/supports-string;1"]. michael@0: createInstance(Ci.nsISupportsString); michael@0: wuri.data = url; michael@0: michael@0: let charset = null; michael@0: if (aCharset) { michael@0: charset = Cc["@mozilla.org/supports-string;1"] michael@0: .createInstance(Ci.nsISupportsString); michael@0: charset.data = "charset=" + aCharset; michael@0: } michael@0: michael@0: var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"]. michael@0: createInstance(Ci.nsISupportsPRBool); michael@0: allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup; michael@0: michael@0: sa.AppendElement(wuri); michael@0: sa.AppendElement(charset); michael@0: sa.AppendElement(aReferrerURI); michael@0: sa.AppendElement(aPostData); michael@0: sa.AppendElement(allowThirdPartyFixupSupports); michael@0: michael@0: let features = "chrome,dialog=no,all"; michael@0: if (aIsPrivate) { michael@0: features += ",private"; michael@0: } michael@0: michael@0: Services.ww.openWindow(w || window, getBrowserURL(), null, features, sa); michael@0: return; michael@0: } michael@0: michael@0: let loadInBackground = where == "current" ? false : aInBackground; michael@0: if (loadInBackground == null) { michael@0: loadInBackground = aFromChrome ? michael@0: false : michael@0: getBoolPref("browser.tabs.loadInBackground"); michael@0: } michael@0: michael@0: if (where == "current" && w.gBrowser.selectedTab.pinned) { michael@0: try { michael@0: let uriObj = Services.io.newURI(url, null, null); michael@0: if (!uriObj.schemeIs("javascript") && michael@0: w.gBrowser.currentURI.host != uriObj.host) { michael@0: where = "tab"; michael@0: loadInBackground = false; michael@0: } michael@0: } catch (err) { michael@0: where = "tab"; michael@0: loadInBackground = false; michael@0: } michael@0: } michael@0: michael@0: // Raise the target window before loading the URI, since loading it may michael@0: // result in a new frontmost window (e.g. "javascript:window.open('');"). michael@0: w.focus(); michael@0: michael@0: switch (where) { michael@0: case "current": michael@0: let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE; michael@0: if (aAllowThirdPartyFixup) { michael@0: flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP; michael@0: flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS; michael@0: } michael@0: if (aDisallowInheritPrincipal) michael@0: flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER; michael@0: w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData); michael@0: break; michael@0: case "tabshifted": michael@0: loadInBackground = !loadInBackground; michael@0: // fall through michael@0: case "tab": michael@0: let browser = w.gBrowser; michael@0: browser.loadOneTab(url, { michael@0: referrerURI: aReferrerURI, michael@0: charset: aCharset, michael@0: postData: aPostData, michael@0: inBackground: loadInBackground, michael@0: allowThirdPartyFixup: aAllowThirdPartyFixup, michael@0: relatedToCurrent: aRelatedToCurrent, michael@0: skipAnimation: aSkipTabAnimation, michael@0: disableMCB: aDisableMCB}); michael@0: break; michael@0: } michael@0: michael@0: w.gBrowser.selectedBrowser.focus(); michael@0: michael@0: if (!loadInBackground && w.isBlankPageURL(url)) michael@0: w.focusAndSelectUrlBar(); michael@0: } michael@0: michael@0: // Used as an onclick handler for UI elements with link-like behavior. michael@0: // e.g. onclick="checkForMiddleClick(this, event);" michael@0: function checkForMiddleClick(node, event) { michael@0: // We should be using the disabled property here instead of the attribute, michael@0: // but some elements that this function is used with don't support it (e.g. michael@0: // menuitem). michael@0: if (node.getAttribute("disabled") == "true") michael@0: return; // Do nothing michael@0: michael@0: if (event.button == 1) { michael@0: /* Execute the node's oncommand or command. michael@0: * michael@0: * XXX: we should use node.oncommand(event) once bug 246720 is fixed. michael@0: */ michael@0: var target = node.hasAttribute("oncommand") ? node : michael@0: node.ownerDocument.getElementById(node.getAttribute("command")); michael@0: var fn = new Function("event", target.getAttribute("oncommand")); michael@0: fn.call(target, event); michael@0: michael@0: // If the middle-click was on part of a menu, close the menu. michael@0: // (Menus close automatically with left-click but not with middle-click.) michael@0: closeMenus(event.target); michael@0: } michael@0: } michael@0: michael@0: // Closes all popups that are ancestors of the node. michael@0: function closeMenus(node) michael@0: { michael@0: if ("tagName" in node) { michael@0: if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" michael@0: && (node.tagName == "menupopup" || node.tagName == "popup")) michael@0: node.hidePopup(); michael@0: michael@0: closeMenus(node.parentNode); michael@0: } michael@0: } michael@0: michael@0: // Gather all descendent text under given document node. michael@0: function gatherTextUnder ( root ) michael@0: { michael@0: var text = ""; michael@0: var node = root.firstChild; michael@0: var depth = 1; michael@0: while ( node && depth > 0 ) { michael@0: // See if this node is text. michael@0: if ( node.nodeType == Node.TEXT_NODE ) { michael@0: // Add this text to our collection. michael@0: text += " " + node.data; michael@0: } else if ( node instanceof HTMLImageElement) { michael@0: // If it has an "alt" attribute, add that. michael@0: var altText = node.getAttribute( "alt" ); michael@0: if ( altText && altText != "" ) { michael@0: text += " " + altText; michael@0: } michael@0: } michael@0: // Find next node to test. michael@0: // First, see if this node has children. michael@0: if ( node.hasChildNodes() ) { michael@0: // Go to first child. michael@0: node = node.firstChild; michael@0: depth++; michael@0: } else { michael@0: // No children, try next sibling (or parent next sibling). michael@0: while ( depth > 0 && !node.nextSibling ) { michael@0: node = node.parentNode; michael@0: depth--; michael@0: } michael@0: if ( node.nextSibling ) { michael@0: node = node.nextSibling; michael@0: } michael@0: } michael@0: } michael@0: // Strip leading and tailing whitespace. michael@0: text = text.trim(); michael@0: // Compress remaining whitespace. michael@0: text = text.replace( /\s+/g, " " ); michael@0: return text; michael@0: } michael@0: michael@0: function getShellService() michael@0: { michael@0: var shell = null; michael@0: try { michael@0: shell = Components.classes["@mozilla.org/browser/shell-service;1"] michael@0: .getService(Components.interfaces.nsIShellService); michael@0: } catch (e) { michael@0: } michael@0: return shell; michael@0: } michael@0: michael@0: function isBidiEnabled() { michael@0: // first check the pref. michael@0: if (getBoolPref("bidi.browser.ui", false)) michael@0: return true; michael@0: michael@0: // then check intl.uidirection. michael@0: var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"]. michael@0: getService(Components.interfaces.nsIXULChromeRegistry); michael@0: if (chromeReg.isLocaleRTL("global")) michael@0: return true; michael@0: michael@0: // now see if the system locale is an RTL one. michael@0: var rv = false; michael@0: michael@0: try { michael@0: var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] michael@0: .getService(Components.interfaces.nsILocaleService); michael@0: var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0,3); michael@0: michael@0: switch (systemLocale) { michael@0: case "ar-": michael@0: case "he-": michael@0: case "fa-": michael@0: case "ug-": michael@0: case "ur-": michael@0: case "syr": michael@0: rv = true; michael@0: Services.prefs.setBoolPref("bidi.browser.ui", true); michael@0: } michael@0: } catch (e) {} michael@0: michael@0: return rv; michael@0: } michael@0: michael@0: function openAboutDialog() { michael@0: var enumerator = Services.wm.getEnumerator("Browser:About"); michael@0: while (enumerator.hasMoreElements()) { michael@0: // Only open one about window (Bug 599573) michael@0: let win = enumerator.getNext(); michael@0: if (win.closed) { michael@0: continue; michael@0: } michael@0: win.focus(); michael@0: return; michael@0: } michael@0: michael@0: #ifdef XP_WIN michael@0: var features = "chrome,centerscreen,dependent"; michael@0: #elifdef XP_MACOSX michael@0: var features = "chrome,resizable=no,minimizable=no"; michael@0: #else michael@0: var features = "chrome,centerscreen,dependent,dialog=no"; michael@0: #endif michael@0: window.openDialog("chrome://browser/content/aboutDialog.xul", "", features); michael@0: } michael@0: michael@0: function openPreferences(paneID, extraArgs) michael@0: { michael@0: function switchToAdvancedSubPane(doc) { michael@0: if (extraArgs && extraArgs["advancedTab"]) { michael@0: let advancedPaneTabs = doc.getElementById("advancedPrefs"); michael@0: advancedPaneTabs.selectedTab = doc.getElementById(extraArgs["advancedTab"]); michael@0: } michael@0: } michael@0: michael@0: if (getBoolPref("browser.preferences.inContent")) { michael@0: let win = Services.wm.getMostRecentWindow("navigator:browser"); michael@0: if (!win) { michael@0: return; michael@0: } michael@0: michael@0: let newLoad = !win.switchToTabHavingURI("about:preferences", true); michael@0: let browser = win.gBrowser.selectedBrowser; michael@0: michael@0: function switchToPane() { michael@0: if (paneID) { michael@0: browser.contentWindow.selectCategory(paneID); michael@0: } michael@0: switchToAdvancedSubPane(browser.contentDocument); michael@0: } michael@0: michael@0: if (newLoad) { michael@0: browser.addEventListener("load", function onload() { michael@0: browser.removeEventListener("load", onload, true); michael@0: switchToPane(); michael@0: }, true); michael@0: } else { michael@0: switchToPane(); michael@0: } michael@0: } else { michael@0: var instantApply = getBoolPref("browser.preferences.instantApply", false); michael@0: var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal"); michael@0: michael@0: var win = Services.wm.getMostRecentWindow("Browser:Preferences"); michael@0: if (win) { michael@0: win.focus(); michael@0: if (paneID) { michael@0: var pane = win.document.getElementById(paneID); michael@0: win.document.documentElement.showPane(pane); michael@0: } michael@0: michael@0: switchToAdvancedSubPane(win.document); michael@0: } else { michael@0: openDialog("chrome://browser/content/preferences/preferences.xul", michael@0: "Preferences", features, paneID, extraArgs); michael@0: } michael@0: } michael@0: } michael@0: michael@0: function openAdvancedPreferences(tabID) michael@0: { michael@0: openPreferences("paneAdvanced", { "advancedTab" : tabID }); michael@0: } michael@0: michael@0: /** michael@0: * Opens the troubleshooting information (about:support) page for this version michael@0: * of the application. michael@0: */ michael@0: function openTroubleshootingPage() michael@0: { michael@0: openUILinkIn("about:support", "tab"); michael@0: } michael@0: michael@0: #ifdef MOZ_SERVICES_HEALTHREPORT michael@0: /** michael@0: * Opens the troubleshooting information (about:support) page for this version michael@0: * of the application. michael@0: */ michael@0: function openHealthReport() michael@0: { michael@0: openUILinkIn("about:healthreport", "tab"); michael@0: } michael@0: #endif michael@0: michael@0: /** michael@0: * Opens the feedback page for this version of the application. michael@0: */ michael@0: function openFeedbackPage() michael@0: { michael@0: var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] michael@0: .getService(Components.interfaces.nsIURLFormatter) michael@0: .formatURLPref("app.feedback.baseURL"); michael@0: openUILinkIn(url, "tab"); michael@0: } michael@0: michael@0: function openTourPage() michael@0: { michael@0: let scope = {} michael@0: Components.utils.import("resource:///modules/UITour.jsm", scope); michael@0: openUILinkIn(scope.UITour.url, "tab"); michael@0: } michael@0: michael@0: function buildHelpMenu() michael@0: { michael@0: // Enable/disable the "Report Web Forgery" menu item. michael@0: if (typeof gSafeBrowsing != "undefined") michael@0: gSafeBrowsing.setReportPhishingMenu(); michael@0: } michael@0: michael@0: function isElementVisible(aElement) michael@0: { michael@0: if (!aElement) michael@0: return false; michael@0: michael@0: // If aElement or a direct or indirect parent is hidden or collapsed, michael@0: // height, width or both will be 0. michael@0: var bo = aElement.boxObject; michael@0: return (bo.height > 0 && bo.width > 0); michael@0: } michael@0: michael@0: function makeURLAbsolute(aBase, aUrl) michael@0: { michael@0: // Note: makeURI() will throw if aUri is not a valid URI michael@0: return makeURI(aUrl, null, makeURI(aBase)).spec; michael@0: } michael@0: michael@0: /** michael@0: * openNewTabWith: opens a new tab with the given URL. michael@0: * michael@0: * @param aURL michael@0: * The URL to open (as a string). michael@0: * @param aDocument michael@0: * Note this parameter is now ignored. There is no security check & no michael@0: * referrer header derived from aDocument (null case). michael@0: * @param aPostData michael@0: * Form POST data, or null. michael@0: * @param aEvent michael@0: * The triggering event (for the purpose of determining whether to open michael@0: * in the background), or null. michael@0: * @param aAllowThirdPartyFixup michael@0: * If true, then we allow the URL text to be sent to third party services michael@0: * (e.g., Google's I Feel Lucky) for interpretation. This parameter may michael@0: * be undefined in which case it is treated as false. michael@0: * @param [optional] aReferrer michael@0: * This will be used as the referrer. There will be no security check. michael@0: */ michael@0: function openNewTabWith(aURL, aDocument, aPostData, aEvent, michael@0: aAllowThirdPartyFixup, aReferrer) { michael@0: michael@0: // As in openNewWindowWith(), we want to pass the charset of the michael@0: // current document over to a new tab. michael@0: let originCharset = null; michael@0: if (document.documentElement.getAttribute("windowtype") == "navigator:browser") michael@0: originCharset = gBrowser.selectedBrowser.characterSet; michael@0: michael@0: openLinkIn(aURL, aEvent && aEvent.shiftKey ? "tabshifted" : "tab", michael@0: { charset: originCharset, michael@0: postData: aPostData, michael@0: allowThirdPartyFixup: aAllowThirdPartyFixup, michael@0: referrerURI: aReferrer }); michael@0: } michael@0: michael@0: /** michael@0: * @param aDocument michael@0: * Note this parameter is ignored. See openNewTabWith() michael@0: */ michael@0: function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) { michael@0: // Extract the current charset menu setting from the current document and michael@0: // use it to initialize the new browser window... michael@0: let originCharset = null; michael@0: if (document.documentElement.getAttribute("windowtype") == "navigator:browser") michael@0: originCharset = gBrowser.selectedBrowser.characterSet; michael@0: michael@0: openLinkIn(aURL, "window", michael@0: { charset: originCharset, michael@0: postData: aPostData, michael@0: allowThirdPartyFixup: aAllowThirdPartyFixup, michael@0: referrerURI: aReferrer }); michael@0: } michael@0: michael@0: // aCalledFromModal is optional michael@0: function openHelpLink(aHelpTopic, aCalledFromModal, aWhere) { michael@0: var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] michael@0: .getService(Components.interfaces.nsIURLFormatter) michael@0: .formatURLPref("app.support.baseURL"); michael@0: url += aHelpTopic; michael@0: michael@0: var where = aWhere; michael@0: if (!aWhere) michael@0: where = aCalledFromModal ? "window" : "tab"; michael@0: michael@0: openUILinkIn(url, where); michael@0: } michael@0: michael@0: function openPrefsHelp() { michael@0: // non-instant apply prefwindows are usually modal, so we can't open in the topmost window, michael@0: // since its probably behind the window. michael@0: var instantApply = getBoolPref("browser.preferences.instantApply"); michael@0: michael@0: var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic; michael@0: openHelpLink(helpTopic, !instantApply); michael@0: } michael@0: michael@0: function trimURL(aURL) { michael@0: // This function must not modify the given URL such that calling michael@0: // nsIURIFixup::createFixupURI with the result will produce a different URI. michael@0: return aURL /* remove single trailing slash for http/https/ftp URLs */ michael@0: .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1") michael@0: /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */ michael@0: .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1"); michael@0: }