browser/base/content/utilityOverlay.js

Wed, 31 Dec 2014 13:27:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 13:27:57 +0100
branch
TOR_BUG_3246
changeset 6
8bccb770b82d
permissions
-rw-r--r--

Ignore runtime configuration files generated during quality assurance.

     1 # -*- Mode: javascript; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*-
     2 # This Source Code Form is subject to the terms of the Mozilla Public
     3 # License, v. 2.0. If a copy of the MPL was not distributed with this
     4 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     6 // Services = object with smart getters for common XPCOM services
     7 Components.utils.import("resource://gre/modules/Services.jsm");
     8 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
     9 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
    10 Components.utils.import("resource:///modules/RecentWindow.jsm");
    12 XPCOMUtils.defineLazyGetter(this, "BROWSER_NEW_TAB_URL", function () {
    13   const PREF = "browser.newtab.url";
    15   function getNewTabPageURL() {
    16     if (!Services.prefs.prefHasUserValue(PREF)) {
    17       if (PrivateBrowsingUtils.isWindowPrivate(window) &&
    18           !PrivateBrowsingUtils.permanentPrivateBrowsing)
    19         return "about:privatebrowsing";
    20     }
    21     let url = Services.prefs.getComplexValue(PREF, Ci.nsISupportsString).data;
    22     return url || "about:blank";
    23   }
    25   function update() {
    26     BROWSER_NEW_TAB_URL = getNewTabPageURL();
    27   }
    29   Services.prefs.addObserver(PREF, update, false);
    31   addEventListener("unload", function onUnload() {
    32     removeEventListener("unload", onUnload);
    33     Services.prefs.removeObserver(PREF, update);
    34   });
    36   return getNewTabPageURL();
    37 });
    39 var TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
    41 var gBidiUI = false;
    43 /**
    44  * Determines whether the given url is considered a special URL for new tabs.
    45  */
    46 function isBlankPageURL(aURL) {
    47   return aURL == "about:blank" || aURL == BROWSER_NEW_TAB_URL;
    48 }
    50 function getBrowserURL()
    51 {
    52   return "chrome://browser/content/browser.xul";
    53 }
    55 function getTopWin(skipPopups) {
    56   // If this is called in a browser window, use that window regardless of
    57   // whether it's the frontmost window, since commands can be executed in
    58   // background windows (bug 626148).
    59   if (top.document.documentElement.getAttribute("windowtype") == "navigator:browser" &&
    60       (!skipPopups || top.toolbar.visible))
    61     return top;
    63   let isPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
    64   return RecentWindow.getMostRecentBrowserWindow({private: isPrivate,
    65                                                   allowPopups: !skipPopups});
    66 }
    68 function openTopWin(url) {
    69   /* deprecated */
    70   openUILinkIn(url, "current");
    71 }
    73 function getBoolPref(prefname, def)
    74 {
    75   try {
    76     return Services.prefs.getBoolPref(prefname);
    77   }
    78   catch(er) {
    79     return def;
    80   }
    81 }
    83 /* openUILink handles clicks on UI elements that cause URLs to load.
    84  *
    85  * As the third argument, you may pass an object with the same properties as
    86  * accepted by openUILinkIn, plus "ignoreButton" and "ignoreAlt".
    87  */
    88 function openUILink(url, event, aIgnoreButton, aIgnoreAlt, aAllowThirdPartyFixup,
    89                     aPostData, aReferrerURI) {
    90   let params;
    92   if (aIgnoreButton && typeof aIgnoreButton == "object") {
    93     params = aIgnoreButton;
    95     // don't forward "ignoreButton" and "ignoreAlt" to openUILinkIn
    96     aIgnoreButton = params.ignoreButton;
    97     aIgnoreAlt = params.ignoreAlt;
    98     delete params.ignoreButton;
    99     delete params.ignoreAlt;
   100   } else {
   101     params = {
   102       allowThirdPartyFixup: aAllowThirdPartyFixup,
   103       postData: aPostData,
   104       referrerURI: aReferrerURI,
   105       initiatingDoc: event ? event.target.ownerDocument : null
   106     };
   107   }
   109   let where = whereToOpenLink(event, aIgnoreButton, aIgnoreAlt);
   110   openUILinkIn(url, where, params);
   111 }
   114 /* whereToOpenLink() looks at an event to decide where to open a link.
   115  *
   116  * The event may be a mouse event (click, double-click, middle-click) or keypress event (enter).
   117  *
   118  * On Windows, the modifiers are:
   119  * Ctrl        new tab, selected
   120  * Shift       new window
   121  * Ctrl+Shift  new tab, in background
   122  * Alt         save
   123  *
   124  * Middle-clicking is the same as Ctrl+clicking (it opens a new tab).
   125  *
   126  * Exceptions: 
   127  * - Alt is ignored for menu items selected using the keyboard so you don't accidentally save stuff.  
   128  *    (Currently, the Alt isn't sent here at all for menu items, but that will change in bug 126189.)
   129  * - Alt is hard to use in context menus, because pressing Alt closes the menu.
   130  * - Alt can't be used on the bookmarks toolbar because Alt is used for "treat this as something draggable".
   131  * - The button is ignored for the middle-click-paste-URL feature, since it's always a middle-click.
   132  */
   133 function whereToOpenLink( e, ignoreButton, ignoreAlt )
   134 {
   135   // This method must treat a null event like a left click without modifier keys (i.e.
   136   // e = { shiftKey:false, ctrlKey:false, metaKey:false, altKey:false, button:0 })
   137   // for compatibility purposes.
   138   if (!e)
   139     return "current";
   141   var shift = e.shiftKey;
   142   var ctrl =  e.ctrlKey;
   143   var meta =  e.metaKey;
   144   var alt  =  e.altKey && !ignoreAlt;
   146   // ignoreButton allows "middle-click paste" to use function without always opening in a new window.
   147   var middle = !ignoreButton && e.button == 1;
   148   var middleUsesTabs = getBoolPref("browser.tabs.opentabfor.middleclick", true);
   150   // Don't do anything special with right-mouse clicks.  They're probably clicks on context menu items.
   152 #ifdef XP_MACOSX
   153   if (meta || (middle && middleUsesTabs))
   154 #else
   155   if (ctrl || (middle && middleUsesTabs))
   156 #endif
   157     return shift ? "tabshifted" : "tab";
   159   if (alt && getBoolPref("browser.altClickSave", false))
   160     return "save";
   162   if (shift || (middle && !middleUsesTabs))
   163     return "window";
   165   return "current";
   166 }
   168 /* openUILinkIn opens a URL in a place specified by the parameter |where|.
   169  *
   170  * |where| can be:
   171  *  "current"     current tab            (if there aren't any browser windows, then in a new window instead)
   172  *  "tab"         new tab                (if there aren't any browser windows, then in a new window instead)
   173  *  "tabshifted"  same as "tab" but in background if default is to select new tabs, and vice versa
   174  *  "window"      new window
   175  *  "save"        save to disk (with no filename hint!)
   176  *
   177  * aAllowThirdPartyFixup controls whether third party services such as Google's
   178  * I Feel Lucky are allowed to interpret this URL. This parameter may be
   179  * undefined, which is treated as false.
   180  *
   181  * Instead of aAllowThirdPartyFixup, you may also pass an object with any of
   182  * these properties:
   183  *   allowThirdPartyFixup (boolean)
   184  *   postData             (nsIInputStream)
   185  *   referrerURI          (nsIURI)
   186  *   relatedToCurrent     (boolean)
   187  *   skipTabAnimation     (boolean)
   188  */
   189 function openUILinkIn(url, where, aAllowThirdPartyFixup, aPostData, aReferrerURI) {
   190   var params;
   192   if (arguments.length == 3 && typeof arguments[2] == "object") {
   193     params = aAllowThirdPartyFixup;
   194   } else {
   195     params = {
   196       allowThirdPartyFixup: aAllowThirdPartyFixup,
   197       postData: aPostData,
   198       referrerURI: aReferrerURI
   199     };
   200   }
   202   params.fromChrome = true;
   204   openLinkIn(url, where, params);
   205 }
   207 function openLinkIn(url, where, params) {
   208   if (!where || !url)
   209     return;
   211   var aFromChrome           = params.fromChrome;
   212   var aAllowThirdPartyFixup = params.allowThirdPartyFixup;
   213   var aPostData             = params.postData;
   214   var aCharset              = params.charset;
   215   var aReferrerURI          = params.referrerURI;
   216   var aRelatedToCurrent     = params.relatedToCurrent;
   217   var aDisableMCB           = params.disableMCB;
   218   var aInBackground         = params.inBackground;
   219   var aDisallowInheritPrincipal = params.disallowInheritPrincipal;
   220   var aInitiatingDoc        = params.initiatingDoc;
   221   var aIsPrivate            = params.private;
   222   var aSkipTabAnimation     = params.skipTabAnimation;
   224   if (where == "save") {
   225     if (!aInitiatingDoc) {
   226       Components.utils.reportError("openUILink/openLinkIn was called with " +
   227         "where == 'save' but without initiatingDoc.  See bug 814264.");
   228       return;
   229     }
   230     saveURL(url, null, null, true, null, aReferrerURI, aInitiatingDoc);
   231     return;
   232   }
   233   const Cc = Components.classes;
   234   const Ci = Components.interfaces;
   236   var w = getTopWin();
   237   if ((where == "tab" || where == "tabshifted") &&
   238       w && !w.toolbar.visible) {
   239     w = getTopWin(true);
   240     aRelatedToCurrent = false;
   241   }
   243   if (!w || where == "window") {
   244     var sa = Cc["@mozilla.org/supports-array;1"].
   245              createInstance(Ci.nsISupportsArray);
   247     var wuri = Cc["@mozilla.org/supports-string;1"].
   248                createInstance(Ci.nsISupportsString);
   249     wuri.data = url;
   251     let charset = null;
   252     if (aCharset) {
   253       charset = Cc["@mozilla.org/supports-string;1"]
   254                   .createInstance(Ci.nsISupportsString);
   255       charset.data = "charset=" + aCharset;
   256     }
   258     var allowThirdPartyFixupSupports = Cc["@mozilla.org/supports-PRBool;1"].
   259                                        createInstance(Ci.nsISupportsPRBool);
   260     allowThirdPartyFixupSupports.data = aAllowThirdPartyFixup;
   262     sa.AppendElement(wuri);
   263     sa.AppendElement(charset);
   264     sa.AppendElement(aReferrerURI);
   265     sa.AppendElement(aPostData);
   266     sa.AppendElement(allowThirdPartyFixupSupports);
   268     let features = "chrome,dialog=no,all";
   269     if (aIsPrivate) {
   270       features += ",private";
   271     }
   273     Services.ww.openWindow(w || window, getBrowserURL(), null, features, sa);
   274     return;
   275   }
   277   let loadInBackground = where == "current" ? false : aInBackground;
   278   if (loadInBackground == null) {
   279     loadInBackground = aFromChrome ?
   280                          false :
   281                          getBoolPref("browser.tabs.loadInBackground");
   282   }
   284   if (where == "current" && w.gBrowser.selectedTab.pinned) {
   285     try {
   286       let uriObj = Services.io.newURI(url, null, null);
   287       if (!uriObj.schemeIs("javascript") &&
   288           w.gBrowser.currentURI.host != uriObj.host) {
   289         where = "tab";
   290         loadInBackground = false;
   291       }
   292     } catch (err) {
   293       where = "tab";
   294       loadInBackground = false;
   295     }
   296   }
   298   // Raise the target window before loading the URI, since loading it may
   299   // result in a new frontmost window (e.g. "javascript:window.open('');").
   300   w.focus();
   302   switch (where) {
   303   case "current":
   304     let flags = Ci.nsIWebNavigation.LOAD_FLAGS_NONE;
   305     if (aAllowThirdPartyFixup) {
   306       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP;
   307       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_FIXUP_SCHEME_TYPOS;
   308     }
   309     if (aDisallowInheritPrincipal)
   310       flags |= Ci.nsIWebNavigation.LOAD_FLAGS_DISALLOW_INHERIT_OWNER;
   311     w.gBrowser.loadURIWithFlags(url, flags, aReferrerURI, null, aPostData);
   312     break;
   313   case "tabshifted":
   314     loadInBackground = !loadInBackground;
   315     // fall through
   316   case "tab":
   317     let browser = w.gBrowser;
   318     browser.loadOneTab(url, {
   319                        referrerURI: aReferrerURI,
   320                        charset: aCharset,
   321                        postData: aPostData,
   322                        inBackground: loadInBackground,
   323                        allowThirdPartyFixup: aAllowThirdPartyFixup,
   324                        relatedToCurrent: aRelatedToCurrent,
   325                        skipAnimation: aSkipTabAnimation,
   326                        disableMCB: aDisableMCB});
   327     break;
   328   }
   330   w.gBrowser.selectedBrowser.focus();
   332   if (!loadInBackground && w.isBlankPageURL(url))
   333     w.focusAndSelectUrlBar();
   334 }
   336 // Used as an onclick handler for UI elements with link-like behavior.
   337 // e.g. onclick="checkForMiddleClick(this, event);"
   338 function checkForMiddleClick(node, event) {
   339   // We should be using the disabled property here instead of the attribute,
   340   // but some elements that this function is used with don't support it (e.g.
   341   // menuitem).
   342   if (node.getAttribute("disabled") == "true")
   343     return; // Do nothing
   345   if (event.button == 1) {
   346     /* Execute the node's oncommand or command.
   347      *
   348      * XXX: we should use node.oncommand(event) once bug 246720 is fixed.
   349      */
   350     var target = node.hasAttribute("oncommand") ? node :
   351                  node.ownerDocument.getElementById(node.getAttribute("command"));
   352     var fn = new Function("event", target.getAttribute("oncommand"));
   353     fn.call(target, event);
   355     // If the middle-click was on part of a menu, close the menu.
   356     // (Menus close automatically with left-click but not with middle-click.)
   357     closeMenus(event.target);
   358   }
   359 }
   361 // Closes all popups that are ancestors of the node.
   362 function closeMenus(node)
   363 {
   364   if ("tagName" in node) {
   365     if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
   366     && (node.tagName == "menupopup" || node.tagName == "popup"))
   367       node.hidePopup();
   369     closeMenus(node.parentNode);
   370   }
   371 }
   373 // Gather all descendent text under given document node.
   374 function gatherTextUnder ( root ) 
   375 {
   376   var text = "";
   377   var node = root.firstChild;
   378   var depth = 1;
   379   while ( node && depth > 0 ) {
   380     // See if this node is text.
   381     if ( node.nodeType == Node.TEXT_NODE ) {
   382       // Add this text to our collection.
   383       text += " " + node.data;
   384     } else if ( node instanceof HTMLImageElement) {
   385       // If it has an "alt" attribute, add that.
   386       var altText = node.getAttribute( "alt" );
   387       if ( altText && altText != "" ) {
   388         text += " " + altText;
   389       }
   390     }
   391     // Find next node to test.
   392     // First, see if this node has children.
   393     if ( node.hasChildNodes() ) {
   394       // Go to first child.
   395       node = node.firstChild;
   396       depth++;
   397     } else {
   398       // No children, try next sibling (or parent next sibling).
   399       while ( depth > 0 && !node.nextSibling ) {
   400         node = node.parentNode;
   401         depth--;
   402       }
   403       if ( node.nextSibling ) {
   404         node = node.nextSibling;
   405       }
   406     }
   407   }
   408   // Strip leading and tailing whitespace.
   409   text = text.trim();
   410   // Compress remaining whitespace.
   411   text = text.replace( /\s+/g, " " );
   412   return text;
   413 }
   415 function getShellService()
   416 {
   417   var shell = null;
   418   try {
   419     shell = Components.classes["@mozilla.org/browser/shell-service;1"]
   420       .getService(Components.interfaces.nsIShellService);
   421   } catch (e) {
   422   }
   423   return shell;
   424 }
   426 function isBidiEnabled() {
   427   // first check the pref.
   428   if (getBoolPref("bidi.browser.ui", false))
   429     return true;
   431   // then check intl.uidirection.<locale>
   432   var chromeReg = Components.classes["@mozilla.org/chrome/chrome-registry;1"].
   433                   getService(Components.interfaces.nsIXULChromeRegistry);
   434   if (chromeReg.isLocaleRTL("global"))
   435     return true;
   437   // now see if the system locale is an RTL one.
   438   var rv = false;
   440   try {
   441     var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"]
   442                                   .getService(Components.interfaces.nsILocaleService);
   443     var systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE").substr(0,3);
   445     switch (systemLocale) {
   446       case "ar-":
   447       case "he-":
   448       case "fa-":
   449       case "ug-":
   450       case "ur-":
   451       case "syr":
   452         rv = true;
   453         Services.prefs.setBoolPref("bidi.browser.ui", true);
   454     }
   455   } catch (e) {}
   457   return rv;
   458 }
   460 function openAboutDialog() {
   461   var enumerator = Services.wm.getEnumerator("Browser:About");
   462   while (enumerator.hasMoreElements()) {
   463     // Only open one about window (Bug 599573)
   464     let win = enumerator.getNext();
   465     if (win.closed) {
   466       continue;
   467     }
   468     win.focus();
   469     return;
   470   }
   472 #ifdef XP_WIN
   473   var features = "chrome,centerscreen,dependent";
   474 #elifdef XP_MACOSX
   475   var features = "chrome,resizable=no,minimizable=no";
   476 #else
   477   var features = "chrome,centerscreen,dependent,dialog=no";
   478 #endif
   479   window.openDialog("chrome://browser/content/aboutDialog.xul", "", features);
   480 }
   482 function openPreferences(paneID, extraArgs)
   483 {
   484   function switchToAdvancedSubPane(doc) {
   485     if (extraArgs && extraArgs["advancedTab"]) {
   486       let advancedPaneTabs = doc.getElementById("advancedPrefs");
   487       advancedPaneTabs.selectedTab = doc.getElementById(extraArgs["advancedTab"]);
   488     }
   489   }
   491   if (getBoolPref("browser.preferences.inContent")) {
   492     let win = Services.wm.getMostRecentWindow("navigator:browser");
   493     if (!win) {
   494       return;
   495     }
   497     let newLoad = !win.switchToTabHavingURI("about:preferences", true);
   498     let browser = win.gBrowser.selectedBrowser;
   500     function switchToPane() {
   501       if (paneID) {
   502         browser.contentWindow.selectCategory(paneID);
   503       }
   504       switchToAdvancedSubPane(browser.contentDocument);
   505     }
   507     if (newLoad) {
   508       browser.addEventListener("load", function onload() {
   509         browser.removeEventListener("load", onload, true);
   510         switchToPane();
   511       }, true);
   512     } else {
   513       switchToPane();
   514     }
   515   } else {
   516     var instantApply = getBoolPref("browser.preferences.instantApply", false);
   517     var features = "chrome,titlebar,toolbar,centerscreen" + (instantApply ? ",dialog=no" : ",modal");
   519     var win = Services.wm.getMostRecentWindow("Browser:Preferences");
   520     if (win) {
   521       win.focus();
   522       if (paneID) {
   523         var pane = win.document.getElementById(paneID);
   524         win.document.documentElement.showPane(pane);
   525       }
   527       switchToAdvancedSubPane(win.document);
   528     } else {
   529       openDialog("chrome://browser/content/preferences/preferences.xul",
   530                  "Preferences", features, paneID, extraArgs);
   531     }
   532   }
   533 }
   535 function openAdvancedPreferences(tabID)
   536 {
   537   openPreferences("paneAdvanced", { "advancedTab" : tabID });
   538 }
   540 /**
   541  * Opens the troubleshooting information (about:support) page for this version
   542  * of the application.
   543  */
   544 function openTroubleshootingPage()
   545 {
   546   openUILinkIn("about:support", "tab");
   547 }
   549 #ifdef MOZ_SERVICES_HEALTHREPORT
   550 /**
   551  * Opens the troubleshooting information (about:support) page for this version
   552  * of the application.
   553  */
   554 function openHealthReport()
   555 {
   556   openUILinkIn("about:healthreport", "tab");
   557 }
   558 #endif
   560 /**
   561  * Opens the feedback page for this version of the application.
   562  */
   563 function openFeedbackPage()
   564 {
   565   var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
   566                       .getService(Components.interfaces.nsIURLFormatter)
   567                       .formatURLPref("app.feedback.baseURL");
   568   openUILinkIn(url, "tab");
   569 }
   571 function openTourPage()
   572 {
   573   let scope = {}
   574   Components.utils.import("resource:///modules/UITour.jsm", scope);
   575   openUILinkIn(scope.UITour.url, "tab");
   576 }
   578 function buildHelpMenu()
   579 {
   580   // Enable/disable the "Report Web Forgery" menu item.
   581   if (typeof gSafeBrowsing != "undefined")
   582     gSafeBrowsing.setReportPhishingMenu();
   583 }
   585 function isElementVisible(aElement)
   586 {
   587   if (!aElement)
   588     return false;
   590   // If aElement or a direct or indirect parent is hidden or collapsed,
   591   // height, width or both will be 0.
   592   var bo = aElement.boxObject;
   593   return (bo.height > 0 && bo.width > 0);
   594 }
   596 function makeURLAbsolute(aBase, aUrl)
   597 {
   598   // Note:  makeURI() will throw if aUri is not a valid URI
   599   return makeURI(aUrl, null, makeURI(aBase)).spec;
   600 }
   602 /**
   603  * openNewTabWith: opens a new tab with the given URL.
   604  *
   605  * @param aURL
   606  *        The URL to open (as a string).
   607  * @param aDocument
   608  *        Note this parameter is now ignored. There is no security check & no
   609  *        referrer header derived from aDocument (null case).
   610  * @param aPostData
   611  *        Form POST data, or null.
   612  * @param aEvent
   613  *        The triggering event (for the purpose of determining whether to open
   614  *        in the background), or null.
   615  * @param aAllowThirdPartyFixup
   616  *        If true, then we allow the URL text to be sent to third party services
   617  *        (e.g., Google's I Feel Lucky) for interpretation. This parameter may
   618  *        be undefined in which case it is treated as false.
   619  * @param [optional] aReferrer
   620  *        This will be used as the referrer. There will be no security check.
   621  */ 
   622 function openNewTabWith(aURL, aDocument, aPostData, aEvent,
   623                         aAllowThirdPartyFixup, aReferrer) {
   625   // As in openNewWindowWith(), we want to pass the charset of the
   626   // current document over to a new tab.
   627   let originCharset = null;
   628   if (document.documentElement.getAttribute("windowtype") == "navigator:browser")
   629     originCharset = gBrowser.selectedBrowser.characterSet;
   631   openLinkIn(aURL, aEvent && aEvent.shiftKey ? "tabshifted" : "tab",
   632              { charset: originCharset,
   633                postData: aPostData,
   634                allowThirdPartyFixup: aAllowThirdPartyFixup,
   635                referrerURI: aReferrer });
   636 }
   638 /**
   639  * @param aDocument
   640  *        Note this parameter is ignored. See openNewTabWith()
   641  */
   642 function openNewWindowWith(aURL, aDocument, aPostData, aAllowThirdPartyFixup, aReferrer) {
   643   // Extract the current charset menu setting from the current document and
   644   // use it to initialize the new browser window...
   645   let originCharset = null;
   646   if (document.documentElement.getAttribute("windowtype") == "navigator:browser")
   647     originCharset = gBrowser.selectedBrowser.characterSet;
   649   openLinkIn(aURL, "window",
   650              { charset: originCharset,
   651                postData: aPostData,
   652                allowThirdPartyFixup: aAllowThirdPartyFixup,
   653                referrerURI: aReferrer });
   654 }
   656 // aCalledFromModal is optional
   657 function openHelpLink(aHelpTopic, aCalledFromModal, aWhere) {
   658   var url = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"]
   659                       .getService(Components.interfaces.nsIURLFormatter)
   660                       .formatURLPref("app.support.baseURL");
   661   url += aHelpTopic;
   663   var where = aWhere;
   664   if (!aWhere)
   665     where = aCalledFromModal ? "window" : "tab";
   667   openUILinkIn(url, where);
   668 }
   670 function openPrefsHelp() {
   671   // non-instant apply prefwindows are usually modal, so we can't open in the topmost window, 
   672   // since its probably behind the window.
   673   var instantApply = getBoolPref("browser.preferences.instantApply");
   675   var helpTopic = document.getElementsByTagName("prefwindow")[0].currentPane.helpTopic;
   676   openHelpLink(helpTopic, !instantApply);
   677 }
   679 function trimURL(aURL) {
   680   // This function must not modify the given URL such that calling
   681   // nsIURIFixup::createFixupURI with the result will produce a different URI.
   682   return aURL /* remove single trailing slash for http/https/ftp URLs */
   683              .replace(/^((?:http|https|ftp):\/\/[^/]+)\/$/, "$1")
   684               /* remove http:// unless the host starts with "ftp\d*\." or contains "@" */
   685              .replace(/^http:\/\/((?!ftp\d*\.)[^\/@]+(?:\/|$))/, "$1");
   686 }

mercurial