home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 35 Internet / 35-Internet.zip / phoenx05.zip / phoenix / chrome / browser.jar / content / browser / browser.js < prev    next >
Text File  |  2002-12-10  |  147KB  |  4,222 lines

  1.  
  2. const NS_ERROR_MODULE_NETWORK = 2152398848;
  3. const NS_NET_STATUS_READ_FROM = NS_ERROR_MODULE_NETWORK + 8;
  4. const NS_NET_STATUS_WROTE_TO  = NS_ERROR_MODULE_NETWORK + 9;
  5.  
  6. const nsIWebNavigation = Components.interfaces.nsIWebNavigation;
  7.  
  8. const MAX_HISTORY_MENU_ITEMS = 15;
  9. var gRDF = null;
  10. var gGlobalHistory = null;
  11. var gURIFixup = null;
  12. var gReportButton = null;
  13. var gCharsetMenu = null;
  14. var gLastBrowserCharset = null;
  15. var gPrevCharset = null;
  16. var gURLBar = null;
  17. var gProxyButton = null;
  18. var gProxyFavIcon = null;
  19. var gProxyDeck = null;
  20. var gNavigatorBundle = null;
  21. var gIsLoadingBlank = false;
  22. var gLastValidURLStr = "";
  23. var gLastValidURL = null;
  24. var gHaveUpdatedToolbarState = false;
  25. var gClickSelectsAll = false;
  26. var gIgnoreFocus = false;
  27. var gIgnoreClick = false;
  28. var gToolbarMode = "icons";
  29. var gIconSize = "";
  30. var gMustLoadSidebar = false;
  31. var gProgressMeterPanel = null;
  32. var gProgressCollapseTimer = null;
  33. var gPrefService = null;
  34. var appCore = null;
  35. var gBrowser = null;
  36.  
  37. // Global variable that holds the nsContextMenu instance.
  38. var gContextMenu = null;
  39.  
  40. var gPrintSettingsAreGlobal = true;
  41. var gSavePrintSettings = true;
  42. var gPrintSettings = null;
  43. var gChromeState = null; // chrome state before we went into print preview
  44. var gOldCloseHandler = null; // close handler before we went into print preview
  45. var gInPrintPreviewMode = false;
  46. var gWebProgress = null;
  47. var gFormHistory = null;
  48.  
  49. const dlObserver = {
  50.   observe: function(subject, topic, state) {  
  51.     if (topic != "dl-start") return;
  52.     var open = gPrefService.getBoolPref("browser.download.openSidebar");
  53.     if (open) {
  54.       var sidebar = document.getElementById("sidebar-box");
  55.       if (sidebar.hidden || (sidebar.getAttribute("sidebarcommand") != "viewDownloadsSidebar"))
  56.         toggleSidebar("viewDownloadsSidebar");
  57.     }
  58.   }
  59. };
  60.   
  61. /**
  62. * We can avoid adding multiple load event listeners and save some time by adding
  63. * one listener that calls all real handlers.
  64. */
  65.  
  66. function loadEventHandlers(event)
  67. {
  68.   // Filter out events that are not about the document load we are interested in
  69.   if (event.originalTarget == _content.document) {
  70.     UpdateBookmarksLastVisitedDate(event);
  71.     checkForDirectoryListing();
  72.     charsetLoadListener(event);
  73.   }
  74. }
  75.  
  76. /**
  77.  * Determine whether or not the content area is displaying a page with frames,
  78.  * and if so, toggle the display of the 'save frame as' menu item.
  79.  **/
  80. function getContentAreaFrameCount()
  81. {
  82.   var saveFrameItem = document.getElementById("menu_saveFrame");
  83.   if (!content || !_content.frames.length || !isDocumentFrame(document.commandDispatcher.focusedWindow))
  84.     saveFrameItem.setAttribute("hidden", "true");
  85.   else
  86.     saveFrameItem.removeAttribute("hidden");
  87. }
  88.  
  89. //////////////////////////////// BOOKMARKS ////////////////////////////////////
  90.  
  91. function UpdateBookmarksLastVisitedDate(event)
  92. {
  93.   var url = getWebNavigation().currentURI.spec;
  94.   if (url) {
  95.     // if the URL is bookmarked, update its "Last Visited" date
  96.     BMSVC.updateLastVisitedDate(url, _content.document.characterSet);
  97.   }
  98. }
  99.  
  100. function HandleBookmarkIcon(iconURL, addFlag)
  101. {
  102.   var url = getWebNavigation().currentURI.spec
  103.   if (url) {
  104.     // update URL with new icon reference
  105.     if (addFlag)
  106.       BMSVC.updateBookmarkIcon(url, iconURL);
  107.     else
  108.       BMSVC.removeBookmarkIcon(url, iconURL);
  109.   }
  110. }
  111.  
  112. function getHomePage()
  113. {
  114.   var url;
  115.   try {
  116.     url = gPrefService.getComplexValue("browser.startup.homepage",
  117.                                Components.interfaces.nsIPrefLocalizedString).data;
  118.   } catch (e) {
  119.   }
  120.  
  121.   // use this if we can't find the pref
  122.   if (!url) {
  123.     var navigatorRegionBundle = document.getElementById("bundle_browser_region");
  124.     url = navigatorRegionBundle.getString("homePageDefault");
  125.   }
  126.  
  127.   return url;
  128. }
  129.  
  130. function UpdateBackForwardButtons()
  131. {
  132.   var backBroadcaster = document.getElementById("Browser:Back");
  133.   var forwardBroadcaster = document.getElementById("Browser:Forward");
  134.   
  135.   var webNavigation = gBrowser.webNavigation;
  136.  
  137.   // Avoid setting attributes on broadcasters if the value hasn't changed!
  138.   // Remember, guys, setting attributes on elements is expensive!  They
  139.   // get inherited into anonymous content, broadcast to other widgets, etc.!
  140.   // Don't do it if the value hasn't changed! - dwh
  141.  
  142.   var backDisabled = backBroadcaster.hasAttribute("disabled");
  143.   var forwardDisabled = forwardBroadcaster.hasAttribute("disabled");
  144.   if (backDisabled == webNavigation.canGoBack) {
  145.     if (backDisabled)
  146.       backBroadcaster.removeAttribute("disabled");
  147.     else
  148.       backBroadcaster.setAttribute("disabled", true);
  149.   }
  150.   
  151.   if (forwardDisabled == webNavigation.canGoForward) {
  152.     if (forwardDisabled)
  153.       forwardBroadcaster.removeAttribute("disabled");
  154.     else
  155.       forwardBroadcaster.setAttribute("disabled", true);
  156.   }
  157. }
  158.  
  159. function UpdatePageReport(event)
  160. {
  161.   if (!gReportButton)
  162.     gReportButton = document.getElementById("page-report-button");
  163.  
  164.   if (gBrowser.mCurrentBrowser.pageReport) {
  165.     gReportButton.setAttribute("blocked", "true");
  166.     if (gPrefService && gPrefService.getBoolPref("privacy.popups.firstTime")) {
  167.       displayPageReportFirstTime();
  168.  
  169.       // Now set the pref.
  170.       gPrefService.setBoolPref("privacy.popups.firstTime", "false");
  171.     }
  172.   }
  173.   else
  174.     gReportButton.removeAttribute("blocked");
  175. }
  176.  
  177. function Startup()
  178. {
  179.   gBrowser = document.getElementById("content");
  180.  
  181.   var uriToLoad = null;
  182.   // Check for window.arguments[0]. If present, use that for uriToLoad.
  183.   if ("arguments" in window && window.arguments.length >= 1 && window.arguments[0])
  184.     uriToLoad = window.arguments[0];
  185.   gIsLoadingBlank = uriToLoad == "about:blank";
  186.  
  187.   if (!gIsLoadingBlank) {
  188.     prepareForStartup();
  189.   }
  190.  
  191.   // only load url passed in when we're not page cycling
  192.  
  193.   if (uriToLoad && !gIsLoadingBlank) {
  194.     if ("arguments" in window && window.arguments.length >= 3)
  195.       loadURI(uriToLoad, window.arguments[2]);
  196.     else
  197.       loadOneOrMoreURIs(uriToLoad);
  198.   }
  199.  
  200.   if (window.opener) {
  201.     var openerSidebarBox = window.opener.document.getElementById("sidebar-box");
  202.     if (!openerSidebarBox.hidden) {
  203.       var sidebarBox = document.getElementById("sidebar-box");
  204.       var sidebarTitle = document.getElementById("sidebar-title");
  205.       sidebarTitle.setAttribute("value", window.opener.document.getElementById("sidebar-title").getAttribute("value"));
  206.       sidebarBox.setAttribute("width", openerSidebarBox.boxObject.width);
  207.       var sidebarCmd = openerSidebarBox.getAttribute("sidebarcommand");
  208.       sidebarBox.setAttribute("sidebarcommand", sidebarCmd);
  209.       sidebarBox.setAttribute("src", window.opener.document.getElementById("sidebar").getAttribute("src"));
  210.       gMustLoadSidebar = true;
  211.       sidebarBox.hidden = false;
  212.       var sidebarSplitter = document.getElementById("sidebar-splitter");
  213.       sidebarSplitter.hidden = false;
  214.       document.getElementById(sidebarCmd).setAttribute("checked", "true");
  215.     }
  216.   }
  217.   else {
  218.     var box = document.getElementById("sidebar-box");
  219.     if (box.hasAttribute("sidebarcommand")) { 
  220.       var cmd = box.getAttribute("sidebarcommand");
  221.       if (cmd != "") {
  222.         gMustLoadSidebar = true;
  223.         box.hidden = false;
  224.         var sidebarSplitter = document.getElementById("sidebar-splitter");
  225.         sidebarSplitter.hidden = false;
  226.         document.getElementById(cmd).setAttribute("checked", "true");
  227.       }
  228.     }
  229.   }
  230.  
  231.   setTimeout(delayedStartup, 0);
  232. }
  233.  
  234. function prepareForStartup()
  235. {
  236.   gURLBar = document.getElementById("urlbar");  
  237.   gNavigatorBundle = document.getElementById("bundle_browser");
  238.   gProgressMeterPanel = document.getElementById("statusbar-progresspanel");
  239.   gBrowser.addEventListener("DOMUpdatePageReport", UpdatePageReport, false);
  240.  
  241.   var webNavigation;
  242.   try {
  243.     // Create the browser instance component.
  244.     appCore = Components.classes["@mozilla.org/appshell/component/browser/instance;1"]
  245.                         .createInstance(Components.interfaces.nsIBrowserInstance);
  246.     if (!appCore)
  247.       throw "couldn't create a browser instance";
  248.  
  249.     webNavigation = getWebNavigation();
  250.     if (!webNavigation)
  251.       throw "no XBL binding for browser";
  252.   } catch (e) {
  253.     alert("Error launching browser window:" + e);
  254.     window.close(); // Give up.
  255.     return;
  256.   }
  257.  
  258.   // initialize observers and listeners
  259.   window.XULBrowserWindow = new nsBrowserStatusHandler();
  260.   window.browserContentListener =
  261.     new nsBrowserContentListener(window, gBrowser);
  262.  
  263.   // set default character set if provided
  264.   if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) {
  265.     if (window.arguments[1].indexOf("charset=") != -1) {
  266.       var arrayArgComponents = window.arguments[1].split("=");
  267.       if (arrayArgComponents) {
  268.         //we should "inherit" the charset menu setting in a new window
  269.         getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1];
  270.       }
  271.     }
  272.   }
  273.  
  274.   // Initialize browser instance..
  275.   appCore.setWebShellWindow(window);
  276.  
  277.   // Wire up session and global history before any possible
  278.   // progress notifications for back/forward button updating
  279.   webNavigation.sessionHistory = Components.classes["@mozilla.org/browser/shistory;1"]
  280.                                            .createInstance(Components.interfaces.nsISHistory);
  281.  
  282.   // wire up global history.  the same applies here.
  283.   var globalHistory = Components.classes["@mozilla.org/browser/global-history;1"]
  284.                                 .getService(Components.interfaces.nsIGlobalHistory);
  285.   gBrowser.docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).globalHistory = globalHistory;
  286.  
  287.   const selectedBrowser = gBrowser.selectedBrowser;
  288.   if (selectedBrowser.securityUI)
  289.     selectedBrowser.securityUI.init(selectedBrowser.contentWindow);
  290.  
  291.   // hook up UI through progress listener
  292.   gBrowser.addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL);
  293. }
  294.  
  295. function delayedStartup()
  296. {
  297.   if (gIsLoadingBlank)
  298.     prepareForStartup();
  299.  
  300.   // loads the services
  301.   initServices();
  302.   initBMService();
  303.   
  304.   gBrowser.addEventListener("load", function(evt) { setTimeout(loadEventHandlers, 0, evt); }, true);
  305.  
  306.   window.addEventListener("keypress", ctrlNumberTabSelection, true);
  307.  
  308.   if (gMustLoadSidebar) {
  309.     var sidebar = document.getElementById("sidebar");
  310.     var sidebarBox = document.getElementById("sidebar-box");
  311.     sidebar.setAttribute("src", sidebarBox.getAttribute("src"));
  312.   }
  313.  
  314.  
  315.   // now load bookmarks after a delay
  316.   BMSVC.ReadBookmarks();
  317.   var bt = document.getElementById("bookmarks-toolbar");
  318.   if (bt && "toolbar" in bt)
  319.     bt.toolbar.builder.rebuild();       
  320.  
  321.   // called when we go into full screen, even if it is 
  322.   // initiated by a web page script
  323.   window.addEventListener("fullscreen", onFullScreen, false);
  324.  
  325.   var element;
  326.   if (gIsLoadingBlank && gURLBar && !gURLBar.hidden && !gURLBar.parentNode.parentNode.collapsed)
  327.     element = gURLBar;
  328.   else
  329.     element = _content;
  330.  
  331.   // This is a redo of the fix for jag bug 91884
  332.   var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
  333.                      .getService(Components.interfaces.nsIWindowWatcher);
  334.   if (window == ww.activeWindow) {
  335.     element.focus();
  336.   } else {
  337.     // set the element in command dispatcher so focus will restore properly
  338.     // when the window does become active
  339.     if (element instanceof Components.interfaces.nsIDOMElement)
  340.       document.commandDispatcher.focusedElement = element;
  341.     else if (element instanceof Components.interfaces.nsIDOMWindow)
  342.       document.commandDispatcher.focusedWindow = element;
  343.   }
  344.  
  345.   SetPageProxyState("invalid", null);
  346.  
  347.   var toolbox = document.getElementById("navigator-toolbox");
  348.   toolbox.customizeDone = BrowserToolboxCustomizeDone;
  349.  
  350.   gPrefService = Components.classes["@mozilla.org/preferences-service;1"]
  351.                               .getService(Components.interfaces.nsIPrefService);
  352.   gPrefService = gPrefService.getBranch(null);
  353.  
  354.   var observerService = Components.classes["@mozilla.org/observer-service;1"]
  355.                                   .getService(Components.interfaces.nsIObserverService);
  356.   observerService.addObserver(dlObserver, "dl-start", false);
  357.  
  358.   updateHomeTooltip();
  359. }
  360.  
  361. function Shutdown()
  362. {
  363.   try {
  364.     gBrowser.removeProgressListener(window.XULBrowserWindow);
  365.   } catch (ex) {
  366.   }
  367.  
  368.   var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
  369.   var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
  370.   var enumerator = windowManagerInterface.getEnumerator(null);
  371.   enumerator.getNext();
  372.   if (!enumerator.hasMoreElements()) {
  373.     document.persist("sidebar-box", "sidebarcommand");
  374.     document.persist("sidebar-box", "width");
  375.     document.persist("sidebar-box", "src");
  376.     document.persist("sidebar-title", "value");
  377.   }
  378.  
  379.   var service = Components.classes["@mozilla.org/observer-service;1"]
  380.                             .getService(Components.interfaces.nsIObserverService);
  381.   service.removeObserver(dlObserver, "dl-start");
  382.   service = null;
  383.  
  384.   window.XULBrowserWindow.destroy();
  385.   window.XULBrowserWindow = null;
  386.  
  387.   window.browserContentListener.close();
  388.   // Close the app core.
  389.   if (appCore)
  390.     appCore.close();
  391. }
  392.  
  393. function ctrlNumberTabSelection(event)
  394. {
  395.   if (event.altKey && event.keyCode == KeyEvent.DOM_VK_RETURN) {
  396.     // Don't let winxp beep on ALT+ENTER, since the URL bar uses it.
  397.     event.preventDefault();
  398.     return;
  399.   } 
  400.  
  401.   if (!event.ctrlKey)
  402.     return;
  403.  
  404.   var index = event.charCode - 49;
  405.   if (index < 0 || index > 8)
  406.     return;
  407.  
  408.   if (index >= gBrowser.mTabContainer.childNodes.length)
  409.     return;
  410.  
  411.   var oldTab = gBrowser.selectedTab;
  412.   var newTab = gBrowser.mTabContainer.childNodes[index];
  413.   if (newTab != oldTab) {
  414.     oldTab.selected = false;
  415.     gBrowser.selectedTab = newTab;
  416.   }
  417.  
  418.   event.preventDefault();
  419.   event.preventBubble();
  420.   event.preventCapture();
  421.   event.stopPropagation();
  422. }
  423.  
  424. function gotoHistoryIndex(aEvent)
  425. {
  426.   var index = aEvent.target.getAttribute("index");
  427.   if (!index)
  428.     return false;
  429.   try {
  430.     getWebNavigation().gotoIndex(index);
  431.   }
  432.   catch(ex) {
  433.     return false;
  434.   }
  435.   return true;
  436.  
  437. }
  438.  
  439. function BrowserBack()
  440. {
  441.   try {
  442.     getWebNavigation().goBack();
  443.   }
  444.   catch(ex) {
  445.   }
  446. }
  447.  
  448. function BrowserForward()
  449. {
  450.   try {
  451.     getWebNavigation().goForward();
  452.   }
  453.   catch(ex) {
  454.   }
  455. }
  456.  
  457. function BrowserBackMenu(event)
  458. {
  459.   return FillHistoryMenu(event.target, "back");
  460. }
  461.  
  462. function BrowserForwardMenu(event)
  463. {
  464.   return FillHistoryMenu(event.target, "forward");
  465. }
  466.  
  467. function BrowserStop()
  468. {
  469.   try {
  470.     const stopFlags = nsIWebNavigation.STOP_ALL;
  471.     getWebNavigation().stop(stopFlags);
  472.   }
  473.   catch(ex) {
  474.   }
  475. }
  476.  
  477. function BrowserReload()
  478. {
  479.   const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE;
  480.   return BrowserReloadWithFlags(reloadFlags);
  481. }
  482.  
  483. function BrowserReloadSkipCache()
  484. {
  485.   // Bypass proxy and cache.
  486.   const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE;
  487.   return BrowserReloadWithFlags(reloadFlags);
  488. }
  489.  
  490. function BrowserHome()
  491. {
  492.   var homePage = getHomePage();
  493.   loadOneOrMoreURIs(homePage);
  494. }
  495.  
  496. function loadOneOrMoreURIs(aURIString)
  497. {
  498.   if (aURIString.indexOf("|") != -1) {
  499.     var urls = aURIString.split("|");
  500.     loadURI(urls[0]);
  501.     for (var i = 1; i < urls.length; ++i)
  502.       gBrowser.addTab(urls[i]);
  503.   }
  504.   else
  505.     loadURI(aURIString);
  506. }
  507.  
  508. function constructGoMenuItem(goMenu, beforeItem, url, title)
  509. {
  510.   const kXULNS = 
  511.     "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  512.  
  513.   var menuitem = document.createElementNS(kXULNS, "menuitem");
  514.   menuitem.setAttribute("url", url);
  515.   menuitem.setAttribute("label", title);
  516.   goMenu.insertBefore(menuitem, beforeItem);
  517.   return menuitem;
  518. }
  519.  
  520. function onGoMenuHidden()
  521. {
  522.   setTimeout("destroyGoMenuItems(document.getElementById('goPopup'));", 0);
  523. }
  524.  
  525. function destroyGoMenuItems(goMenu) {
  526.   var startSeparator = document.getElementById("startHistorySeparator");
  527.   var endSeparator = document.getElementById("endHistorySeparator");
  528.   endSeparator.hidden = true;
  529.  
  530.   // Destroy the items.
  531.   var destroy = false;
  532.   for (var i = 0; i < goMenu.childNodes.length; i++) {
  533.     var item = goMenu.childNodes[i];
  534.     if (item == endSeparator)
  535.       break;
  536.  
  537.     if (destroy) {
  538.       i--;
  539.       goMenu.removeChild(item);
  540.     }
  541.  
  542.     if (item == startSeparator)
  543.       destroy = true;
  544.   }
  545. }
  546.  
  547. function updateGoMenu(goMenu)
  548. {
  549.   // In case the timer didn't fire.
  550.   destroyGoMenuItems(goMenu);
  551.  
  552.   var history = document.getElementById("hiddenHistoryTree");
  553.   
  554.   if (history.hidden) {
  555.     history.hidden = false;
  556.     var globalHistory = Components.classes["@mozilla.org/browser/global-history;1"]
  557.                                   .getService(Components.interfaces.nsIGlobalHistory);
  558.     var dataSource = globalHistory.QueryInterface(Components.interfaces.nsIRDFDataSource);
  559.     history.database.AddDataSource(dataSource);
  560.   }
  561.  
  562.   if (!history.ref)
  563.     history.ref = "NC:HistoryRoot";
  564.   
  565.   var count = history.treeBoxObject.view.rowCount;
  566.   if (count > 10)
  567.     count = 10;
  568.  
  569.   if (count == 0)
  570.     return;
  571.  
  572.   const NC_NS     = "http://home.netscape.com/NC-rdf#";
  573.  
  574.   if (!gRDF)
  575.      gRDF = Components.classes["@mozilla.org/rdf/rdf-service;1"]
  576.                       .getService(Components.interfaces.nsIRDFService);
  577.  
  578.   var builder = history.builder.QueryInterface(Components.interfaces.nsIXULTreeBuilder);
  579.   
  580.   var beforeItem = document.getElementById("endHistorySeparator");
  581.   
  582.   var nameResource = gRDF.GetResource(NC_NS + "Name");
  583.  
  584.   var endSep = beforeItem;
  585.   var showSep = false;
  586.  
  587.   for (var i = count-1; i >= 0; i--) {
  588.     var res = builder.getResourceAtIndex(i);
  589.     var url = res.Value;
  590.     var titleRes = history.database.GetTarget(res, nameResource, true);
  591.     if (!titleRes)
  592.       continue;
  593.  
  594.     showSep = true;
  595.     var titleLiteral = titleRes.QueryInterface(Components.interfaces.nsIRDFLiteral);
  596.     beforeItem = constructGoMenuItem(goMenu, beforeItem, url, titleLiteral.Value);
  597.   }
  598.  
  599.   if (showSep)
  600.     endSep.hidden = false;
  601. }
  602.  
  603. function addGroupmarkAs()
  604. {
  605.   BookmarksUtils.addBookmarkForTabBrowser(gBrowser, true);
  606. }
  607.  
  608. function addBookmarkAs(aBrowser)
  609. {
  610.   const browsers = aBrowser.browsers;
  611.   if (browsers.length > 1)
  612.     BookmarksUtils.addBookmarkForTabBrowser(aBrowser);
  613.   else
  614.     BookmarksUtils.addBookmarkForBrowser(aBrowser.webNavigation, true);
  615. }
  616.  
  617. function openLocation()
  618. {
  619.   if (gURLBar && !gURLBar.parentNode.parentNode.collapsed) {
  620.     gURLBar.focus();
  621.     gURLBar.select();
  622.   }
  623.   else {
  624.     openDialog("chrome://browser/content/openLocation.xul", "_blank", "chrome,modal,titlebar", window);
  625.   }
  626. }
  627.  
  628. function BrowserOpenTab()
  629. {
  630.   if (!gInPrintPreviewMode) {
  631.     gBrowser.selectedTab = gBrowser.addTab('about:blank');
  632.     if (gURLBar)
  633.       setTimeout("gURLBar.focus();", 0); 
  634.   }
  635. }
  636.  
  637. /* Called from the openLocation dialog. This allows that dialog to instruct
  638.    its opener to open a new window and then step completely out of the way.
  639.    Anything less byzantine is causing horrible crashes, rather believably,
  640.    though oddly only on Linux. */
  641. function delayedOpenWindow(chrome,flags,url)
  642. {
  643.   setTimeout("openDialog('"+chrome+"','_blank','"+flags+"','"+url+"')", 10);
  644. }
  645.  
  646. /* Required because the tab needs time to set up its content viewers and get the load of
  647.    the URI kicked off before becoming the active content area. */
  648. function delayedOpenTab(url)
  649. {
  650.   setTimeout(function(aTabElt) { gBrowser.selectedTab = aTabElt; }, 0, gBrowser.addTab(url));
  651. }
  652.  
  653. function BrowserOpenFileWindow()
  654. {
  655.   // Get filepicker component.
  656.   try {
  657.     const nsIFilePicker = Components.interfaces.nsIFilePicker;
  658.     var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker);
  659.     fp.init(window, gNavigatorBundle.getString("openFile"), nsIFilePicker.modeOpen);
  660.     fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | nsIFilePicker.filterImages |
  661.                      nsIFilePicker.filterXML | nsIFilePicker.filterHTML);
  662.  
  663.     if (fp.show() == nsIFilePicker.returnOK)
  664.       openTopWin(fp.fileURL.spec);
  665.   } catch (ex) {
  666.   }
  667. }
  668.  
  669. function BrowserCloseTabOrWindow()
  670. {
  671.   if (gBrowser.localName == 'tabbrowser' && gBrowser.mTabContainer.childNodes.length > 1) {
  672.     // Just close up a tab.
  673.     gBrowser.removeCurrentTab();
  674.     return;
  675.   }
  676.  
  677.   BrowserCloseWindow();
  678. }
  679.  
  680. function BrowserCloseWindow() 
  681. {
  682.   // This code replicates stuff in Shutdown().  It is here because
  683.   // window.screenX and window.screenY have real values.  We need
  684.   // to fix this eventually but by replicating the code here, we
  685.   // provide a means of saving position (it just requires that the
  686.   // user close the window via File->Close (vs. close box).
  687.   
  688.   // Get the current window position/size.
  689.   var x = window.screenX;
  690.   var y = window.screenY;
  691.   var h = window.outerHeight;
  692.   var w = window.outerWidth;
  693.  
  694.   // Store these into the window attributes (for persistence).
  695.   var win = document.getElementById( "main-window" );
  696.   win.setAttribute( "x", x );
  697.   win.setAttribute( "y", y );
  698.   win.setAttribute( "height", h );
  699.   win.setAttribute( "width", w );
  700.  
  701.   window.close();
  702. }
  703.  
  704. function loadURI(uri, referrer)
  705. {
  706.   try {
  707.     getWebNavigation().loadURI(uri, nsIWebNavigation.LOAD_FLAGS_NONE, referrer, null, null);
  708.   } catch (e) {
  709.   }
  710. }
  711.  
  712. function BrowserLoadURL(aTriggeringEvent)
  713. {
  714.   var url = gURLBar.value;
  715.   if (url.match(/^view-source:/)) {
  716.     BrowserViewSourceOfURL(url.replace(/^view-source:/, ""), null, null);
  717.   } else {
  718.     if (gBrowser.localName == "tabbrowser" &&
  719.         aTriggeringEvent && 'altKey' in aTriggeringEvent &&
  720.         aTriggeringEvent.altKey) {
  721.       _content.focus();
  722.       var t = gBrowser.addTab(url); // open link in new tab
  723.       gBrowser.selectedTab = t;
  724.       gURLBar.value = url;
  725.       event.preventDefault();
  726.       event.preventBubble();
  727.       event.preventCapture();
  728.       event.stopPropagation();
  729.     }
  730.     else  
  731.       loadURI(url);
  732.     _content.focus();
  733.   }
  734. }
  735.  
  736. function getShortcutOrURI(url)
  737. {
  738.   // rjc: added support for URL shortcuts (3/30/1999)
  739.   try {
  740.     var shortcutURL = BMSVC.resolveKeyword(url);
  741.     if (!shortcutURL) {
  742.       // rjc: add support for string substitution with shortcuts (4/4/2000)
  743.       //      (see bug # 29871 for details)
  744.       var aOffset = url.indexOf(" ");
  745.       if (aOffset > 0) {
  746.         var cmd = url.substr(0, aOffset);
  747.         var text = url.substr(aOffset+1);
  748.         shortcutURL = BMSVC.resolveKeyword(cmd);
  749.         if (shortcutURL && text) {
  750.           aOffset = shortcutURL.indexOf("%s");
  751.           if (aOffset >= 0)
  752.             shortcutURL = shortcutURL.substr(0, aOffset) + text + shortcutURL.substr(aOffset+2);
  753.           else
  754.             shortcutURL = null;
  755.         }
  756.       }
  757.     }
  758.  
  759.     if (shortcutURL)
  760.       url = shortcutURL;
  761.  
  762.   } catch (ex) {
  763.   }
  764.   return url;
  765. }
  766.  
  767. function readFromClipboard()
  768. {
  769.   var url;
  770.  
  771.   try {
  772.     // Get clipboard.
  773.     var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"]
  774.                               .getService(Components.interfaces.nsIClipboard);
  775.  
  776.     // Create tranferable that will transfer the text.
  777.     var trans = Components.classes["@mozilla.org/widget/transferable;1"]
  778.                           .createInstance(Components.interfaces.nsITransferable);
  779.  
  780.     trans.addDataFlavor("text/unicode");
  781.     clipboard.getData(trans, clipboard.kSelectionClipboard);
  782.  
  783.     var data = {};
  784.     var dataLen = {};
  785.     trans.getTransferData("text/unicode", data, dataLen);
  786.  
  787.     if (data) {
  788.       data = data.value.QueryInterface(Components.interfaces.nsISupportsString);
  789.       url = data.data.substring(0, dataLen.value / 2);
  790.     }
  791.   } catch (ex) {
  792.   }
  793.  
  794.   return url;
  795. }
  796.  
  797. function BrowserViewSourceOfDocument(aDocument)
  798. {
  799.   var docCharset;
  800.   var pageCookie;
  801.   var webNav;
  802.  
  803.   // Get the document charset
  804.   docCharset = "charset=" + aDocument.characterSet;
  805.  
  806.   // Get the nsIWebNavigation associated with the document
  807.   try {
  808.       var win;
  809.       var ifRequestor;
  810.  
  811.       // Get the DOMWindow for the requested document.  If the DOMWindow
  812.       // cannot be found, then just use the _content window...
  813.       //
  814.       // XXX:  This is a bit of a hack...
  815.       win = aDocument.defaultView;
  816.       if (win == window) {
  817.         win = _content;
  818.       }
  819.       ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  820.  
  821.       webNav = ifRequestor.getInterface(nsIWebNavigation);
  822.   } catch(err) {
  823.       // If nsIWebNavigation cannot be found, just get the one for the whole
  824.       // window...
  825.       webNav = getWebNavigation();
  826.   }
  827.   //
  828.   // Get the 'PageDescriptor' for the current document. This allows the
  829.   // view-source to access the cached copy of the content rather than
  830.   // refetching it from the network...
  831.   //
  832.   try{
  833.     var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor);
  834.  
  835.     pageCookie = PageLoader.currentDescriptor;
  836.   } catch(err) {
  837.     // If no page descriptor is available, just use the view-source URL...
  838.   }
  839.  
  840.   BrowserViewSourceOfURL(webNav.currentURI.spec, docCharset, pageCookie);
  841. }
  842.  
  843. function BrowserViewSourceOfURL(url, charset, pageCookie)
  844. {
  845.   // try to open a view-source window while inheriting the charset (if any)
  846.   openDialog("chrome://browser/content/viewSource.xul",
  847.              "_blank",
  848.              "scrollbars,resizable,chrome,dialog=no",
  849.              url, charset, pageCookie);
  850. }
  851.  
  852. // doc=null for regular page info, doc=owner document for frame info.
  853. function BrowserPageInfo(doc)
  854. {
  855.   window.openDialog("chrome://navigator/content/pageInfo.xul",
  856.                     "_blank",
  857.                     "chrome,dialog=no",
  858.                     doc);
  859. }
  860.  
  861.  
  862. function checkForDirectoryListing()
  863. {
  864.   if ( "HTTPIndex" in _content &&
  865.        _content.HTTPIndex instanceof Components.interfaces.nsIHTTPIndex ) {
  866.     _content.defaultCharacterset = getMarkupDocumentViewer().defaultCharacterSet;
  867.   }
  868. }
  869.  
  870. /**
  871.  * Use Stylesheet functions.
  872.  *     Written by Tim Hill (bug 6782)
  873.  *     Frameset handling by Neil Rashbrook <neil@parkwaycc.co.uk>
  874.  **/
  875. function getStyleSheetArray(frame)
  876. {
  877.   var styleSheets = frame.document.styleSheets;
  878.   var styleSheetsArray = new Array(styleSheets.length);
  879.   for (var i = 0; i < styleSheets.length; i++) {
  880.     styleSheetsArray[i] = styleSheets[i];
  881.   }
  882.   return styleSheetsArray;
  883. }
  884.  
  885. function getAllStyleSheets(frameset)
  886. {
  887.   var styleSheetsArray = getStyleSheetArray(frameset);
  888.   for (var i = 0; i < frameset.frames.length; i++) {
  889.     var frameSheets = getAllStyleSheets(frameset.frames[i]);
  890.     styleSheetsArray = styleSheetsArray.concat(frameSheets);
  891.   }
  892.   return styleSheetsArray;
  893. }
  894.  
  895. function stylesheetFillPopup(menuPopup)
  896. {
  897.   var itemNoOptStyles = menuPopup.firstChild;
  898.   while (itemNoOptStyles.nextSibling)
  899.     menuPopup.removeChild(itemNoOptStyles.nextSibling);
  900.  
  901.   var noOptionalStyles = true;
  902.   var styleSheets = getAllStyleSheets(window._content);
  903.   var currentStyleSheets = [];
  904.  
  905.   for (var i = 0; i < styleSheets.length; ++i) {
  906.     var currentStyleSheet = styleSheets[i];
  907.  
  908.     if (currentStyleSheet.title) {
  909.       if (!currentStyleSheet.disabled)
  910.         noOptionalStyles = false;
  911.  
  912.       var lastWithSameTitle = null;
  913.       if (currentStyleSheet.title in currentStyleSheets)
  914.         lastWithSameTitle = currentStyleSheets[currentStyleSheet.title];
  915.  
  916.       if (!lastWithSameTitle) {
  917.         var menuItem = document.createElement("menuitem");
  918.         menuItem.setAttribute("type", "radio");
  919.         menuItem.setAttribute("label", currentStyleSheet.title);
  920.         menuItem.setAttribute("data", currentStyleSheet.title);
  921.         menuItem.setAttribute("checked", !currentStyleSheet.disabled);
  922.         menuPopup.appendChild(menuItem);
  923.         currentStyleSheets[currentStyleSheet.title] = menuItem;
  924.       } else {
  925.         if (currentStyleSheet.disabled)
  926.           lastWithSameTitle.removeAttribute("checked");
  927.       }
  928.     }
  929.   }
  930.   itemNoOptStyles.setAttribute("checked", noOptionalStyles);
  931. }
  932.  
  933. function stylesheetInFrame(frame, title) {
  934.   var docStyleSheets = frame.document.styleSheets;
  935.  
  936.   for (var i = 0; i < docStyleSheets.length; ++i) {
  937.     if (docStyleSheets[i].title == title)
  938.       return true;
  939.   }
  940.   return false;
  941. }
  942.  
  943. function stylesheetSwitchFrame(frame, title) {
  944.   var docStyleSheets = frame.document.styleSheets;
  945.  
  946.   for (var i = 0; i < docStyleSheets.length; ++i) {
  947.     var docStyleSheet = docStyleSheets[i];
  948.  
  949.     if (docStyleSheet.title)
  950.       docStyleSheet.disabled = (docStyleSheet.title != title);
  951.     else if (docStyleSheet.disabled)
  952.       docStyleSheet.disabled = false;
  953.   }
  954. }
  955.  
  956. function stylesheetSwitchAll(frameset, title) {
  957.   if (!title || stylesheetInFrame(frameset, title)) {
  958.     stylesheetSwitchFrame(frameset, title);
  959.   }
  960.   for (var i = 0; i < frameset.frames.length; i++) {
  961.     stylesheetSwitchAll(frameset.frames[i], title);
  962.   }
  963. }
  964.  
  965. function URLBarFocusHandler(aEvent, aElt)
  966. {
  967.   if (gIgnoreFocus)
  968.     gIgnoreFocus = false;
  969.   else if (gClickSelectsAll)
  970.     aElt.select();
  971. }
  972.  
  973. function URLBarMouseDownHandler(aEvent, aElt)
  974. {
  975.   if (aElt.hasAttribute("focused")) {
  976.     gIgnoreClick = true;
  977.   } else {
  978.     gIgnoreFocus = true;
  979.     gIgnoreClick = false;
  980.     aElt.setSelectionRange(0, 0);
  981.   }
  982. }
  983.  
  984. function URLBarClickHandler(aEvent, aElt)
  985. {
  986.   if (!gIgnoreClick && gClickSelectsAll && aElt.selectionStart == aElt.selectionEnd)
  987.     aElt.select();
  988. }
  989.  
  990. // If "ESC" is pressed in the url bar, we replace the urlbar's value with the url of the page
  991. // and highlight it, unless it is about:blank, where we reset it to "".
  992. function handleURLBarRevert()
  993. {
  994.   var url = getWebNavigation().currentURI.spec;
  995.   var throbberElement = document.getElementById("navigator-throbber");
  996.  
  997.   var isScrolling = gURLBar.popupOpen;
  998.   
  999.   // don't revert to last valid url unless page is NOT loading
  1000.   // and user is NOT key-scrolling through autocomplete list
  1001.   if ((!throbberElement || !throbberElement.hasAttribute("busy")) && !isScrolling) {
  1002.     if (url != "about:blank") { 
  1003.       gURLBar.value = url;
  1004.       gURLBar.select();
  1005.       SetPageProxyState("valid", null); // XXX Build a URI and pass it in here.
  1006.     } else { //if about:blank, urlbar becomes ""
  1007.       gURLBar.value = "";
  1008.     }
  1009.   }
  1010.  
  1011.   // tell widget to revert to last typed text only if the user
  1012.   // was scrolling when they hit escape
  1013.   return !isScrolling; 
  1014. }
  1015.  
  1016. function handleURLBarCommand(aTriggeringEvent)
  1017. {
  1018.   canonizeUrl(aTriggeringEvent);
  1019.  
  1020.   try { 
  1021.     addToUrlbarHistory();
  1022.   } catch (ex) {
  1023.     // Things may go wrong when adding url to session history,
  1024.     // but don't let that interfere with the loading of the url.
  1025.   }
  1026.   
  1027.   BrowserLoadURL(aTriggeringEvent); 
  1028. }
  1029.  
  1030. function canonizeUrl(aTriggeringEvent)
  1031. {
  1032.   if (!gURLBar)
  1033.     return;
  1034.   
  1035.   var url = gURLBar.value;
  1036.   if (aTriggeringEvent && 'ctrlKey' in aTriggeringEvent &&
  1037.       aTriggeringEvent.ctrlKey && 'shiftKey' in aTriggeringEvent &&
  1038.       aTriggeringEvent.shiftKey)
  1039.     // Tack http://www. and .org on.
  1040.     url = "http://www." + url + ".org/";
  1041.   else if (aTriggeringEvent && 'ctrlKey' in aTriggeringEvent &&
  1042.       aTriggeringEvent.ctrlKey)
  1043.     // Tack www. and .com on.
  1044.     url = "http://www." + url + ".com/";
  1045.   else if (aTriggeringEvent && 'shiftKey' in aTriggeringEvent &&
  1046.       aTriggeringEvent.shiftKey)
  1047.     // Tack www. and .org on.
  1048.     url = "http://www." + url + ".net/";
  1049.  
  1050.   gURLBar.value = getShortcutOrURI(url);
  1051. }
  1052.  
  1053. function UpdatePageProxyState()
  1054. {
  1055.   if (gURLBar && gURLBar.value != gLastValidURLStr)
  1056.     SetPageProxyState("invalid", null);
  1057. }
  1058.  
  1059. function SetPageProxyState(aState, aURI)
  1060. {
  1061.   if (!gURLBar)
  1062.     return;
  1063.  
  1064.   if (!gProxyButton)
  1065.     gProxyButton = document.getElementById("page-proxy-button");
  1066.   if (!gProxyFavIcon)
  1067.     gProxyFavIcon = document.getElementById("page-proxy-favicon");
  1068.   if (!gProxyDeck)
  1069.     gProxyDeck = document.getElementById("page-proxy-deck");
  1070.  
  1071.   gProxyButton.setAttribute("pageproxystate", aState);
  1072.  
  1073.   if (aState == "valid") {
  1074.     gLastValidURLStr = gURLBar.value;
  1075.     gURLBar.addEventListener("input", UpdatePageProxyState, false);
  1076.     if (gBrowser.shouldLoadFavIcon(aURI)) {
  1077.       var favStr = gBrowser.buildFavIconString(aURI);
  1078.       if (favStr != gProxyFavIcon.src) {
  1079.         gBrowser.loadFavIcon(aURI, "src", gProxyFavIcon);
  1080.         gProxyDeck.selectedIndex = 0;
  1081.       }
  1082.       else gProxyDeck.selectedIndex = 1;
  1083.     }
  1084.     else {
  1085.       gProxyDeck.selectedIndex = 0;
  1086.       gProxyFavIcon.removeAttribute("src");
  1087.     }
  1088.   } else if (aState == "invalid") {
  1089.     gURLBar.removeEventListener("input", UpdatePageProxyState, false);
  1090.     gProxyDeck.selectedIndex = 0;
  1091.   }
  1092. }
  1093.  
  1094. function PageProxyDragGesture(aEvent)
  1095. {
  1096.   if (gProxyButton.getAttribute("pageproxystate") == "valid") {
  1097.     nsDragAndDrop.startDrag(aEvent, proxyIconDNDObserver);
  1098.     return true;
  1099.   }
  1100.   return false;
  1101. }
  1102.  
  1103. function SearchBarPopupShowing(aEvent)
  1104. {
  1105.   var searchBar = document.getElementById("search-bar");
  1106.   var searchMode = searchBar.searchMode;
  1107.  
  1108.   var popup = document.getElementById("SearchBarPopup");
  1109.   var node = popup.firstChild;
  1110.   while (node) {
  1111.     node.setAttribute("checked", node.id == searchMode);
  1112.     node = node.nextSibling;
  1113.   }
  1114.  
  1115.   var findItem = document.getElementById("miSearchModeFind");
  1116.   findItem.setAttribute("checked", !searchMode);
  1117. }
  1118.  
  1119. function SearchBarPopupCommand(aEvent)
  1120. {
  1121.   var searchBar = document.getElementById("search-bar");
  1122.  
  1123.   if (aEvent.target.id == "miSearchModeFind") {
  1124.     searchBar.removeAttribute("searchmode");
  1125.     searchBar.setAttribute("autocompletesearchparam", "__PhoenixFindInPage");
  1126.     gPrefService.setCharPref("browser.search.defaultengine", "");
  1127.  
  1128.     // Clear out the search engine icon
  1129.     searchBar.firstChild.removeAttribute("src");
  1130.   } else {
  1131.     searchBar.setAttribute("searchmode", aEvent.target.id);
  1132.     searchBar.setAttribute("autocompletesearchparam", "q");
  1133.     gPrefService.setCharPref("browser.search.defaultengine", aEvent.target.id);
  1134.   }
  1135.   
  1136.   searchBar.detachController();
  1137.   focusSearchBar();
  1138. }
  1139.  
  1140. function handleSearchBarCommand(aEvent)
  1141. {
  1142.   var searchBar = document.getElementById("search-bar");
  1143.  
  1144.   // Save the current value in the form history
  1145.   if (!gFormHistory)
  1146.     gFormHistory = Components.classes["@mozilla.org/satchel/form-history;1"]
  1147.                              .getService(Components.interfaces.nsIFormHistory);
  1148.   gFormHistory.addEntry(searchBar.getAttribute("autocompletesearchparam"), searchBar.value);
  1149.  
  1150.   if (searchBar.hasAttribute("searchmode")) {
  1151.     gURLBar.value = searchBar.searchValue;
  1152.     BrowserLoadURL(aEvent);
  1153.   } else {
  1154.     quickFindInPage(searchBar.value);
  1155.   }
  1156. }
  1157.  
  1158. function quickFindInPage(aValue)
  1159. {
  1160.   var focusedWindow = document.commandDispatcher.focusedWindow;
  1161.   if (!focusedWindow || focusedWindow == window)
  1162.     focusedWindow = window._content;
  1163.       
  1164.   var findInst = gBrowser.webBrowserFind;
  1165.   var findInFrames = findInst.QueryInterface(Components.interfaces.nsIWebBrowserFindInFrames);
  1166.   findInFrames.rootSearchFrame = _content;
  1167.   findInFrames.currentSearchFrame = focusedWindow;
  1168.  
  1169.   var findService = Components.classes["@mozilla.org/find/find_service;1"]
  1170.                           .getService(Components.interfaces.nsIFindService);
  1171.   findInst.searchString  = aValue;
  1172.   findInst.matchCase     = findService.matchCase;
  1173.   findInst.wrapFind      = true;
  1174.   findInst.entireWord    = findService.entireWord;
  1175.   findInst.findBackwards = false;
  1176.  
  1177.   findInst.findNext();
  1178. }
  1179.  
  1180. function updateToolbarStates(toolbarMenuElt)
  1181. {
  1182.   if (!gHaveUpdatedToolbarState) {
  1183.     var mainWindow = document.getElementById("main-window");
  1184.     if (mainWindow.hasAttribute("chromehidden")) {
  1185.       gHaveUpdatedToolbarState = true;
  1186.       var i;
  1187.       for (i = 0; i < toolbarMenuElt.childNodes.length; ++i)
  1188.         document.getElementById(toolbarMenuElt.childNodes[i].getAttribute("observes")).removeAttribute("checked");
  1189.       var toolbars = document.getElementsByTagName("toolbar");
  1190.       
  1191.       // Start i at 1, since we skip the menubar.
  1192.       for (i = 1; i < toolbars.length; ++i) {
  1193.         if (toolbars[i].getAttribute("class").indexOf("chromeclass") != -1)
  1194.           toolbars[i].setAttribute("hidden", "true");
  1195.       }
  1196.       var statusbars = document.getElementsByTagName("statusbar");
  1197.       for (i = 1; i < statusbars.length; ++i) {
  1198.         if (statusbars[i].getAttribute("class").indexOf("chromeclass") != -1)
  1199.           statusbars[i].setAttribute("hidden", "true");
  1200.       }
  1201.       mainWindow.removeAttribute("chromehidden");
  1202.     }
  1203.   }
  1204. }
  1205.  
  1206. // Fill in tooltips for personal toolbar
  1207. function FillInPTTooltip(tipElement)
  1208. {
  1209.  
  1210.   var title = tipElement.label;
  1211.   var url = tipElement.statusText;
  1212.  
  1213.   if (!title && !url) {
  1214.     // bail out early if there is nothing to show
  1215.     return false;
  1216.   }
  1217.  
  1218.   var tooltipTitle = document.getElementById("ptTitleText");
  1219.   var tooltipUrl = document.getElementById("ptUrlText"); 
  1220.  
  1221.   if (title && title != url) {
  1222.     tooltipTitle.removeAttribute("hidden");
  1223.     tooltipTitle.setAttribute("value", title);
  1224.   } else  {
  1225.     tooltipTitle.setAttribute("hidden", "true");
  1226.   }
  1227.  
  1228.   if (url) {
  1229.     tooltipUrl.removeAttribute("hidden");
  1230.     tooltipUrl.setAttribute("value", url);
  1231.   } else {
  1232.     tooltipUrl.setAttribute("hidden", "true");
  1233.   }
  1234.  
  1235.   return true; // show tooltip
  1236. }
  1237.  
  1238. function BrowserFullScreen()
  1239. {
  1240.   window.fullScreen = !window.fullScreen;
  1241. }
  1242.  
  1243. function onFullScreen()
  1244. {
  1245.   FullScreen.toggle();
  1246.   
  1247. }
  1248.  
  1249. function getWebNavigation()
  1250. {
  1251.   try {
  1252.     return gBrowser.webNavigation;
  1253.   } catch (e) {
  1254.     return null;
  1255.   }
  1256. }
  1257.  
  1258. function BrowserReloadWithFlags(reloadFlags)
  1259. {
  1260.   /* First, we'll try to use the session history object to reload so 
  1261.    * that framesets are handled properly. If we're in a special 
  1262.    * window (such as view-source) that has no session history, fall 
  1263.    * back on using the web navigation's reload method.
  1264.    */
  1265.  
  1266.   var webNav = getWebNavigation();
  1267.   try {
  1268.     var sh = webNav.sessionHistory;
  1269.     if (sh)
  1270.       webNav = sh.QueryInterface(nsIWebNavigation);
  1271.   } catch (e) {
  1272.   }
  1273.  
  1274.   try {
  1275.     webNav.reload(reloadFlags);
  1276.   } catch (e) {
  1277.   }
  1278. }
  1279.  
  1280. function toggleAffectedChrome(aHide)
  1281. {
  1282.   // chrome to toggle includes:
  1283.   //   (*) menubar
  1284.   //   (*) navigation bar
  1285.   //   (*) bookmarks toolbar
  1286.   //   (*) tab browser ``strip''
  1287.   //   (*) sidebar
  1288.  
  1289.   if (!gChromeState)
  1290.     gChromeState = new Object;
  1291.   var navToolbox = document.getElementById("navigator-toolbox");
  1292.   navToolbox.hidden = aHide;
  1293.   if (aHide)
  1294.   {
  1295.     // going into print preview mode
  1296.     //deal with tab browser
  1297.     gChromeState.hadTabStrip = gBrowser.getStripVisibility();
  1298.     gBrowser.setStripVisibilityTo(false);
  1299.     
  1300.     var sidebar = document.getElementById("sidebar-box");
  1301.     gChromeState.sidebarOpen = !sidebar.hidden;
  1302.     if (gChromeState.sidebarOpen) {
  1303.       toggleSidebar();
  1304.     }
  1305.   }
  1306.   else
  1307.   {
  1308.     // restoring normal mode (i.e., leaving print preview mode)
  1309.     //restore tab browser
  1310.     gBrowser.setStripVisibilityTo(gChromeState.hadTabStrip);
  1311.     if (gChromeState.sidebarOpen) {
  1312.       toggleSidebar();
  1313.     }
  1314.   }
  1315. }
  1316.  
  1317. function showPrintPreviewToolbar()
  1318. {
  1319.   toggleAffectedChrome(true);
  1320.   const kXULNS = 
  1321.     "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  1322.  
  1323.   var printPreviewTB = document.createElementNS(kXULNS, "toolbar");
  1324.   printPreviewTB.setAttribute("printpreview", true);
  1325.   printPreviewTB.setAttribute("id", "print-preview-toolbar");
  1326.  
  1327.   var navToolbox = document.getElementById("navigator-toolbox");
  1328.   navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox);
  1329. }
  1330.  
  1331. function BrowserExitPrintPreview()
  1332. {
  1333.   gInPrintPreviewMode = false;
  1334.  
  1335.   gBrowser.setAttribute("handleCtrlPageUpDown", "true");
  1336.  
  1337.   // exit print preview galley mode in content area
  1338.   var ifreq = _content.QueryInterface(
  1339.     Components.interfaces.nsIInterfaceRequestor);
  1340.   var webBrowserPrint = ifreq.getInterface(
  1341.     Components.interfaces.nsIWebBrowserPrint);     
  1342.   webBrowserPrint.exitPrintPreview(); 
  1343.   _content.focus();
  1344.  
  1345.   // remove the print preview toolbar
  1346.   var navToolbox = document.getElementById("navigator-toolbox");
  1347.   var printPreviewTB = document.getElementById("print-preview-toolbar");
  1348.   navToolbox.parentNode.removeChild(printPreviewTB);
  1349.  
  1350.   // restore chrome to original state
  1351.   toggleAffectedChrome(false);
  1352.  
  1353.   // restore old onclose handler if we found one before previewing
  1354.   var mainWin = document.getElementById("main-window");
  1355.   mainWin.setAttribute("onclose", gOldCloseHandler);
  1356. }
  1357.  
  1358. function GetPrintSettings()
  1359. {
  1360.   var prevPS = gPrintSettings;
  1361.  
  1362.   try {
  1363.     if (gPrintSettings == null) {
  1364.       gPrintSettingsAreGlobal = gPrefService.getBoolPref("print.use_global_printsettings", false);
  1365.       gSavePrintSettings = gPrefService.getBoolPref("print.save_print_settings", false);
  1366.  
  1367.       var psService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
  1368.                                         .getService(Components.interfaces.nsIPrintSettingsService);
  1369.       if (gPrintSettingsAreGlobal) {
  1370.         gPrintSettings = psService.globalPrintSettings;        
  1371.         if (gSavePrintSettings) {
  1372.           psService.initPrintSettingsFromPrefs(gPrintSettings, false, gPrintSettings.kInitSaveNativeData);
  1373.         }
  1374.       } else {
  1375.         gPrintSettings = psService.newPrintSettings;
  1376.       }
  1377.     }
  1378.   } catch (e) {
  1379.     dump("GetPrintSettings "+e);
  1380.   }
  1381.  
  1382.   return gPrintSettings;
  1383. }
  1384.  
  1385. // This observer is called once the progress dialog has been "opened"
  1386. var gPrintPreviewObs = {
  1387.     observe: function(aSubject, aTopic, aData)
  1388.     {
  1389.       setTimeout(FinishPrintPreview, 0);
  1390.     },
  1391.  
  1392.     QueryInterface : function(iid)
  1393.     {
  1394.      if (iid.equals(Components.interfaces.nsIObserver) || iid.equals(Components.interfaces.nsISupportsWeakReference))
  1395.       return this;
  1396.      
  1397.      throw Components.results.NS_NOINTERFACE;
  1398.     }
  1399. };
  1400.  
  1401. function BrowserPrintPreview()
  1402. {
  1403.   var ifreq;
  1404.   var webBrowserPrint;  
  1405.   try {
  1406.     ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  1407.     webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint);     
  1408.     gPrintSettings = GetPrintSettings();
  1409.  
  1410.   } catch (e) {
  1411.     // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
  1412.     // causing an exception to be thrown which we catch here.
  1413.     // Unfortunately this will also consume helpful failures, so add a
  1414.     // dump(e); // if you need to debug
  1415.   }
  1416.  
  1417.   // Here we get the PrintingPromptService tso we can display the PP Progress from script
  1418.   // For the browser implemented via XUL with the PP toolbar we cannot let it be
  1419.   // automatically opened from the print engine because the XUL scrollbars in the PP window
  1420.   // will layout before the content window and a crash will occur.
  1421.   //
  1422.   // Doing it all from script, means it lays out before hand and we can let printing do it's own thing
  1423.   gWebProgress = new Object();
  1424.  
  1425.   var printPreviewParams    = new Object();
  1426.   var notifyOnOpen          = new Object();
  1427.   var printingPromptService = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"]
  1428.                                   .getService(Components.interfaces.nsIPrintingPromptService);
  1429.   if (printingPromptService) {
  1430.     // just in case we are already printing, 
  1431.     // an error code could be returned if the Prgress Dialog is already displayed
  1432.     try {
  1433.       printingPromptService.showProgress(this, webBrowserPrint, gPrintSettings, gPrintPreviewObs, false, gWebProgress, 
  1434.                                          printPreviewParams, notifyOnOpen);
  1435.       if (printPreviewParams.value) {
  1436.         var webNav = getWebNavigation();
  1437.         printPreviewParams.value.docTitle = webNav.document.title;
  1438.         printPreviewParams.value.docURL   = webNav.currentURI.spec;
  1439.       }
  1440.  
  1441.       // this tells us whether we should continue on with PP or 
  1442.       // wait for the callback via the observer
  1443.       if (!notifyOnOpen.value.valueOf() || gWebProgress.value == null) {
  1444.         FinishPrintPreview();
  1445.       }
  1446.     } catch (e) {
  1447.       FinishPrintPreview();
  1448.     }
  1449.   }
  1450. }
  1451.  
  1452. function FinishPrintPreview()
  1453. {
  1454.   try {
  1455.     var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  1456.     var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint);     
  1457.     if (webBrowserPrint) {
  1458.       gPrintSettings = GetPrintSettings();
  1459.       webBrowserPrint.printPreview(gPrintSettings, null, gWebProgress.value);
  1460.     }
  1461.  
  1462.     gBrowser.setAttribute("handleCtrlPageUpDown", "false");
  1463.  
  1464.     var mainWin = document.getElementById("main-window");
  1465.  
  1466.     // save previous close handler to restoreon exiting print preview mode
  1467.     if (mainWin.hasAttribute("onclose"))
  1468.       gOldCloseHandler = mainWin.getAttribute("onclose");
  1469.     else
  1470.       gOldCloseHandler = null;
  1471.     mainWin.setAttribute("onclose", "BrowserExitPrintPreview(); return false;");
  1472.  
  1473.     // show the toolbar after we go into print preview mode so
  1474.     // that we can initialize the toolbar with total num pages
  1475.     showPrintPreviewToolbar();
  1476.  
  1477.     _content.focus();
  1478.   } catch (e) {
  1479.     // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
  1480.     // causing an exception to be thrown which we catch here.
  1481.     // Unfortunately this will also consume helpful failures, so add a
  1482.     // dump(e); // if you need to debug
  1483.   }
  1484.   gInPrintPreviewMode = true;
  1485. }
  1486.  
  1487. function BrowserPrintSetup()
  1488. {
  1489.   var didOK = false;
  1490.   try {
  1491.     var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  1492.     var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint);     
  1493.     if (webBrowserPrint) {
  1494.       gPrintSettings = GetPrintSettings();
  1495.     }
  1496.  
  1497.     didOK = goPageSetup(window, gPrintSettings);  // from utilityOverlay.js
  1498.     if (didOK) {  // from utilityOverlay.js
  1499.  
  1500.       if (webBrowserPrint) {
  1501.         if (gPrintSettingsAreGlobal && gSavePrintSettings) {
  1502.           var psService = Components.classes["@mozilla.org/gfx/printsettings-service;1"]
  1503.                                             .getService(Components.interfaces.nsIPrintSettingsService);
  1504.           psService.savePrintSettingsToPrefs(gPrintSettings, false, gPrintSettings.kInitSaveNativeData);
  1505.         }
  1506.       }
  1507.     }
  1508.   } catch (e) {
  1509.     dump("BrowserPrintSetup "+e);
  1510.   }
  1511.   return didOK;
  1512. }
  1513.  
  1514. function BrowserPrint()
  1515. {
  1516.   try {
  1517.     var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  1518.     var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint);     
  1519.     if (webBrowserPrint) {
  1520.       gPrintSettings = GetPrintSettings();
  1521.       webBrowserPrint.print(gPrintSettings, null);
  1522.     }
  1523.   } catch (e) {
  1524.     // Pressing cancel is expressed as an NS_ERROR_ABORT return value,
  1525.     // causing an exception to be thrown which we catch here.
  1526.     // Unfortunately this will also consume helpful failures, so add a
  1527.     // dump(e); // if you need to debug
  1528.   }
  1529. }
  1530.  
  1531. function BrowserFind()
  1532. {
  1533.   var focusedWindow = document.commandDispatcher.focusedWindow;
  1534.   if (!focusedWindow || focusedWindow == window)
  1535.     focusedWindow = window._content;
  1536.  
  1537.   findInPage(gBrowser, window._content, focusedWindow)
  1538. }
  1539.  
  1540. function BrowserFindAgain(reverse)
  1541. {
  1542.     var focusedWindow = document.commandDispatcher.focusedWindow;
  1543.     if (!focusedWindow || focusedWindow == window)
  1544.       focusedWindow = window._content;
  1545.  
  1546.   findAgainInPage(gBrowser, window._content, focusedWindow, reverse)
  1547. }
  1548.  
  1549. function BrowserCanFindAgain()
  1550. {
  1551.   return canFindAgainInPage();
  1552. }
  1553.  
  1554. function getMarkupDocumentViewer()
  1555. {
  1556.   return gBrowser.markupDocumentViewer;
  1557. }
  1558.  
  1559. /**
  1560.  * Content area tooltip.
  1561.  * XXX - this must move into XBL binding/equiv! Do not want to pollute
  1562.  *       browser.js with functionality that can be encapsulated into
  1563.  *       browser widget. TEMPORARY!
  1564.  *
  1565.  * NOTE: Any changes to this routine need to be mirrored in ChromeListener::FindTitleText()
  1566.  *       (located in mozilla/embedding/browser/webBrowser/nsDocShellTreeOwner.cpp)
  1567.  *       which performs the same function, but for embedded clients that
  1568.  *       don't use a XUL/JS layer. It is important that the logic of
  1569.  *       these two routines be kept more or less in sync.
  1570.  *       (pinkerton)
  1571.  **/
  1572. function FillInHTMLTooltip(tipElement)
  1573. {
  1574.   var retVal = false;
  1575.   if (tipElement.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul")
  1576.     return retVal;
  1577.  
  1578.   const XLinkNS = "http://www.w3.org/1999/xlink";
  1579.  
  1580.  
  1581.   var titleText = null;
  1582.   var XLinkTitleText = null;
  1583.   
  1584.   while (!titleText && !XLinkTitleText && tipElement) {
  1585.     if (tipElement.nodeType == Node.ELEMENT_NODE) {
  1586.       titleText = tipElement.getAttribute("title");
  1587.       XLinkTitleText = tipElement.getAttributeNS(XLinkNS, "title");
  1588.     }
  1589.     tipElement = tipElement.parentNode;
  1590.   }
  1591.  
  1592.   var texts = [titleText, XLinkTitleText];
  1593.   var tipNode = document.getElementById("aHTMLTooltip");
  1594.  
  1595.   for (var i = 0; i < texts.length; ++i) {
  1596.     var t = texts[i];
  1597.     if (t && t.search(/\S/) >= 0) {
  1598.       tipNode.setAttribute("label", t);
  1599.       retVal = true;
  1600.     }
  1601.   }
  1602.  
  1603.   return retVal;
  1604. }
  1605.  
  1606. var proxyIconDNDObserver = {
  1607.   onDragStart: function (aEvent, aXferData, aDragAction)
  1608.     {
  1609.       var value = gURLBar.value;
  1610.       // XXX - do we want to allow the user to set a blank page to their homepage?
  1611.       //       if so then we want to modify this a little to set about:blank as
  1612.       //       the homepage in the event of an empty urlbar.
  1613.       if (!value) return;
  1614.  
  1615.       var urlString = value + "\n" + window._content.document.title;
  1616.       var htmlString = "<a href=\"" + value + "\">" + value + "</a>";
  1617.  
  1618.       aXferData.data = new TransferData();
  1619.       aXferData.data.addDataForFlavour("text/x-moz-url", urlString);
  1620.       aXferData.data.addDataForFlavour("text/unicode", value);
  1621.       aXferData.data.addDataForFlavour("text/html", htmlString);
  1622.     }
  1623. }
  1624.  
  1625. var homeButtonObserver = {
  1626.   onDrop: function (aEvent, aXferData, aDragSession)
  1627.     {
  1628.       var url = transferUtils.retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);
  1629.       setTimeout(openHomeDialog, 0, url);
  1630.     },
  1631.  
  1632.   onDragOver: function (aEvent, aFlavour, aDragSession)
  1633.     {
  1634.       var statusTextFld = document.getElementById("statusbar-display");
  1635.       statusTextFld.label = gNavigatorBundle.getString("droponhomebutton");
  1636.       aDragSession.dragAction = Components.interfaces.nsIDragService.DRAGDROP_ACTION_LINK;
  1637.     },
  1638.  
  1639.   onDragExit: function (aEvent, aDragSession)
  1640.     {
  1641.       var statusTextFld = document.getElementById("statusbar-display");
  1642.       statusTextFld.label = "";
  1643.     },
  1644.  
  1645.   getSupportedFlavours: function ()
  1646.     {
  1647.       var flavourSet = new FlavourSet();
  1648.       flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  1649.       flavourSet.appendFlavour("text/x-moz-url");
  1650.       flavourSet.appendFlavour("text/unicode");
  1651.       return flavourSet;
  1652.     }
  1653. }
  1654.  
  1655. function openHomeDialog(aURL)
  1656. {
  1657.   var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService);
  1658.   var promptTitle = gNavigatorBundle.getString("droponhometitle");
  1659.   var promptMsg   = gNavigatorBundle.getString("droponhomemsg");
  1660.   var okButton    = gNavigatorBundle.getString("droponhomeokbutton");
  1661.   var pressedVal  = promptService.confirmEx(window, promptTitle, promptMsg,
  1662.                           (promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0) +
  1663.                           (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1),
  1664.                           okButton, null, null, null, {value:0});
  1665.  
  1666.   if (pressedVal == 0) {
  1667.     try {
  1668.       var str = Components.classes["@mozilla.org/supports-string;1"]
  1669.                           .createInstance(Components.interfaces.nsISupportsString);
  1670.       str.data = aURL;
  1671.       gPrefService.setComplexValue("browser.startup.homepage",
  1672.                                    Components.interfaces.nsISupportsString, str);
  1673.       var homeButton = document.getElementById("home-button");
  1674.       homeButton.setAttribute("tooltiptext", aURL);
  1675.     } catch (ex) {
  1676.       dump("Failed to set the home page.\n"+ex+"\n");
  1677.     }
  1678.   }
  1679. }
  1680.  
  1681. var goButtonObserver = {
  1682.   onDragOver: function(aEvent, aFlavour, aDragSession)
  1683.     {
  1684.       aEvent.target.setAttribute("dragover", "true");
  1685.       return true;
  1686.     },
  1687.   onDragExit: function (aEvent, aDragSession)
  1688.     {
  1689.       aEvent.target.removeAttribute("dragover");
  1690.     },
  1691.   onDrop: function (aEvent, aXferData, aDragSession)
  1692.     {
  1693.       var xferData = aXferData.data.split("\n");
  1694.       var uri = xferData[0] ? xferData[0] : xferData[1];
  1695.       if (uri)
  1696.         loadURI(uri);
  1697.     },
  1698.   getSupportedFlavours: function ()
  1699.     {
  1700.       var flavourSet = new FlavourSet();
  1701.       flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  1702.       flavourSet.appendFlavour("text/x-moz-url");
  1703.       flavourSet.appendFlavour("text/unicode");
  1704.       return flavourSet;
  1705.     }
  1706. }
  1707.  
  1708. function ensureDefaultEnginePrefs(aRDF,aDS) 
  1709. {
  1710.   var mPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
  1711.   var defaultName = mPrefs.getComplexValue("browser.search.defaultenginename", Components.interfaces.nsIPrefLocalizedString).data;
  1712.   var kNC_Root = aRDF.GetResource("NC:SearchEngineRoot");
  1713.   var kNC_child = aRDF.GetResource("http://home.netscape.com/NC-rdf#child");
  1714.   var kNC_Name = aRDF.GetResource("http://home.netscape.com/NC-rdf#Name");
  1715.           
  1716.   var arcs = aDS.GetTargets(kNC_Root, kNC_child, true);
  1717.   while (arcs.hasMoreElements()) {
  1718.     var engineRes = arcs.getNext().QueryInterface(Components.interfaces.nsIRDFResource);       
  1719.     var name = readRDFString(aDS, engineRes, kNC_Name);
  1720.     if (name == defaultName)
  1721.       mPrefs.setCharPref("browser.search.defaultengine", engineRes.Value);
  1722.   }
  1723. }
  1724.  
  1725. function readRDFString(aDS,aRes,aProp)
  1726. {
  1727.   var n = aDS.GetTarget(aRes, aProp, true);
  1728.   return n ? n.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : "";
  1729. }
  1730.  
  1731. function ensureSearchPref()
  1732. {
  1733.   var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService);
  1734.   var ds = rdf.GetDataSource("rdf:internetsearch");
  1735.   var mPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch);
  1736.   var kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name");
  1737.   var defaultEngine;
  1738.   try {
  1739.     defaultEngine = mPrefs.getCharPref("browser.search.defaultengine");
  1740.   } catch(ex) {
  1741.     ensureDefaultEnginePrefs(rdf, ds);
  1742.     defaultEngine = mPrefs.getCharPref("browser.search.defaultengine");
  1743.   }
  1744. }
  1745.  
  1746. function OpenSearch(tabName, searchStr, newWindowFlag)
  1747. {
  1748.   //This function needs to be split up someday.
  1749.  
  1750.   var defaultSearchURL = null;
  1751.   var navigatorRegionBundle = document.getElementById("bundle_browser_region");
  1752.   var fallbackDefaultSearchURL = navigatorRegionBundle.getString("fallbackDefaultSearchURL");
  1753.   ensureSearchPref()
  1754.   //Check to see if search string contains "://" or "ftp." or white space.
  1755.   //If it does treat as url and match for pattern
  1756.   
  1757.   var urlmatch= /(:\/\/|^ftp\.)[^ \S]+$/ 
  1758.   var forceAsURL = urlmatch.test(searchStr);
  1759.  
  1760.   try {
  1761.     defaultSearchURL = gPrefService.getComplexValue("browser.search.defaulturl",
  1762.                                             Components.interfaces.nsIPrefLocalizedString).data;
  1763.   } catch (ex) {
  1764.   }
  1765.  
  1766.   // Fallback to a default url (one that we can get sidebar search results for)
  1767.   if (!defaultSearchURL)
  1768.     defaultSearchURL = fallbackDefaultSearchURL;
  1769.  
  1770.   if (!searchStr) {
  1771.     BrowserSearchInternet();
  1772.   } else {
  1773.  
  1774.     //Check to see if location bar field is a url
  1775.     //If it is a url go to URL.  A Url is "://" or "." as commented above
  1776.     //Otherwise search on entry
  1777.     if (forceAsURL) {
  1778.        BrowserLoadURL()
  1779.     } else {
  1780.       if (searchStr) {
  1781.         var escapedSearchStr = escape(searchStr);
  1782.         defaultSearchURL += escapedSearchStr;
  1783.         var searchDS = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"]
  1784.                                  .getService(Components.interfaces.nsIInternetSearchService);
  1785.  
  1786.         searchDS.RememberLastSearchText(escapedSearchStr);
  1787.         try {
  1788.           var searchEngineURI = gPrefService.getCharPref("browser.search.defaultengine");
  1789.           if (searchEngineURI) {          
  1790.             var searchURL = getSearchUrl("actionButton");
  1791.             if (searchURL) {
  1792.               defaultSearchURL = searchURL + escapedSearchStr; 
  1793.             } else {
  1794.               searchURL = searchDS.GetInternetSearchURL(searchEngineURI, escapedSearchStr, 0, 0, {value:0});
  1795.               if (searchURL)
  1796.                 defaultSearchURL = searchURL;
  1797.             }
  1798.           }
  1799.         } catch (ex) {
  1800.         }
  1801.  
  1802.         if (!newWindowFlag)
  1803.           loadURI(defaultSearchURL);
  1804.         else
  1805.           window.open(defaultSearchURL, "_blank");
  1806.       }
  1807.     }
  1808.   }
  1809. }
  1810.  
  1811. var personalToolbarDNDObserver = {
  1812.  
  1813.   ////////////////////
  1814.   // Public methods //
  1815.   ////////////////////
  1816.  
  1817.   onDragStart: function (aEvent, aXferData, aDragAction)
  1818.     {
  1819.       var target = aEvent.originalTarget;
  1820.  
  1821.       // Prevent dragging from an invalid region
  1822.       if (!this.canDrop(aEvent))
  1823.         return;
  1824.  
  1825.       // Prevent dragging out of menupopups on non Win32 platforms. 
  1826.       // a) on Mac drag from menus is generally regarded as being satanic
  1827.       // b) on Linux, this causes an X-server crash, (bug 151336)
  1828.       // c) on Windows, there is no hang or crash associated with this, so we'll leave 
  1829.       // the functionality there. 
  1830.       if (navigator.platform != "Win32" && target.localName != "toolbarbutton")
  1831.         return;
  1832.  
  1833.       // bail if dragging from the empty area of the bookmarks toolbar
  1834.       if (target.localName == "hbox")
  1835.         return
  1836.  
  1837.       // a drag start is fired when leaving an open toolbarbutton(type=menu) 
  1838.       // (see bug 143031)
  1839.       if (this.isContainer(target) && 
  1840.           target.getAttribute("group") != "true") {
  1841.         if (this.isPlatformNotSupported) 
  1842.           return;
  1843.         if (!aEvent.shiftKey && !aEvent.altKey && !aEvent.ctrlKey)
  1844.           return;
  1845.         // menus open on mouse down
  1846.         target.firstChild.hidePopup();
  1847.       }
  1848.       var bt = document.getElementById("bookmarks-toolbar");
  1849.       var selection  = bt.getBTSelection(target);
  1850.       aXferData.data = BookmarksUtils.getXferDataFromSelection(selection);
  1851.     },
  1852.  
  1853.   onDragOver: function(aEvent, aFlavour, aDragSession) 
  1854.   {
  1855.     var bt = document.getElementById("bookmarks-toolbar");
  1856.     var orientation = bt.getBTOrientation(aEvent)
  1857.     if (aDragSession.canDrop)
  1858.       this.onDragSetFeedBack(aEvent.originalTarget, orientation);
  1859.     if (orientation != this.mCurrentDropPosition) {
  1860.       // emulating onDragExit and onDragEnter events since the drop region
  1861.       // has changed on the target.
  1862.       this.onDragExit(aEvent, aDragSession);
  1863.       this.onDragEnter(aEvent, aDragSession);
  1864.     }
  1865.     if (this.isPlatformNotSupported)
  1866.       return;
  1867.     if (this.isTimerSupported)
  1868.       return;
  1869.     this.onDragOverCheckTimers();
  1870.   },
  1871.  
  1872.   onDragEnter: function (aEvent, aDragSession)
  1873.   {
  1874.     var target = aEvent.originalTarget;
  1875.     var bt = document.getElementById("bookmarks-toolbar");
  1876.     var orientation = bt.getBTOrientation(aEvent);
  1877.     if (target.localName == "menupopup" || target.localName == "hbox")
  1878.       target = target.parentNode;
  1879.     if (aDragSession.canDrop) {
  1880.       this.onDragSetFeedBack(target, orientation);
  1881.       this.onDragEnterSetTimer(target, aDragSession);
  1882.     }
  1883.     this.mCurrentDragOverTarget = target;
  1884.     this.mCurrentDropPosition   = orientation;
  1885.   },
  1886.  
  1887.   onDragExit: function (aEvent, aDragSession)
  1888.   {
  1889.     var target = aEvent.originalTarget;
  1890.     if (target.localName == "menupopup" || target.localName == "hbox")
  1891.       target = target.parentNode;
  1892.     this.onDragRemoveFeedBack(target);
  1893.     this.onDragExitSetTimer(target, aDragSession);
  1894.     this.mCurrentDragOverTarget = null;
  1895.     this.mCurrentDropPosition = null;
  1896.   },
  1897.  
  1898.   onDrop: function (aEvent, aXferData, aDragSession)
  1899.   {
  1900.     var target = aEvent.originalTarget;
  1901.     this.onDragRemoveFeedBack(target);
  1902.  
  1903.     var bt        = document.getElementById("bookmarks-toolbar");
  1904.     var selection = BookmarksUtils.getSelectionFromXferData(aDragSession);
  1905.  
  1906.     // if the personal toolbar does not exist, recreate it
  1907.     if (target == "bookmarks-toolbar") {
  1908.       //BookmarksUtils.recreatePersonalToolbarFolder(transactionSet);
  1909.       //target = { parent: "NC:PersonalToolbarFolder", index: 1 };
  1910.     } else {
  1911.       var orientation = bt.getBTOrientation(aEvent);
  1912.       var selTarget   = bt.getBTTarget(target, orientation);
  1913.     }
  1914.  
  1915.     const kDSIID      = Components.interfaces.nsIDragService;
  1916.     const kCopyAction = kDSIID.DRAGDROP_ACTION_COPY + kDSIID.DRAGDROP_ACTION_LINK;
  1917.  
  1918.     // hide the 'open in tab' menuseparator because bookmarks
  1919.     // can be inserted after it if they are dropped after the last bookmark
  1920.     // a more comprehensive fix would be in the menupopup template builder
  1921.     var menuTarget = (target.localName == "toolbarbutton" ||
  1922.                       target.localName == "menu")         && 
  1923.                      orientation == BookmarksUtils.DROP_ON?
  1924.                      target.lastChild:target.parentNode;
  1925.     if (menuTarget.hasChildNodes() &&
  1926.         menuTarget.lastChild.id == "openintabs-menuitem") {
  1927.       menuTarget.removeChild(menuTarget.lastChild.previousSibling);
  1928.     }
  1929.  
  1930.     if (aDragSession.dragAction & kCopyAction)
  1931.       BookmarksUtils.insertSelection("drag", selection, selTarget, true);
  1932.     else
  1933.       BookmarksUtils.moveSelection("drag", selection, selTarget);
  1934.  
  1935.     // show again the menuseparator
  1936.     if (menuTarget.hasChildNodes() &&
  1937.         menuTarget.lastChild.id == "openintabs-menuitem") {
  1938.       var element = document.createElementNS(XUL_NS, "menuseparator");
  1939.       menuTarget.insertBefore(element, menuTarget.lastChild);
  1940.     }
  1941.  
  1942.   },
  1943.  
  1944.   canDrop: function (aEvent, aDragSession)
  1945.   {
  1946.     var target = aEvent.originalTarget;
  1947.     var bt = document.getElementById("bookmarks-toolbar");
  1948.     return bt.isBTBookmark(target.id)                  && 
  1949.            target.id != "NC:SystemBookmarksStaticRoot" &&
  1950.            target.id.substring(0,5) != "find:"         ||
  1951.            target.id == "bookmarks-menu"               ||
  1952.            target.getAttribute("class") == "chevron"   ||
  1953.            target.localName == "hbox";
  1954.   },
  1955.  
  1956.   canHandleMultipleItems: true,
  1957.  
  1958.   getSupportedFlavours: function () 
  1959.   {
  1960.     var flavourSet = new FlavourSet();
  1961.     flavourSet.appendFlavour("moz/rdfitem");
  1962.     flavourSet.appendFlavour("text/x-moz-url");
  1963.     flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  1964.     flavourSet.appendFlavour("text/unicode");
  1965.     return flavourSet;
  1966.   }, 
  1967.   
  1968.  
  1969.   ////////////////////////////////////
  1970.   // Private methods and properties //
  1971.   ////////////////////////////////////
  1972.  
  1973.   springLoadedMenuDelay: 350, // milliseconds
  1974.   isPlatformNotSupported: navigator.platform.indexOf("Mac") != -1, // see bug 136524
  1975.   isTimerSupported: navigator.platform.indexOf("Win") == -1,
  1976.  
  1977.   mCurrentDragOverTarget: null,
  1978.   mCurrentDropPosition: null,
  1979.   loadTimer  : null,
  1980.   closeTimer : null,
  1981.   loadTarget : null,
  1982.   closeTarget: null,
  1983.  
  1984.   _observers : null,
  1985.   get mObservers ()
  1986.   {
  1987.     if (!this._observers) {
  1988.       var bt = document.getElementById("bookmarks-toolbar");
  1989.       this._observers = [
  1990.         document.getAnonymousElementByAttribute(bt , "anonid", "bookmarks-ptf"),
  1991.         document.getElementById("bookmarks-menu").parentNode,
  1992.         document.getAnonymousElementByAttribute(bt , "class", "chevron").parentNode
  1993.       ]
  1994.     }
  1995.     return this._observers;
  1996.   },
  1997.  
  1998.   getObserverForNode: function (aNode)
  1999.   {
  2000.     if (!aNode)
  2001.       return null;
  2002.     var node = aNode;
  2003.     var observer;
  2004.     do {
  2005.       for (var i=0; i < this.mObservers.length; i++) {
  2006.         observer = this.mObservers[i];
  2007.         if (observer == node)
  2008.           return observer;
  2009.       }
  2010.       node = node.parentNode;
  2011.     } while (node != document)
  2012.     return null;
  2013.   },
  2014.  
  2015.   onDragCloseMenu: function (aNode)
  2016.   {
  2017.     var children = aNode.childNodes;
  2018.     for (var i = 0; i < children.length; i++) {
  2019.       if (this.isContainer(children[i]) && 
  2020.           children[i].getAttribute("open") == "true") {
  2021.         this.onDragCloseMenu(children[i].lastChild);
  2022.         if (children[i] != this.mCurrentDragOverTarget || this.mCurrentDropPosition != BookmarksUtils.DROP_ON)
  2023.           children[i].lastChild.hidePopup();
  2024.       }
  2025.     } 
  2026.   },
  2027.  
  2028.   onDragCloseTarget: function ()
  2029.   {
  2030.     var currentObserver = this.getObserverForNode(this.mCurrentDragOverTarget);
  2031.     // close all the menus not hovered by the mouse
  2032.     for (var i=0; i < this.mObservers.length; i++) {
  2033.       if (currentObserver != this.mObservers[i])
  2034.         this.onDragCloseMenu(this.mObservers[i]);
  2035.       else
  2036.         this.onDragCloseMenu(this.mCurrentDragOverTarget.parentNode);
  2037.     }
  2038.   },
  2039.  
  2040.   onDragLoadTarget: function (aTarget) 
  2041.   {
  2042.     if (!this.mCurrentDragOverTarget)
  2043.       return;
  2044.     // Load the current menu
  2045.     if (this.mCurrentDropPosition == BookmarksUtils.DROP_ON && 
  2046.         this.isContainer(aTarget)             && 
  2047.         aTarget.getAttribute("group") != "true")
  2048.       aTarget.lastChild.showPopup(aTarget);
  2049.   },
  2050.  
  2051.   onDragOverCheckTimers: function ()
  2052.   {
  2053.     var now = new Date().getTime();
  2054.     if (this.closeTimer && now-this.springLoadedMenuDelay>this.closeTimer) {
  2055.       this.onDragCloseTarget();
  2056.       this.closeTimer = null;
  2057.     }
  2058.     if (this.loadTimer && (now-this.springLoadedMenuDelay>this.loadTimer)) {
  2059.       this.onDragLoadTarget(this.loadTarget);
  2060.       this.loadTimer = null;
  2061.     }
  2062.   },
  2063.  
  2064.   onDragEnterSetTimer: function (aTarget, aDragSession)
  2065.   {
  2066.     if (this.isPlatformNotSupported)
  2067.       return;
  2068.     if (this.isTimerSupported) {
  2069.       var targetToBeLoaded = aTarget;
  2070.       clearTimeout(this.loadTimer);
  2071.       if (aTarget == aDragSession.sourceNode)
  2072.         return;
  2073.       //XXX Hack: see bug 139645
  2074.       var thisHack = this;
  2075.       this.loadTimer=setTimeout(function () {thisHack.onDragLoadTarget(targetToBeLoaded)}, this.springLoadedMenuDelay);
  2076.     } else {
  2077.       var now = new Date().getTime();
  2078.       this.loadTimer  = now;
  2079.       this.loadTarget = aTarget;
  2080.     }
  2081.   },
  2082.  
  2083.   onDragExitSetTimer: function (aTarget, aDragSession)
  2084.   {
  2085.     if (this.isPlatformNotSupported)
  2086.       return;
  2087.     var thisHack = this;
  2088.     if (this.isTimerSupported) {
  2089.       clearTimeout(this.closeTimer)
  2090.       this.closeTimer=setTimeout(function () {thisHack.onDragCloseTarget()}, this.springLoadedMenuDelay);
  2091.     } else {
  2092.       var now = new Date().getTime();
  2093.       this.closeTimer  = now;
  2094.       this.closeTarget = aTarget;
  2095.       this.loadTimer = null;
  2096.  
  2097.       // If user isn't rearranging within the menu, close it
  2098.       // To do so, we exploit a Mac bug: timeout set during
  2099.       // drag and drop on Windows and Mac are fired only after that the drop is released.
  2100.       // timeouts will pile up, we may have a better approach but for the moment, this one
  2101.       // correctly close the menus after a drop/cancel outside the personal toolbar.
  2102.       // The if statement in the function has been introduced to deal with rare but reproducible
  2103.       // missing Exit events.
  2104.       if (aDragSession.sourceNode.localName != "menuitem" && aDragSession.sourceNode.localName != "menu")
  2105.         setTimeout(function () { if (thisHack.mCurrentDragOverTarget) {thisHack.onDragRemoveFeedBack(thisHack.mCurrentDragOverTarget); thisHack.mCurrentDragOverTarget=null} thisHack.loadTimer=null; thisHack.onDragCloseTarget() }, 0);
  2106.     }
  2107.   },
  2108.  
  2109.   onDragSetFeedBack: function (aTarget, aOrientation)
  2110.   {
  2111.    switch (aTarget.localName) {
  2112.       case "toolbarseparator":
  2113.       case "toolbarbutton":
  2114.         switch (aOrientation) {
  2115.           case BookmarksUtils.DROP_BEFORE: 
  2116.             aTarget.setAttribute("dragover-left", "true");
  2117.             break;
  2118.           case BookmarksUtils.DROP_AFTER:
  2119.             aTarget.setAttribute("dragover-right", "true");
  2120.             break;
  2121.           case BookmarksUtils.DROP_ON:
  2122.             aTarget.setAttribute("dragover-top"   , "true");
  2123.             aTarget.setAttribute("dragover-bottom", "true");
  2124.             aTarget.setAttribute("dragover-left"  , "true");
  2125.             aTarget.setAttribute("dragover-right" , "true");
  2126.             break;
  2127.         }
  2128.         break;
  2129.       case "menuseparator": 
  2130.       case "menu":
  2131.       case "menuitem":
  2132.         switch (aOrientation) {
  2133.           case BookmarksUtils.DROP_BEFORE: 
  2134.             aTarget.setAttribute("dragover-top", "true");
  2135.             break;
  2136.           case BookmarksUtils.DROP_AFTER:
  2137.             aTarget.setAttribute("dragover-bottom", "true");
  2138.             break;
  2139.           case BookmarksUtils.DROP_ON:
  2140.             break;
  2141.         }
  2142.         break;
  2143.       case "hbox"     : 
  2144.         // hit between the last visible bookmark and the chevron
  2145.         var bt = document.getElementById("bookmarks-toolbar");
  2146.         var newTarget = bt.getLastVisibleBookmark();
  2147.         if (newTarget)
  2148.           newTarget.setAttribute("dragover-right", "true");
  2149.         break;
  2150.       case "stack"    :
  2151.       case "menupopup": break; 
  2152.      default: dump("No feedback for: "+aTarget.localName+"\n");
  2153.     }
  2154.   },
  2155.  
  2156.   onDragRemoveFeedBack: function (aTarget)
  2157.   { 
  2158.     var newTarget;
  2159.     var bt;
  2160.     if (aTarget.localName == "hbox") { 
  2161.       // hit when dropping in the bt or between the last visible bookmark 
  2162.       // and the chevron
  2163.       bt = document.getElementById("bookmarks-toolbar");
  2164.       newTarget = bt.getLastVisibleBookmark();
  2165.       if (newTarget)
  2166.         newTarget.removeAttribute("dragover-right");
  2167.     } else if (aTarget.localName == "stack") {
  2168.       bt = document.getElementById("bookmarks-toolbar");
  2169.       newTarget = bt.getLastVisibleBookmark();
  2170.       newTarget.removeAttribute("dragover-right");
  2171.     } else {
  2172.       aTarget.removeAttribute("dragover-left");
  2173.       aTarget.removeAttribute("dragover-right");
  2174.       aTarget.removeAttribute("dragover-top");
  2175.       aTarget.removeAttribute("dragover-bottom");
  2176.     }
  2177.   },
  2178.  
  2179.   onDropSetFeedBack: function (aTarget)
  2180.   {
  2181.     //XXX Not yet...
  2182.   },
  2183.  
  2184.   isContainer: function (aTarget)
  2185.   {
  2186.     return aTarget.localName == "menu"          || 
  2187.            aTarget.localName == "toolbarbutton" &&
  2188.            aTarget.getAttribute("type") == "menu";
  2189.   }
  2190. }
  2191.  
  2192. function FillHistoryMenu(aParent, aMenu)
  2193.   {
  2194.     // Remove old entries if any
  2195.     deleteHistoryItems(aParent);
  2196.  
  2197.     var sessionHistory = getWebNavigation().sessionHistory;
  2198.  
  2199.     var count = sessionHistory.count;
  2200.     var index = sessionHistory.index;
  2201.     var end;
  2202.     var j;
  2203.     var entry;
  2204.  
  2205.     switch (aMenu)
  2206.       {
  2207.         case "back":
  2208.           end = (index > MAX_HISTORY_MENU_ITEMS) ? index - MAX_HISTORY_MENU_ITEMS : 0;
  2209.           if ((index - 1) < end) return false;
  2210.           for (j = index - 1; j >= end; j--)
  2211.             {
  2212.               entry = sessionHistory.getEntryAtIndex(j, false);
  2213.               if (entry)
  2214.                 createMenuItem(aParent, j, entry.title);
  2215.             }
  2216.           break;
  2217.         case "forward":
  2218.           end  = ((count-index) > MAX_HISTORY_MENU_ITEMS) ? index + MAX_HISTORY_MENU_ITEMS : count;
  2219.           if ((index + 1) >= end) return false;
  2220.           for (j = index + 1; j < end; j++)
  2221.             {
  2222.               entry = sessionHistory.getEntryAtIndex(j, false);
  2223.               if (entry)
  2224.                 createMenuItem(aParent, j, entry.title);
  2225.             }
  2226.           break;
  2227.         case "go":
  2228.           aParent.lastChild.hidden = (count == 0);
  2229.           end = count > MAX_HISTORY_MENU_ITEMS ? count - MAX_HISTORY_MENU_ITEMS : 0;
  2230.           for (j = count - 1; j >= end; j--)
  2231.             {
  2232.               entry = sessionHistory.getEntryAtIndex(j, false);
  2233.               if (entry)
  2234.                 createRadioMenuItem(aParent, j, entry.title, j==index);
  2235.             }
  2236.           break;
  2237.       }
  2238.     return true;
  2239.   }
  2240.  
  2241. function addToUrlbarHistory()
  2242. {
  2243.   var urlToAdd = gURLBar.value;
  2244.   if (!urlToAdd)
  2245.      return;
  2246.   if (urlToAdd.search(/[\x00-\x1F]/) != -1) // don't store bad URLs
  2247.      return;
  2248.  
  2249.   if (!gGlobalHistory)
  2250.     gGlobalHistory = Components.classes["@mozilla.org/browser/global-history;1"]
  2251.                                .getService(Components.interfaces.nsIBrowserHistory);
  2252.   
  2253.   if (!gURIFixup)
  2254.     gURIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"]
  2255.                           .getService(Components.interfaces.nsIURIFixup);
  2256.    try {
  2257.      if (urlToAdd.indexOf(" ") == -1) {
  2258.        var fixedUpURI = gURIFixup.createFixupURI(urlToAdd, 0);
  2259.        gGlobalHistory.markPageAsTyped(fixedUpURI.spec);
  2260.      }
  2261.    }
  2262.    catch(ex) {
  2263.    }
  2264. }
  2265.  
  2266. function createMenuItem( aParent, aIndex, aLabel)
  2267.   {
  2268.     var menuitem = document.createElement( "menuitem" );
  2269.     menuitem.setAttribute( "label", aLabel );
  2270.     menuitem.setAttribute( "index", aIndex );
  2271.     aParent.appendChild( menuitem );
  2272.   }
  2273.  
  2274. function createRadioMenuItem( aParent, aIndex, aLabel, aChecked)
  2275.   {
  2276.     var menuitem = document.createElement( "menuitem" );
  2277.     menuitem.setAttribute( "type", "radio" );
  2278.     menuitem.setAttribute( "label", aLabel );
  2279.     menuitem.setAttribute( "index", aIndex );
  2280.     if (aChecked==true)
  2281.       menuitem.setAttribute( "checked", "true" );
  2282.     aParent.appendChild( menuitem );
  2283.   }
  2284.  
  2285. function deleteHistoryItems(aParent)
  2286. {
  2287.   var children = aParent.childNodes;
  2288.   for (var i = 0; i < children.length; i++)
  2289.     {
  2290.       var index = children[i].getAttribute("index");
  2291.       if (index)
  2292.         aParent.removeChild(children[i]);
  2293.     }
  2294. }
  2295.  
  2296. function toJavaScriptConsole()
  2297. {
  2298.   toOpenWindowByType("global:console", "chrome://browser/content/console/console.xul");
  2299. }
  2300.  
  2301. function toOpenWindowByType(inType, uri)
  2302. {
  2303.   var windowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService();
  2304.   var windowManagerInterface = windowManager.QueryInterface(Components.interfaces.nsIWindowMediator);
  2305.   var topWindow = windowManagerInterface.getMostRecentWindow(inType);
  2306.   
  2307.   if ( topWindow )
  2308.     topWindow.focus();
  2309.   else
  2310.     window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar");
  2311. }
  2312.  
  2313.  
  2314. function OpenBrowserWindow()
  2315. {
  2316.   var charsetArg = new String();
  2317.   var handler = Components.classes['@mozilla.org/commandlinehandler/general-startup;1?type=browser'];
  2318.   handler = handler.getService();
  2319.   handler = handler.QueryInterface(Components.interfaces.nsICmdLineHandler);
  2320.   var startpage = handler.defaultArgs;
  2321.   var url = handler.chromeUrlForTask;
  2322.   var wintype = document.firstChild.getAttribute('windowtype');
  2323.  
  2324.   // if and only if the current window is a browser window and it has a document with a character
  2325.   // set, then extract the current charset menu setting from the current document and use it to
  2326.   // initialize the new browser window...
  2327.   if (window && (wintype == "navigator:browser") && window._content && window._content.document)
  2328.   {
  2329.     var DocCharset = window._content.document.characterSet;
  2330.     charsetArg = "charset="+DocCharset;
  2331.  
  2332.     //we should "inherit" the charset menu setting in a new window
  2333.     window.openDialog(url, "_blank", "chrome,all,dialog=no", startpage, charsetArg);
  2334.   }
  2335.   else // forget about the charset information.
  2336.   {
  2337.     window.openDialog(url, "_blank", "chrome,all,dialog=no", startpage);
  2338.   }
  2339. }
  2340.  
  2341. function openAboutDialog()
  2342. {
  2343.   window.openDialog("chrome://browser/content/aboutDialog.xul", "About", "modal,centerscreen,chrome,resizable=no");
  2344. }
  2345.  
  2346. function BrowserCustomizeToolbar()
  2347. {
  2348.   // Disable the toolbar context menu items
  2349.   var menubar = document.getElementById("main-menubar");
  2350.   for (var i = 0; i < menubar.childNodes.length; ++i)
  2351.     menubar.childNodes[i].setAttribute("disabled", true);
  2352.     
  2353.   var cmd = document.getElementById("cmd_CustomizeToolbars");
  2354.   cmd.setAttribute("disabled", "true");
  2355.   
  2356.   window.openDialog("chrome://global/content/customizeToolbar.xul", "CustomizeToolbar",
  2357.                     "chrome,all,dependent", document.getElementById("navigator-toolbox"));
  2358. }
  2359.  
  2360. function BrowserToolboxCustomizeDone(aToolboxChanged)
  2361. {
  2362.   // Update global UI elements that may have been added or removed
  2363.   if (aToolboxChanged) {
  2364.     gURLBar = document.getElementById("urlbar");
  2365.     gProxyButton = document.getElementById("page-proxy-button");
  2366.     gProxyFavIcon = document.getElementById("page-proxy-favicon");
  2367.     gProxyDeck = document.getElementById("page-proxy-deck");
  2368.     updateHomeTooltip();
  2369.     window.XULBrowserWindow.init();
  2370.   }
  2371.  
  2372.   // Update the urlbar
  2373.   var url = getWebNavigation().currentURI.spec;
  2374.   if (gURLBar) {
  2375.     gURLBar.value = url;
  2376.     var uri = Components.classes["@mozilla.org/network/standard-url;1"]
  2377.                         .createInstance(Components.interfaces.nsIURI);
  2378.     uri.spec = url;
  2379.     SetPageProxyState("valid", uri);
  2380.   }
  2381.  
  2382.   // Re-enable parts of the UI we disabled during the dialog
  2383.   var menubar = document.getElementById("main-menubar");
  2384.   for (var i = 0; i < menubar.childNodes.length; ++i)
  2385.     menubar.childNodes[i].setAttribute("disabled", false);
  2386.   var cmd = document.getElementById("cmd_CustomizeToolbars");
  2387.   cmd.removeAttribute("disabled");
  2388.  
  2389.   // XXX Shouldn't have to do this, but I do
  2390.   window.focus();
  2391. }
  2392.  
  2393. var FullScreen = 
  2394. {
  2395.   toggle: function()
  2396.   {
  2397.     // show/hide all menubars, toolbars, and statusbars (except the full screen toolbar)
  2398.     this.showXULChrome("menubar", window.fullScreen);
  2399.     this.showXULChrome("toolbar", window.fullScreen);
  2400.     this.showXULChrome("statusbar", window.fullScreen);
  2401.   },
  2402.   
  2403.   showXULChrome: function(aTag, aShow)
  2404.   {
  2405.     var XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  2406.     var els = document.getElementsByTagNameNS(XULNS, aTag);
  2407.     
  2408.     var i;
  2409.     for (i = 0; i < els.length; ++i) {
  2410.       // XXX don't interfere with previously collapsed toolbars
  2411.       if (els[i].getAttribute("fullscreentoolbar") == "true") {
  2412.         if (!aShow) {
  2413.           gToolbarMode = els[i].getAttribute("mode");
  2414.           gIconSize = els[i].getAttribute("iconsize");
  2415.           els[i].setAttribute("mode", "icons");
  2416.           els[i].setAttribute("iconsize", "small");
  2417.         }
  2418.         else {
  2419.           els[i].setAttribute("mode", gToolbarMode);
  2420.           els[i].setAttribute("iconsize", gIconSize);
  2421.         }
  2422.       } else {
  2423.         // use moz-collapsed so it doesn't persist hidden/collapsed,
  2424.         // so that new windows don't have missing toolbars
  2425.         if (aShow)
  2426.           els[i].removeAttribute("moz-collapsed");
  2427.         else
  2428.           els[i].setAttribute("moz-collapsed", "true");
  2429.       }
  2430.     }
  2431.     
  2432.     var controls = document.getElementsByAttribute("fullscreencontrol", "true");
  2433.     for (i = 0; i < controls.length; ++i)
  2434.       controls[i].hidden = aShow;
  2435.   }
  2436. };
  2437.  
  2438. function nsBrowserStatusHandler()
  2439. {
  2440.   this.init();
  2441. }
  2442.  
  2443. nsBrowserStatusHandler.prototype =
  2444. {
  2445.   userTyped :
  2446.   {
  2447.     _value : false,
  2448.     browser : null,
  2449.  
  2450.     get value() {
  2451.       if (this.browser != gBrowser.mCurrentBrowser)
  2452.         this._value = false;
  2453.       
  2454.       return this._value;
  2455.     },
  2456.  
  2457.     set value(aValue) {
  2458.       if (this._value != aValue) {
  2459.         this._value = aValue;
  2460.         this.browser = aValue ? gBrowser.mCurrentBrowser : null;
  2461.       }
  2462.  
  2463.       return aValue;
  2464.     }
  2465.   },
  2466.  
  2467.   // Stored Status, Link and Loading values
  2468.   status : "",
  2469.   defaultStatus : "",
  2470.   jsStatus : "",
  2471.   jsDefaultStatus : "",
  2472.   overLink : "",
  2473.   startTime : 0,
  2474.   statusText: "",
  2475.  
  2476.   statusTimeoutInEffect : false,
  2477.  
  2478.   hideAboutBlank : true,
  2479.  
  2480.   QueryInterface : function(aIID)
  2481.   {
  2482.     if (aIID.equals(Components.interfaces.nsIWebProgressListener) ||
  2483.         aIID.equals(Components.interfaces.nsISupportsWeakReference) ||
  2484.         aIID.equals(Components.interfaces.nsIXULBrowserWindow) ||
  2485.         aIID.equals(Components.interfaces.nsISupports))
  2486.       return this;
  2487.     throw Components.results.NS_NOINTERFACE;
  2488.   },
  2489.  
  2490.   init : function()
  2491.   {
  2492.     this.throbberElement = document.getElementById("navigator-throbber");
  2493.     this.statusMeter     = document.getElementById("statusbar-icon");
  2494.     this.stopCommand     = document.getElementById("Browser:Stop");
  2495.     this.statusTextField = document.getElementById("statusbar-display");
  2496.     this.securityButton  = document.getElementById("security-button");
  2497.  
  2498.     // Initialize the security button's state and tooltip text
  2499.     const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  2500.     this.onSecurityChange(null, null, nsIWebProgressListener.STATE_IS_INSECURE);
  2501.   },
  2502.  
  2503.   destroy : function()
  2504.   {
  2505.     // XXXjag to avoid leaks :-/, see bug 60729
  2506.     this.throbberElement = null;
  2507.     this.statusMeter     = null;
  2508.     this.stopCommand     = null;
  2509.     this.statusTextField = null;
  2510.     this.securityButton  = null;
  2511.     this.userTyped       = null;
  2512.     this.statusText      = null;
  2513.   },
  2514.  
  2515.   setJSStatus : function(status)
  2516.   {
  2517.     this.jsStatus = status;
  2518.     this.updateStatusField();
  2519.   },
  2520.  
  2521.   setJSDefaultStatus : function(status)
  2522.   {
  2523.     this.jsDefaultStatus = status;
  2524.     this.updateStatusField();
  2525.   },
  2526.  
  2527.   setDefaultStatus : function(status)
  2528.   {
  2529.     this.defaultStatus = status;
  2530.     this.updateStatusField();
  2531.   },
  2532.  
  2533.   setOverLink : function(link, b)
  2534.   {
  2535.     this.overLink = link;
  2536.     this.updateStatusField();
  2537.   },
  2538.  
  2539.   updateStatusField : function()
  2540.   {
  2541.     var text = this.overLink || this.status || this.jsStatus || this.jsDefaultStatus || this.defaultStatus;
  2542.  
  2543.     // check the current value so we don't trigger an attribute change
  2544.     // and cause needless (slow!) UI updates
  2545.     if (this.statusText != text) {
  2546.       this.statusTextField.label = text;
  2547.       this.statusText = text;
  2548.     }
  2549.   },
  2550.  
  2551.   onLinkIconAvailable : function(aHref) {
  2552.     if (gProxyFavIcon) {
  2553.       
  2554.       // XXXBlake gPrefService.getBoolPref("browser.chrome.site_icons"))
  2555.       gProxyFavIcon.setAttribute("src", aHref);
  2556.     }
  2557.   },
  2558.  
  2559.   onProgressChange : function (aWebProgress, aRequest,
  2560.                                aCurSelfProgress, aMaxSelfProgress,
  2561.                                aCurTotalProgress, aMaxTotalProgress)
  2562.   {
  2563.     if (aMaxTotalProgress > 0) {
  2564.       // This is highly optimized.  Don't touch this code unless
  2565.       // you are intimately familiar with the cost of setting
  2566.       // attrs on XUL elements. -- hyatt
  2567.       var percentage = (aCurTotalProgress * 100) / aMaxTotalProgress;
  2568.       this.statusMeter.value = percentage;
  2569.     } 
  2570.   },
  2571.  
  2572.   onStateChange : function(aWebProgress, aRequest, aStateFlags, aStatus)
  2573.   {  
  2574.     const nsIWebProgressListener = Components.interfaces.nsIWebProgressListener;
  2575.     const nsIChannel = Components.interfaces.nsIChannel;
  2576.     if (aStateFlags & nsIWebProgressListener.STATE_START) {
  2577.         // This (thanks to the filter) is a network start or the first
  2578.         // stray request (the first request outside of the document load),
  2579.         // initialize the throbber and his friends.
  2580.         
  2581.         // Call start document load listeners (only if this is a network load)
  2582.         if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK &&
  2583.             aRequest && aWebProgress.DOMWindow == content)
  2584.           this.startDocumentLoad(aRequest);
  2585.   
  2586.         if (this.throbberElement) {          
  2587.           // Turn the throbber on.
  2588.           this.throbberElement.setAttribute("busy", "true");
  2589.         }
  2590.  
  2591.         // Turn the status meter on.
  2592.         this.statusMeter.value = 0;  // be sure to clear the progress bar
  2593.         if (gProgressCollapseTimer) {
  2594.           window.clearTimeout(gProgressCollapseTimer);
  2595.           gProgressCollapseTimer = null;
  2596.         }
  2597.         else
  2598.           this.statusMeter.parentNode.collapsed = false;
  2599.  
  2600.         // XXX: This needs to be based on window activity...
  2601.         this.stopCommand.removeAttribute("disabled");
  2602.     }
  2603.     else if (aStateFlags & nsIWebProgressListener.STATE_STOP) {
  2604.       if (aStateFlags & nsIWebProgressListener.STATE_IS_NETWORK) {
  2605.         if (aRequest) {
  2606.           if (aWebProgress.DOMWindow == content)
  2607.             this.endDocumentLoad(aRequest, aStatus);
  2608.         }
  2609.       }
  2610.  
  2611.       // This (thanks to the filter) is a network stop or the last
  2612.       // request stop outside of loading the document, stop throbbers
  2613.       // and progress bars and such
  2614.       if (aRequest) {
  2615.         var msg = "";
  2616.         // Get the channel if the request is a channel
  2617.         var channel;
  2618.         try {
  2619.           channel = aRequest.QueryInterface(nsIChannel);
  2620.         }
  2621.         catch(e) { };
  2622.           if (channel) {
  2623.             var location = channel.URI.spec;
  2624.             if (location != "about:blank") {
  2625.               const kErrorBindingAborted = 2152398850;
  2626.               const kErrorNetTimeout = 2152398862;
  2627.               switch (aStatus) {
  2628.                 case kErrorBindingAborted:
  2629.                   msg = gNavigatorBundle.getString("nv_stopped");
  2630.                   break;
  2631.                 case kErrorNetTimeout:
  2632.                   msg = gNavigatorBundle.getString("nv_timeout");
  2633.                   break;
  2634.               }
  2635.             }
  2636.           }
  2637.           // If msg is false then we did not have an error (channel may have
  2638.           // been null, in the case of a stray image load).
  2639.           if (!msg) {
  2640.             msg = gNavigatorBundle.getString("nv_done");
  2641.           }
  2642.           this.status = "";
  2643.           this.setDefaultStatus(msg);
  2644.         }
  2645.  
  2646.         // Turn the progress meter and throbber off.
  2647.         gProgressCollapseTimer = window.setTimeout("gProgressMeterPanel.collapsed = true; gProgressCollapseTimer = null;",
  2648.                                                    100);
  2649.  
  2650.         if (this.throbberElement)
  2651.           this.throbberElement.removeAttribute("busy");
  2652.  
  2653.         this.stopCommand.setAttribute("disabled", "true");
  2654.     }
  2655.   },
  2656.  
  2657.   onLocationChange : function(aWebProgress, aRequest, aLocation)
  2658.   {
  2659.     this.setOverLink("", null);
  2660.  
  2661.     var location = aLocation.spec;
  2662.  
  2663.     if (this.hideAboutBlank) {
  2664.       this.hideAboutBlank = false;
  2665.       if (location == "about:blank")
  2666.         location = "";
  2667.     }
  2668.  
  2669.     // We should probably not do this if the value has changed since the user
  2670.     // searched
  2671.     // Update urlbar only if a new page was loaded on the primary content area
  2672.     // Do not update urlbar if there was a subframe navigation
  2673.  
  2674.     if (aWebProgress.DOMWindow == content) {
  2675.       //XXXBlake don't we have to reinit this.urlBar, etc.
  2676.       //         when the toolbar changes?
  2677.       if (gURLBar && !this.userTyped.value) {
  2678.         // If the url has "wyciwyg://" as the protocol, strip it off.
  2679.         // Nobody wants to see it on the urlbar for dynamically generated
  2680.         // pages. 
  2681.         if (/^\s*wyciwyg:\/\/\d+\//.test(location))
  2682.           location = RegExp.rightContext;
  2683.         setTimeout(function(loc, aloc) { gURLBar.value = loc; SetPageProxyState("valid", aloc);}, 0, location, aLocation);
  2684.         // the above causes userTyped.value to become true, reset it
  2685.         this.userTyped.value = false;
  2686.       }
  2687.     }
  2688.     UpdateBackForwardButtons();
  2689.   },
  2690.  
  2691.   onStatusChange : function(aWebProgress, aRequest, aStatus, aMessage)
  2692.   {
  2693.     this.status = aMessage;
  2694.     this.updateStatusField();
  2695.   },
  2696.  
  2697.   onSecurityChange : function(aWebProgress, aRequest, aState)
  2698.   {
  2699.     const wpl = Components.interfaces.nsIWebProgressListener;
  2700.  
  2701.     switch (aState) {
  2702.       case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_HIGH:
  2703.         this.securityButton.setAttribute("level", "high");
  2704.         break;
  2705.       case wpl.STATE_IS_SECURE | wpl.STATE_SECURE_LOW:
  2706.         this.securityButton.setAttribute("level", "low");
  2707.         break;
  2708.       case wpl.STATE_IS_BROKEN:
  2709.         this.securityButton.setAttribute("level", "broken");
  2710.         break;
  2711.       case wpl.STATE_IS_INSECURE:
  2712.       default:
  2713.         this.securityButton.removeAttribute("level");
  2714.         break;
  2715.     }
  2716.  
  2717.     var securityUI = gBrowser.securityUI;
  2718.     if (securityUI)
  2719.       this.securityButton.setAttribute("tooltiptext", securityUI.tooltipText);
  2720.     else
  2721.       this.securityButton.removeAttribute("tooltiptext");
  2722.   },
  2723.  
  2724.   startDocumentLoad : function(aRequest)
  2725.   {
  2726.     // Reset so we can see if the user typed after the document load
  2727.     // starting and the location changing.
  2728.     this.userTyped.value = false;
  2729.  
  2730.     const nsIChannel = Components.interfaces.nsIChannel;
  2731.     var urlStr = aRequest.QueryInterface(nsIChannel).URI.spec;
  2732.     var observerService = Components.classes["@mozilla.org/observer-service;1"]
  2733.                                     .getService(Components.interfaces.nsIObserverService);
  2734.     try {
  2735.       observerService.notifyObservers(_content, "StartDocumentLoad", urlStr);
  2736.     } catch (e) {
  2737.     }
  2738.   },
  2739.  
  2740.   endDocumentLoad : function(aRequest, aStatus)
  2741.   {
  2742.     const nsIChannel = Components.interfaces.nsIChannel;
  2743.     var urlStr = aRequest.QueryInterface(nsIChannel).originalURI.spec;
  2744.  
  2745.     var observerService = Components.classes["@mozilla.org/observer-service;1"]
  2746.                                     .getService(Components.interfaces.nsIObserverService);
  2747.  
  2748.     var notification = Components.isSuccessCode(aStatus) ? "EndDocumentLoad" : "FailDocumentLoad";
  2749.     try {
  2750.       observerService.notifyObservers(_content, notification, urlStr);
  2751.     } catch (e) {
  2752.     }
  2753.   }
  2754. }
  2755.  
  2756. function onViewToolbarsPopupShowing(aEvent)
  2757. {
  2758.   var popup = aEvent.target;
  2759.   var i;
  2760.  
  2761.   // Empty the menu
  2762.   for (i = popup.childNodes.length-1; i >= 0; --i) {
  2763.     var deadItem = popup.childNodes[i];
  2764.     if (deadItem.hasAttribute("toolbarindex"))
  2765.       popup.removeChild(deadItem);
  2766.   }
  2767.   
  2768.   var firstMenuItem = popup.firstChild;
  2769.   
  2770.   var toolbox = document.getElementById("navigator-toolbox");
  2771.   for (i = 0; i < toolbox.childNodes.length; ++i) {
  2772.     var toolbar = toolbox.childNodes[i];
  2773.     var toolbarName = toolbar.getAttribute("toolbarname");
  2774.     var type = toolbar.getAttribute("type");
  2775.     if (toolbarName && type != "menubar") {
  2776.       var menuItem = document.createElement("menuitem");
  2777.       menuItem.setAttribute("toolbarindex", i);
  2778.       menuItem.setAttribute("type", "checkbox");
  2779.       menuItem.setAttribute("label", toolbarName);
  2780.       menuItem.setAttribute("accesskey", toolbar.getAttribute("accesskey"));
  2781.       menuItem.setAttribute("checked", toolbar.getAttribute("collapsed") != "true");
  2782.       popup.insertBefore(menuItem, firstMenuItem);        
  2783.       
  2784.       menuItem.addEventListener("command", onViewToolbarCommand, false);
  2785.     }
  2786.     toolbar = toolbar.nextSibling;
  2787.   }
  2788. }
  2789.  
  2790. function onViewToolbarCommand(aEvent)
  2791. {
  2792.   var toolbox = document.getElementById("navigator-toolbox");
  2793.   var index = aEvent.originalTarget.getAttribute("toolbarindex");
  2794.   var toolbar = toolbox.childNodes[index];
  2795.   
  2796.   toolbar.collapsed = aEvent.originalTarget.getAttribute("checked") != "true";
  2797.   document.persist(toolbar.id, "collapsed");
  2798. }
  2799.  
  2800. function displayPageInfo()
  2801. {
  2802.     window.openDialog("chrome://browser/content/pageInfo.xul", "_blank",
  2803.                       "dialog=no", null, "securityTab");
  2804. }
  2805.  
  2806. function displayPageReportFirstTime()
  2807. {
  2808.     window.openDialog("chrome://browser/content/pageReportFirstTime.xul", "_blank",
  2809.                       "modal");
  2810. }
  2811.  
  2812. function displayPageReport()
  2813. {
  2814.     window.openDialog("chrome://browser/content/pageReport.xul", "_blank",
  2815.                       "dialog=no,modal");
  2816. }
  2817.  
  2818. function nsBrowserContentListener(toplevelWindow, contentWindow)
  2819. {
  2820.     // this one is not as easy as you would hope.
  2821.     // need to convert toplevelWindow to an XPConnected object, instead
  2822.     // of a DOM-based object, to be able to QI() it to nsIXULWindow
  2823.     
  2824.     this.init(toplevelWindow, contentWindow);
  2825. }
  2826.  
  2827. /* implements nsIURIContentListener */
  2828.  
  2829. nsBrowserContentListener.prototype =
  2830. {
  2831.     init: function(toplevelWindow, contentWindow)
  2832.     {
  2833.         const nsIWebBrowserChrome = Components.interfaces.nsIWebBrowserChrome;
  2834.         this.toplevelWindow = toplevelWindow;
  2835.         this.contentWindow = contentWindow;
  2836.  
  2837.         // hook up the whole parent chain thing
  2838.         var windowDocShell = this.convertWindowToDocShell(toplevelWindow);
  2839.         if (windowDocShell)
  2840.             windowDocshell.parentURIContentListener = this;
  2841.     
  2842.         var registerWindow = false;
  2843.         try {          
  2844.           var treeItem = contentWindow.docShell.QueryInterface(Components.interfaces.nsIDocShellTreeItem);
  2845.           var treeOwner = treeItem.treeOwner;
  2846.           var interfaceRequestor = treeOwner.QueryInterface(Components.interfaces.nsIInterfaceRequestor);
  2847.           var webBrowserChrome = interfaceRequestor.getInterface(nsIWebBrowserChrome);
  2848.           if (webBrowserChrome)
  2849.           {
  2850.             var chromeFlags = webBrowserChrome.chromeFlags;
  2851.             var res = chromeFlags & nsIWebBrowserChrome.CHROME_ALL;
  2852.             var res2 = chromeFlags & nsIWebBrowserChrome.CHROME_DEFAULT;
  2853.             if ( res == nsIWebBrowserChrome.CHROME_ALL || res2 == nsIWebBrowserChrome.CHROME_DEFAULT)
  2854.             {             
  2855.               registerWindow = true;
  2856.             }
  2857.          }
  2858.        } catch (ex) {} 
  2859.  
  2860.         // register ourselves
  2861.        if (registerWindow)
  2862.        {
  2863.         var uriLoader = Components.classes["@mozilla.org/uriloader;1"].getService(Components.interfaces.nsIURILoader);
  2864.         uriLoader.registerContentListener(this);
  2865.        }
  2866.     },
  2867.     close: function()
  2868.     {
  2869.         this.contentWindow = null;
  2870.         var uriLoader = Components.classes["@mozilla.org/uriloader;1"].getService(Components.interfaces.nsIURILoader);
  2871.  
  2872.         uriLoader.unRegisterContentListener(this);
  2873.     },
  2874.     QueryInterface: function(iid)
  2875.     {
  2876.         if (iid.equals(Components.interfaces.nsIURIContentListener) ||
  2877.             iid.equals(Components.interfaces.nsISupportsWeakReference) ||
  2878.             iid.equals(Components.interfaces.nsISupports))
  2879.           return this;
  2880.         throw Components.results.NS_NOINTERFACE;
  2881.     },
  2882.     onStartURIOpen: function(uri)
  2883.     {
  2884.         // ignore and don't abort
  2885.         return false;
  2886.     },
  2887.  
  2888.     doContent: function(contentType, isContentPreferred, request, contentHandler)
  2889.     {
  2890.         // forward the doContent to our content area webshell
  2891.         var docShell = this.contentWindow.docShell;
  2892.         var contentListener;
  2893.         try {
  2894.             contentListener =
  2895.                 docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
  2896.                 .getInterface(Components.interfaces.nsIURIContentListener);
  2897.         } catch (ex) {
  2898.             dump(ex);
  2899.         }
  2900.         
  2901.         if (!contentListener) return false;
  2902.         
  2903.         return contentListener.doContent(contentType, isContentPreferred, request, contentHandler);
  2904.         
  2905.     },
  2906.  
  2907.     isPreferred: function(contentType, desiredContentType)
  2908.     {
  2909.         // seems like we should be getting this from helper apps or something
  2910.         switch(contentType) {
  2911.             case "text/html":
  2912.             case "text/xul":
  2913.             case "text/rdf":
  2914.             case "text/xml":
  2915.             case "text/css":
  2916.             case "image/gif":
  2917.             case "image/jpeg":
  2918.             case "image/png":
  2919.             case "text/plain":
  2920.             case "application/http-index-format":
  2921.                 return true;
  2922.         }
  2923.         return false;
  2924.     },
  2925.     canHandleContent: function(contentType, isContentPreferred, desiredContentType)
  2926.     {
  2927.         var docShell = this.contentWindow.docShell;
  2928.         var contentListener;
  2929.         try {
  2930.             contentListener =
  2931.                 docShell.QueryInterface(Components.interfaces.nsIInterfaceRequestor).getInterface(Components.interfaces.nsIURIContentListener);
  2932.         } catch (ex) {
  2933.             dump(ex);
  2934.         }
  2935.         if (!contentListener) return false;
  2936.         
  2937.         return contentListener.canHandleContent(contentType, isContentPreferred, desiredContentType);
  2938.     },
  2939.     convertWindowToDocShell: function(win) {
  2940.         // don't know how to do this
  2941.         return null;
  2942.     },
  2943.     loadCookie: null,
  2944.     parentContentListener: null
  2945. }
  2946.  
  2947. function toggleSidebar(aCommandID) {
  2948.   if (gInPrintPreviewMode)
  2949.     return;
  2950.   var sidebarBox = document.getElementById("sidebar-box");
  2951.   if (!aCommandID)
  2952.     aCommandID = sidebarBox.getAttribute("sidebarcommand");
  2953.  
  2954.   var elt = document.getElementById(aCommandID);
  2955.   var sidebar = document.getElementById("sidebar");
  2956.   var sidebarTitle = document.getElementById("sidebar-title");
  2957.   var sidebarSplitter = document.getElementById("sidebar-splitter");
  2958.  
  2959.   if (elt.getAttribute("checked") == "true") {
  2960.     elt.removeAttribute("checked");
  2961.     sidebarBox.setAttribute("sidebarcommand", "");
  2962.     sidebarTitle.setAttribute("value", "");
  2963.     sidebarBox.hidden = true;
  2964.     sidebarSplitter.hidden = true;
  2965.     return;
  2966.   }
  2967.   
  2968.   var elts = document.getElementsByAttribute("group", "sidebar");
  2969.   for (var i = 0; i < elts.length; ++i)
  2970.     elts[i].removeAttribute("checked");
  2971.  
  2972.   elt.setAttribute("checked", "true");;
  2973.  
  2974.   if (sidebarBox.hidden) {
  2975.     sidebarBox.hidden = false;
  2976.     sidebarSplitter.hidden = false;
  2977.   }
  2978.   
  2979.   var url = elt.getAttribute("sidebarurl");
  2980.   var title = elt.getAttribute("sidebartitle");
  2981.   if (!title)
  2982.     title = elt.getAttribute("label");
  2983.   sidebar.setAttribute("src", url);
  2984.   sidebarBox.setAttribute("src", url);
  2985.   sidebarBox.setAttribute("sidebarcommand", elt.id);
  2986.   sidebarTitle.setAttribute("value", title);
  2987. }
  2988.  
  2989. function goPreferences(containerID, paneURL, itemID)
  2990. {
  2991.   //check for an existing pref window and focus it; it's not application modal
  2992.   const kWindowMediatorContractID = "@mozilla.org/appshell/window-mediator;1";
  2993.   const kWindowMediatorIID = Components.interfaces.nsIWindowMediator;
  2994.   const kWindowMediator = Components.classes[kWindowMediatorContractID].getService(kWindowMediatorIID);
  2995.   var lastPrefWindow = kWindowMediator.getMostRecentWindow("mozilla:preferences");
  2996.   if (lastPrefWindow)
  2997.     lastPrefWindow.focus();
  2998.   else {
  2999.     var features = "chrome,titlebar,resizable";
  3000.     openDialog("chrome://browser/content/pref/pref.xul","PrefWindow", 
  3001.                features, paneURL, containerID, itemID);
  3002.   }
  3003. }
  3004.  
  3005. function updateHomeTooltip()
  3006. {
  3007.   var homeButton = document.getElementById("home-button");
  3008.   if (homeButton) {
  3009.     var homePage = getHomePage();
  3010.     homeButton.setAttribute("tooltiptext", homePage);
  3011.   }
  3012. }
  3013.  
  3014. function focusSearchBar()
  3015. {
  3016.   var searchBar = document.getElementById("search-bar");
  3017.   if (searchBar) {
  3018.     searchBar.select();
  3019.     searchBar.focus();
  3020.   }
  3021. }
  3022.  
  3023. const IMAGEPERMISSION = 1;
  3024. function nsContextMenu( xulMenu ) {
  3025.     this.target         = null;
  3026.     this.menu           = null;
  3027.     this.onTextInput    = false;
  3028.     this.onImage        = false;
  3029.     this.onLink         = false;
  3030.     this.onMailtoLink   = false;
  3031.     this.onSaveableLink = false;
  3032.     this.onMetaDataItem = false;
  3033.     this.onMathML       = false;
  3034.     this.link           = false;
  3035.     this.inFrame        = false;
  3036.     this.hasBGImage     = false;
  3037.     this.isTextSelected = false;
  3038.     this.inDirList      = false;
  3039.     this.shouldDisplay  = true;
  3040.  
  3041.     // Initialize new menu.
  3042.     this.initMenu( xulMenu );
  3043. }
  3044.  
  3045. // Prototype for nsContextMenu "class."
  3046. nsContextMenu.prototype = {
  3047.     // onDestroy is a no-op at this point.
  3048.     onDestroy : function () {
  3049.     },
  3050.     // Initialize context menu.
  3051.     initMenu : function ( popup ) {
  3052.         // Save menu.
  3053.         this.menu = popup;
  3054.  
  3055.         // Get contextual info.
  3056.         this.setTarget( document.popupNode );
  3057.         
  3058.         this.isTextSelected = this.isTextSelection();
  3059.  
  3060.         // Initialize (disable/remove) menu items.
  3061.         this.initItems();
  3062.     },
  3063.     initItems : function () {
  3064.         this.initOpenItems();
  3065.         this.initNavigationItems();
  3066.         this.initViewItems();
  3067.         this.initMiscItems();
  3068.         this.initSaveItems();
  3069.         this.initClipboardItems();
  3070.         this.initMetadataItems();
  3071.     },
  3072.     initOpenItems : function () {
  3073.         this.showItem( "context-openlink", this.onSaveableLink || ( this.inDirList && this.onLink ) );
  3074.         this.showItem( "context-openlinkintab", this.onSaveableLink || ( this.inDirList && this.onLink ) );
  3075.  
  3076.         this.showItem( "context-sep-open", this.onSaveableLink || ( this.inDirList && this.onLink ) );
  3077.     },
  3078.     initNavigationItems : function () {
  3079.         // Back determined by canGoBack broadcaster.
  3080.         this.setItemAttrFromNode( "context-back", "disabled", "canGoBack" );
  3081.  
  3082.         // Forward determined by canGoForward broadcaster.
  3083.         this.setItemAttrFromNode( "context-forward", "disabled", "canGoForward" );
  3084.         
  3085.         this.showItem( "context-back", !( this.isTextSelected || this.onLink || this.onImage || this.onTextInput ) );
  3086.         this.showItem( "context-forward", !( this.isTextSelected || this.onLink || this.onImage || this.onTextInput ) );
  3087.  
  3088.         this.showItem( "context-reload", !( this.isTextSelected || this.onLink || this.onImage || this.onTextInput ) );
  3089.         
  3090.         this.showItem( "context-stop", !( this.isTextSelected || this.onLink || this.onImage || this.onTextInput ) );
  3091.         this.showItem( "context-sep-stop", !( this.isTextSelected || this.onLink || this.onTextInput ) );
  3092.  
  3093.         // XXX: Stop is determined in navigator.js; the canStop broadcaster is broken
  3094.         //this.setItemAttrFromNode( "context-stop", "disabled", "canStop" );
  3095.     },
  3096.     initSaveItems : function () {
  3097.         this.showItem( "context-savepage", !( this.inDirList || this.isTextSelected || this.onTextInput || this.onLink ));
  3098.  
  3099.         // Save link depends on whether we're in a link.
  3100.         this.showItem( "context-savelink", this.onSaveableLink );
  3101.  
  3102.         // Save image depends on whether there is one.
  3103.         this.showItem( "context-saveimage", this.onImage );
  3104.         
  3105.         this.showItem( "context-sendimage", this.onImage );
  3106.     },
  3107.     initViewItems : function () {
  3108.         // View source is always OK, unless in directory listing.
  3109.         this.showItem( "context-viewpartialsource-selection", this.isTextSelected );
  3110.         this.showItem( "context-viewpartialsource-mathml", this.onMathML && !this.isTextSelected );
  3111.         this.showItem( "context-viewsource", !( this.inDirList || this.onImage || this.isTextSelected || this.onLink || this.onTextInput ) );
  3112.         this.showItem( "context-viewinfo", !( this.inDirList || this.onImage || this.isTextSelected || this.onLink || this.onTextInput ) );
  3113.  
  3114.         this.showItem( "context-sep-properties", !( this.inDirList || this.isTextSelected || this.onTextInput ) );
  3115.         // Set As Wallpaper depends on whether an image was clicked on, and only works on Windows.
  3116.         var isWin = navigator.appVersion.indexOf("Windows") != -1;
  3117.         this.showItem( "context-setWallpaper", isWin && this.onImage );
  3118.  
  3119.         if( isWin && this.onImage )
  3120.             // Disable the Set As Wallpaper menu item if we're still trying to load the image
  3121.           this.setItemAttr( "context-setWallpaper", "disabled", (("complete" in this.target) && !this.target.complete) ? "true" : null );
  3122.  
  3123.         // View Image depends on whether an image was clicked on.
  3124.         this.showItem( "context-viewimage", this.onImage );
  3125.  
  3126.         // View background image depends on whether there is one.
  3127.         this.showItem( "context-viewbgimage", !( this.inDirList || this.onImage || this.isTextSelected || this.onLink || this.onTextInput ) );
  3128.         this.showItem( "context-sep-viewbgimage", !( this.inDirList || this.onImage || this.isTextSelected || this.onLink || this.onTextInput ) );
  3129.         this.setItemAttr( "context-viewbgimage", "disabled", this.hasBGImage ? null : "true");
  3130.     },
  3131.     initMiscItems : function () {
  3132.         // Use "Bookmark This Link" if on a link.
  3133.         this.showItem( "context-bookmarkpage", !( this.isTextSelected || this.onTextInput || this.onLink ) );
  3134.         this.showItem( "context-bookmarklink", this.onLink && !this.onMailtoLink );
  3135.         this.showItem( "context-searchselect", this.isTextSelected );
  3136.         this.showItem( "frame", this.inFrame );
  3137.         this.showItem( "frame-sep", this.inFrame );
  3138.         this.showItem( "context-blockimage", this.onImage);
  3139.         if (this.onImage) {
  3140.           var blockImage = document.getElementById("context-blockimage");
  3141.           if (this.isImageBlocked()) {
  3142.             blockImage.setAttribute("checked", "true");
  3143.           }
  3144.           else
  3145.             blockImage.removeAttribute("checked");
  3146.         }
  3147.     },
  3148.     initClipboardItems : function () {
  3149.  
  3150.         // Copy depends on whether there is selected text.
  3151.         // Enabling this context menu item is now done through the global
  3152.         // command updating system
  3153.         // this.setItemAttr( "context-copy", "disabled", !this.isTextSelected() );
  3154.  
  3155.         goUpdateGlobalEditMenuItems();
  3156.  
  3157.         this.showItem( "context-undo", this.isTextSelected || this.onTextInput );
  3158.         this.showItem( "context-sep-undo", this.isTextSelected || this.onTextInput );
  3159.         this.showItem( "context-cut", this.isTextSelected || this.onTextInput );
  3160.         this.showItem( "context-copy", this.isTextSelected || this.onTextInput );
  3161.         this.showItem( "context-paste", this.isTextSelected || this.onTextInput );
  3162.         this.showItem( "context-delete", this.isTextSelected || this.onTextInput );
  3163.         this.showItem( "context-sep-paste", this.isTextSelected || this.onTextInput );
  3164.         this.showItem( "context-selectall", this.isTextSelected || this.onTextInput );
  3165.         this.showItem( "context-sep-selectall", this.isTextSelected );
  3166.  
  3167.         // XXX dr
  3168.         // ------
  3169.         // nsDocumentViewer.cpp has code to determine whether we're
  3170.         // on a link or an image. we really ought to be using that...
  3171.  
  3172.         // Copy email link depends on whether we're on an email link.
  3173.         this.showItem( "context-copyemail", this.onMailtoLink );
  3174.  
  3175.         // Copy link location depends on whether we're on a link.
  3176.         this.showItem( "context-copylink", this.onLink );
  3177.         this.showItem( "context-sep-copylink", this.onLink && this.onImage);
  3178.  
  3179.         // Copy image location depends on whether we're on an image.
  3180.         this.showItem( "context-copyimage", this.onImage );
  3181.         this.showItem( "context-sep-copyimage", this.onImage );
  3182.     },
  3183.     initMetadataItems : function () {
  3184.         // Show if user clicked on something which has metadata.
  3185.         this.showItem( "context-metadata", this.onMetaDataItem );
  3186.     },
  3187.     // Set various context menu attributes based on the state of the world.
  3188.     setTarget : function ( node ) {
  3189.         const xulNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
  3190.         if ( node.namespaceURI == xulNS ) {
  3191.           this.shouldDisplay = false;
  3192.           return;
  3193.         }
  3194.         // Initialize contextual info.
  3195.         this.onImage    = false;
  3196.         this.onMetaDataItem = false;
  3197.         this.onTextInput = false;
  3198.         this.imageURL   = "";
  3199.         this.onLink     = false;
  3200.         this.onMathML   = false;
  3201.         this.inFrame    = false;
  3202.         this.hasBGImage = false;
  3203.         this.bgImageURL = "";
  3204.  
  3205.         // Remember the node that was clicked.
  3206.         this.target = node;
  3207.  
  3208.         // See if the user clicked on an image.
  3209.         if ( this.target.nodeType == Node.ELEMENT_NODE ) {
  3210.              if ( this.target.localName.toUpperCase() == "IMG" ) {
  3211.                 this.onImage = true;
  3212.                 this.imageURL = this.target.src;
  3213.                 // Look for image map.
  3214.                 var mapName = this.target.getAttribute( "usemap" );
  3215.                 if ( mapName ) {
  3216.                     // Find map.
  3217.                     var map = this.target.ownerDocument.getElementById( mapName.substr(1) );
  3218.                     if ( map ) {
  3219.                         // Search child <area>s for a match.
  3220.                         var areas = map.childNodes;
  3221.                         //XXX Client side image maps are too hard for now!
  3222.                         areas.length = 0;
  3223.                         for ( var i = 0; i < areas.length && !this.onLink; i++ ) {
  3224.                             var area = areas[i];
  3225.                             if ( area.nodeType == Node.ELEMENT_NODE
  3226.                                  &&
  3227.                                  area.localName.toUpperCase() == "AREA" ) {
  3228.                                 // Get type (rect/circle/polygon/default).
  3229.                                 var type = area.getAttribute( "type" );
  3230.                                 var coords = this.parseCoords( area );
  3231.                                 switch ( type.toUpperCase() ) {
  3232.                                     case "RECT":
  3233.                                     case "RECTANGLE":
  3234.                                         break;
  3235.                                     case "CIRC":
  3236.                                     case "CIRCLE":
  3237.                                         break;
  3238.                                     case "POLY":
  3239.                                     case "POLYGON":
  3240.                                         break;
  3241.                                     case "DEFAULT":
  3242.                                         // Default matches entire image.
  3243.                                         this.onLink = true;
  3244.                                         this.link = area;
  3245.                                         this.onSaveableLink = this.isLinkSaveable( this.link );
  3246.                                         break;
  3247.                                 }
  3248.                             }
  3249.                         }
  3250.                     }
  3251.                 }
  3252.              } else if ( this.target.localName.toUpperCase() == "OBJECT"
  3253.                          &&
  3254.                          // See if object tag is for an image.
  3255.                          this.objectIsImage( this.target ) ) {
  3256.                 // This is an image.
  3257.                 this.onImage = true;
  3258.                 // URL must be constructed.
  3259.                 this.imageURL = this.objectImageURL( this.target );
  3260.              } else if ( this.target.localName.toUpperCase() == "INPUT") {
  3261.                type = this.target.getAttribute("type");
  3262.                if(type && type.toUpperCase() == "IMAGE") {
  3263.                  this.onImage = true;
  3264.                  // Convert src attribute to absolute URL.
  3265.                  this.imageURL = makeURLAbsolute( this.target.baseURI,
  3266.                                                   this.target.src );
  3267.                } else /* if (this.target.getAttribute( "type" ).toUpperCase() == "TEXT") */ {
  3268.                  this.onTextInput = this.isTargetATextBox(this.target);
  3269.                }
  3270.             } else if ( this.target.localName.toUpperCase() == "TEXTAREA" ) {
  3271.                  this.onTextInput = true;
  3272.             } else if ( this.target.localName.toUpperCase() == "HTML" ) {
  3273.                // pages with multiple <body>s are lame. we'll teach them a lesson.
  3274.                var bodyElt = this.target.ownerDocument.getElementsByTagName("body")[0];
  3275.                if ( bodyElt ) {
  3276.                  var computedURL = this.getComputedURL( bodyElt, "background-image" );
  3277.                  if ( computedURL ) {
  3278.                    this.hasBGImage = true;
  3279.                    this.bgImageURL = makeURLAbsolute( bodyElt.baseURI,
  3280.                                                       computedURL );
  3281.                  }
  3282.                }
  3283.             } else if ( "HTTPIndex" in _content &&
  3284.                         _content.HTTPIndex instanceof Components.interfaces.nsIHTTPIndex ) {
  3285.                 this.inDirList = true;
  3286.                 // Bubble outward till we get to an element with URL attribute
  3287.                 // (which should be the href).
  3288.                 var root = this.target;
  3289.                 while ( root && !this.link ) {
  3290.                     if ( root.tagName == "tree" ) {
  3291.                         // Hit root of tree; must have clicked in empty space;
  3292.                         // thus, no link.
  3293.                         break;
  3294.                     }
  3295.                     if ( root.getAttribute( "URL" ) ) {
  3296.                         // Build pseudo link object so link-related functions work.
  3297.                         this.onLink = true;
  3298.                         this.link = { href : root.getAttribute("URL"),
  3299.                                       getAttribute: function (attr) {
  3300.                                           if (attr == "title") {
  3301.                                               return root.firstChild.firstChild.getAttribute("label");
  3302.                                           } else {
  3303.                                               return "";
  3304.                                           }
  3305.                                       }
  3306.                                     };
  3307.                         // If element is a directory, then you can't save it.
  3308.                         if ( root.getAttribute( "container" ) == "true" ) {
  3309.                             this.onSaveableLink = false;
  3310.                         } else {
  3311.                             this.onSaveableLink = true;
  3312.                         }
  3313.                     } else {
  3314.                         root = root.parentNode;
  3315.                     }
  3316.                 }
  3317.             }
  3318.         }
  3319.  
  3320.         // We have meta data on images.
  3321.         this.onMetaDataItem = this.onImage;
  3322.         
  3323.         // See if the user clicked on MathML
  3324.         const NS_MathML = "http://www.w3.org/1998/Math/MathML";
  3325.         if ((this.target.nodeType == Node.TEXT_NODE &&
  3326.              this.target.parentNode.namespaceURI == NS_MathML)
  3327.              || (this.target.namespaceURI == NS_MathML))
  3328.           this.onMathML = true;
  3329.  
  3330.         // See if the user clicked in a frame.
  3331.         if ( this.target.ownerDocument != window._content.document ) {
  3332.             this.inFrame = true;
  3333.         }
  3334.         
  3335.         // Bubble out, looking for items of interest
  3336.         var elem = this.target;
  3337.         while ( elem ) {
  3338.             if ( elem.nodeType == Node.ELEMENT_NODE ) {
  3339.                 var localname = elem.localName.toUpperCase();
  3340.                 
  3341.                 // Link?
  3342.                 if ( !this.onLink && 
  3343.                     ( (localname === "A" && elem.href) ||
  3344.                       localname === "AREA" ||
  3345.                       localname === "LINK" ||
  3346.                       elem.getAttributeNS( "http://www.w3.org/1999/xlink", "type") == "simple" ) ) {
  3347.                     // Clicked on a link.
  3348.                     this.onLink = true;
  3349.                     this.onMetaDataItem = true;
  3350.                     // Remember corresponding element.
  3351.                     this.link = elem;
  3352.                     this.onMailtoLink = this.isLinkType( "mailto:", this.link );
  3353.                     // Remember if it is saveable.
  3354.                     this.onSaveableLink = this.isLinkSaveable( this.link );
  3355.                 }
  3356.                 
  3357.                 // Text input?
  3358.                 if ( !this.onTextInput ) {
  3359.                     // Clicked on a link.
  3360.                     this.onTextInput = this.isTargetATextBox(elem);
  3361.                 }
  3362.                 
  3363.                 // Metadata item?
  3364.                 if ( !this.onMetaDataItem ) {
  3365.                     // We currently display metadata on anything which fits
  3366.                     // the below test.
  3367.                     if ( ( localname === "BLOCKQUOTE" && 'cite' in elem && elem.cite)  ||
  3368.                          ( localname === "Q" && 'cite' in elem && elem.cite)           ||
  3369.                          ( localname === "TABLE" && 'summary' in elem && elem.summary) ||
  3370.                          ( ( localname === "INS" || localname === "DEL" ) &&
  3371.                            ( ( 'cite' in elem && elem.cite ) ||
  3372.                              ( 'dateTime' in elem && elem.dateTime ) ) )               ||
  3373.                          ( 'title' in elem && elem.title )                             ||
  3374.                          ( 'lang' in elem && elem.lang ) ) {
  3375.                         dump("On metadata item.\n");
  3376.                         this.onMetaDataItem = true;
  3377.                     }
  3378.                 }
  3379.  
  3380.                 // Background image?  Don't bother if we've already found a 
  3381.                 // background image further down the hierarchy.  Otherwise,
  3382.                 // we look for the computed background-image style.
  3383.                 if ( !this.hasBGImage ) {
  3384.                     var bgImgUrl = this.getComputedURL( elem, "background-image" );
  3385.                     if ( bgImgUrl ) {
  3386.                         this.hasBGImage = true;
  3387.                         this.bgImageURL = makeURLAbsolute( elem.baseURI,
  3388.                                                            bgImgUrl );
  3389.                     }
  3390.                 }
  3391.             }
  3392.             elem = elem.parentNode;    
  3393.         }
  3394.     },
  3395.     // Returns the computed style attribute for the given element.
  3396.     getComputedStyle: function( elem, prop ) {
  3397.          return elem.ownerDocument.defaultView.getComputedStyle( elem, '' ).getPropertyValue( prop );
  3398.     },
  3399.     // Returns a "url"-type computed style attribute value, with the url() stripped.
  3400.     getComputedURL: function( elem, prop ) {
  3401.          var url = elem.ownerDocument.defaultView.getComputedStyle( elem, '' ).getPropertyCSSValue( prop );
  3402.          return ( url.primitiveType == CSSPrimitiveValue.CSS_URI ) ? url.getStringValue() : null;
  3403.     },
  3404.     // Returns true iff clicked on link is saveable.
  3405.     isLinkSaveable : function ( link ) {
  3406.         // We don't do the Right Thing for news/snews yet, so turn them off
  3407.         // until we do.
  3408.         return !(this.isLinkType( "mailto:" , link )     ||
  3409.                  this.isLinkType( "javascript:" , link ) ||
  3410.                  this.isLinkType( "news:", link )        || 
  3411.                  this.isLinkType( "snews:", link ) ); 
  3412.     },
  3413.     // Returns true iff clicked on link is of type given.
  3414.     isLinkType : function ( linktype, link ) {        
  3415.         try {
  3416.             // Test for missing protocol property.
  3417.             if ( !link.protocol ) {
  3418.                 // We must resort to testing the URL string :-(.
  3419.                 var protocol;
  3420.                 if ( link.href ) {
  3421.                     protocol = link.href.substr( 0, linktype.length );
  3422.                 } else {
  3423.                     protocol = link.getAttributeNS("http://www.w3.org/1999/xlink","href");
  3424.                     if ( protocol ) {
  3425.                         protocol = protocol.substr( 0, linktype.length );
  3426.                     }
  3427.                 }
  3428.                 return protocol.toLowerCase() === linktype;        
  3429.             } else {
  3430.                 // Presume all but javascript: urls are saveable.
  3431.                 return link.protocol.toLowerCase() === linktype;
  3432.             }
  3433.         } catch (e) {
  3434.             // something was wrong with the link,
  3435.             // so we won't be able to save it anyway
  3436.             return false;
  3437.         }
  3438.     },
  3439.     // Open linked-to URL in a new window.
  3440.     openLink : function () {
  3441.         // Determine linked-to URL.
  3442.         openNewWindowWith(this.linkURL(), this.link, true);
  3443.     },
  3444.     // Open linked-to URL in a new tab.
  3445.     openLinkInTab : function () {
  3446.         // Determine linked-to URL.
  3447.         openNewTabWith(this.linkURL(), this.link, null, true);
  3448.     },
  3449.     // Open frame in a new tab.
  3450.     openFrameInTab : function () {
  3451.         // Determine linked-to URL.
  3452.         openNewTabWith(this.target.ownerDocument.location.href, null, null, true);
  3453.     },
  3454.     // Reload clicked-in frame.
  3455.     reloadFrame : function () {
  3456.         this.target.ownerDocument.location.reload();
  3457.     },
  3458.     // Open clicked-in frame in its own window.
  3459.     openFrame : function () {
  3460.         openNewWindowWith(this.target.ownerDocument.location.href, null, true);
  3461.     },
  3462.     // Open clicked-in frame in the same window
  3463.     showOnlyThisFrame : function () {
  3464.         window.loadURI(this.target.ownerDocument.location.href);
  3465.     },
  3466.     // View Partial Source
  3467.     viewPartialSource : function ( context ) {
  3468.         var focusedWindow = document.commandDispatcher.focusedWindow;
  3469.         if (focusedWindow == window)
  3470.           focusedWindow = _content;
  3471.         var docCharset = null;
  3472.         if (focusedWindow)
  3473.           docCharset = "charset=" + focusedWindow.document.characterSet;
  3474.  
  3475.         // "View Selection Source" and others such as "View MathML Source"
  3476.         // are mutually exclusive, with the precedence given to the selection
  3477.         // when there is one
  3478.         var reference = null;
  3479.         if (context == "selection")
  3480.           reference = focusedWindow.__proto__.getSelection.call(focusedWindow);
  3481.         else if (context == "mathml")
  3482.           reference = this.target;
  3483.         else
  3484.           throw "not reached";
  3485.  
  3486.         var docUrl = null; // unused (and play nice for fragments generated via XSLT too)
  3487.         window.openDialog("chrome://browser/content/viewPartialSource.xul",
  3488.                           "_blank", "scrollbars,resizable,chrome,dialog=no",
  3489.                           docUrl, docCharset, reference, context);
  3490.     },
  3491.     // Open new "view source" window with the frame's URL.
  3492.     viewFrameSource : function () {
  3493.         BrowserViewSourceOfDocument(this.target.ownerDocument);
  3494.     },
  3495.     viewInfo : function () {
  3496.       BrowserPageInfo();
  3497.     },
  3498.     viewFrameInfo : function () {
  3499.       BrowserPageInfo(this.target.ownerDocument);
  3500.     },
  3501.     // Change current window to the URL of the image.
  3502.     viewImage : function () {
  3503.         openTopWin( this.imageURL );
  3504.     },
  3505.     // Change current window to the URL of the background image.
  3506.     viewBGImage : function () {
  3507.         openTopWin( this.bgImageURL );
  3508.     },
  3509.     setWallpaper: function() {
  3510.       var winhooks = Components.classes[ "@mozilla.org/winhooks;1" ].
  3511.                        getService(Components.interfaces.nsIWindowsHooks);
  3512.       
  3513.       winhooks.setImageAsWallpaper(this.target, false);
  3514.     },    
  3515.     // Save URL of clicked-on frame.
  3516.     saveFrame : function () {
  3517.         saveDocument( this.target.ownerDocument );
  3518.     },
  3519.     // Save URL of clicked-on link.
  3520.     saveLink : function () {
  3521.         saveURL( this.linkURL(), this.linkText(), null, true );
  3522.     },
  3523.     // Save URL of clicked-on image.
  3524.     saveImage : function () {
  3525.         saveURL( this.imageURL, null, "SaveImageTitle", false );
  3526.     },
  3527.     toggleImageBlocking : function (aBlock) {
  3528.       var permissionmanager =
  3529.         Components.classes["@mozilla.org/permissionmanager;1"]
  3530.           .getService(Components.interfaces.nsIPermissionManager);
  3531.       permissionmanager.add(this.imageURL, !aBlock, IMAGEPERMISSION);
  3532.     },
  3533.     isImageBlocked : function() {
  3534.        var permissionmanager =
  3535.          Components.classes["@mozilla.org/permissionmanager;1"]
  3536.            .getService(Components.interfaces.nsIPermissionManager);
  3537.        return permissionmanager.testForBlocking(this.imageURL, IMAGEPERMISSION);
  3538.     },
  3539.     // Generate email address and put it on clipboard.
  3540.     copyEmail : function () {
  3541.         // Copy the comma-separated list of email addresses only.
  3542.         // There are other ways of embedding email addresses in a mailto:
  3543.         // link, but such complex parsing is beyond us.
  3544.         var url = this.linkURL();
  3545.         var qmark = url.indexOf( "?" );
  3546.         var addresses;
  3547.         
  3548.         if ( qmark > 7 ) {                   // 7 == length of "mailto:"
  3549.             addresses = url.substring( 7, qmark );
  3550.         } else {
  3551.             addresses = url.substr( 7 );
  3552.         }
  3553.  
  3554.         var clipboard = this.getService( "@mozilla.org/widget/clipboardhelper;1",
  3555.                                          Components.interfaces.nsIClipboardHelper );
  3556.         clipboard.copyString(addresses);
  3557.     },    
  3558.     addBookmark : function() {
  3559.       var docshell = document.getElementById( "content" ).webNavigation;
  3560.       BookmarksUtils.addBookmark( docshell.currentURI.spec,
  3561.                                   docshell.document.title,
  3562.                                   docshell.document.charset,
  3563.                                   false );
  3564.     },
  3565.     addBookmarkForFrame : function() {
  3566.       var doc = this.target.ownerDocument;
  3567.       var uri = doc.location.href;
  3568.       var title = doc.title;
  3569.       if ( !title )
  3570.         title = uri;
  3571.       BookmarksUtils.addBookmark( uri,
  3572.                                   title,
  3573.                                   doc.charset,
  3574.                                   false );
  3575.     },
  3576.     // Open Metadata window for node
  3577.     showMetadata : function () {
  3578.         window.openDialog(  "chrome://navigator/content/metadata.xul",
  3579.                             "_blank",
  3580.                             "scrollbars,resizable,chrome,dialog=no",
  3581.                             this.target);
  3582.     },
  3583.  
  3584.     ///////////////
  3585.     // Utilities //
  3586.     ///////////////
  3587.  
  3588.     // Create instance of component given contractId and iid (as string).
  3589.     createInstance : function ( contractId, iidName ) {
  3590.         var iid = Components.interfaces[ iidName ];
  3591.         return Components.classes[ contractId ].createInstance( iid );
  3592.     },
  3593.     // Get service given contractId and iid (as string).
  3594.     getService : function ( contractId, iidName ) {
  3595.         var iid = Components.interfaces[ iidName ];
  3596.         return Components.classes[ contractId ].getService( iid );
  3597.     },
  3598.     // Show/hide one item (specified via name or the item element itself).
  3599.     showItem : function ( itemOrId, show ) {
  3600.         var item = itemOrId.constructor == String ? document.getElementById(itemOrId) : itemOrId;
  3601.         if (item) 
  3602.           item.hidden = !show;
  3603.     },
  3604.     // Set given attribute of specified context-menu item.  If the
  3605.     // value is null, then it removes the attribute (which works
  3606.     // nicely for the disabled attribute).
  3607.     setItemAttr : function ( id, attr, val ) {
  3608.         var elem = document.getElementById( id );
  3609.         if ( elem ) {
  3610.             if ( val == null ) {
  3611.                 // null indicates attr should be removed.
  3612.                 elem.removeAttribute( attr );
  3613.             } else {
  3614.                 // Set attr=val.
  3615.                 elem.setAttribute( attr, val );
  3616.             }
  3617.         }
  3618.     },
  3619.     // Set context menu attribute according to like attribute of another node
  3620.     // (such as a broadcaster).
  3621.     setItemAttrFromNode : function ( item_id, attr, other_id ) {
  3622.         var elem = document.getElementById( other_id );
  3623.         if ( elem && elem.getAttribute( attr ) == "true" ) {
  3624.             this.setItemAttr( item_id, attr, "true" );
  3625.         } else {
  3626.             this.setItemAttr( item_id, attr, null );
  3627.         }
  3628.     },
  3629.     // Temporary workaround for DOM api not yet implemented by XUL nodes.
  3630.     cloneNode : function ( item ) {
  3631.         // Create another element like the one we're cloning.
  3632.         var node = document.createElement( item.tagName );
  3633.  
  3634.         // Copy attributes from argument item to the new one.
  3635.         var attrs = item.attributes;
  3636.         for ( var i = 0; i < attrs.length; i++ ) {
  3637.             var attr = attrs.item( i );
  3638.             node.setAttribute( attr.nodeName, attr.nodeValue );
  3639.         }
  3640.  
  3641.         // Voila!
  3642.         return node;
  3643.     },
  3644.     // Generate fully-qualified URL for clicked-on link.
  3645.     linkURL : function () {
  3646.         if (this.link.href) {
  3647.           return this.link.href;
  3648.         }
  3649.         var href = this.link.getAttributeNS("http://www.w3.org/1999/xlink","href");
  3650.         if (!href || !href.match(/\S/)) {
  3651.           throw "Empty href"; // Without this we try to save as the current doc, for example, HTML case also throws if empty
  3652.         }
  3653.         href = makeURLAbsolute(this.link.baseURI,href);
  3654.         return href;
  3655.     },
  3656.     // Get text of link.
  3657.     linkText : function () {
  3658.         var text = gatherTextUnder( this.link );
  3659.         if (!text || !text.match(/\S/)) {
  3660.           text = this.link.getAttribute("title");
  3661.           if (!text || !text.match(/\S/)) {
  3662.             text = this.link.getAttribute("alt");
  3663.             if (!text || !text.match(/\S/)) {
  3664.               if (this.link.href) {                
  3665.                 text = this.link.href;
  3666.               } else {
  3667.                 text = getAttributeNS("http://www.w3.org/1999/xlink", "href");
  3668.                 if (text && text.match(/\S/)) {
  3669.                   text = makeURLAbsolute(this.link.baseURI, text);
  3670.                 }
  3671.               }
  3672.             }
  3673.           }
  3674.         }
  3675.  
  3676.         return text;
  3677.     },
  3678.  
  3679.     //Get selected object and convert it to a string to get
  3680.     //selected text.   Only use the first 15 chars.
  3681.     isTextSelection : function() {
  3682.         var result = false;
  3683.         var selection = this.searchSelected();
  3684.  
  3685.         var searchSelectText;
  3686.         if (selection != "") {
  3687.             searchSelectText = selection.toString();
  3688.             if (searchSelectText.length > 15)
  3689.                 searchSelectText = searchSelectText.substr(0,15) + "...";
  3690.             result = true;
  3691.  
  3692.           // format "Search for <selection>" string to show in menu
  3693.           searchSelectText = gNavigatorBundle.getFormattedString("searchText", [searchSelectText]);
  3694.           this.setItemAttr("context-searchselect", "label", searchSelectText);
  3695.         } 
  3696.         return result;
  3697.     },
  3698.     
  3699.     searchSelected : function() {
  3700.         var focusedWindow = document.commandDispatcher.focusedWindow;
  3701.         var searchStr = focusedWindow.__proto__.getSelection.call(focusedWindow);
  3702.         searchStr = searchStr.toString();
  3703.         searchStr = searchStr.replace( /^\s+/, "" );
  3704.         searchStr = searchStr.replace(/(\n|\r|\t)+/g, " ");
  3705.         searchStr = searchStr.replace(/\s+$/,"");
  3706.         return searchStr;
  3707.     },
  3708.     
  3709.     // Determine if target <object> is an image.
  3710.     objectIsImage : function ( objElem ) {
  3711.         var result = false;
  3712.         // Get type and data attributes.
  3713.         var type = objElem.getAttribute( "type" );
  3714.         var data = objElem.getAttribute( "data" );
  3715.         // Presume any mime type of the form "image/..." is an image.
  3716.         // There must be a data= attribute with an URL, also.
  3717.         if ( type.substring( 0, 6 ) == "image/" && data && data != "" ) {
  3718.             result = true;
  3719.         }
  3720.         return result;
  3721.     },
  3722.     // Extract image URL from <object> tag.
  3723.     objectImageURL : function ( objElem ) {
  3724.         // Extract url from data= attribute.
  3725.         var data = objElem.getAttribute( "data" );
  3726.         // Make it absolute.
  3727.         return makeURLAbsolute( objElem.baseURI, data );
  3728.     },
  3729.     // Parse coords= attribute and return array.
  3730.     parseCoords : function ( area ) {
  3731.         return [];
  3732.     },
  3733.     toString : function () {
  3734.         return "contextMenu.target     = " + this.target + "\n" +
  3735.                "contextMenu.onImage    = " + this.onImage + "\n" +
  3736.                "contextMenu.onLink     = " + this.onLink + "\n" +
  3737.                "contextMenu.link       = " + this.link + "\n" +
  3738.                "contextMenu.inFrame    = " + this.inFrame + "\n" +
  3739.                "contextMenu.hasBGImage = " + this.hasBGImage + "\n";
  3740.     },
  3741.     isTargetATextBox : function ( node )
  3742.     {
  3743.       if (node.nodeType != Node.ELEMENT_NODE)
  3744.         return false;
  3745.  
  3746.       if (node.localName.toUpperCase() == "INPUT") {
  3747.         var attrib = "";
  3748.         var type = node.getAttribute("type");
  3749.  
  3750.         if (type)
  3751.           attrib = type.toUpperCase();
  3752.  
  3753.         return( (attrib != "IMAGE") &&
  3754.                 (attrib != "CHECKBOX") &&
  3755.                 (attrib != "RADIO") &&
  3756.                 (attrib != "SUBMIT") &&
  3757.                 (attrib != "RESET") &&
  3758.                 (attrib != "FILE") &&
  3759.                 (attrib != "HIDDEN") &&
  3760.                 (attrib != "RESET") &&
  3761.                 (attrib != "BUTTON") );
  3762.       } else  {
  3763.         return(node.localName.toUpperCase() == "TEXTAREA");
  3764.       }
  3765.     },
  3766.     
  3767.     // Determines whether or not the separator with the specified ID should be 
  3768.     // shown or not by determining if there are any non-hidden items between it
  3769.     // and the previous separator. 
  3770.     shouldShowSeparator : function ( aSeparatorID )
  3771.     {
  3772.       var separator = document.getElementById(aSeparatorID);
  3773.       if (separator) {
  3774.         var sibling = separator.previousSibling;
  3775.         while (sibling && sibling.localName != "menuseparator") {
  3776.           if (sibling.getAttribute("hidden") != "true")
  3777.             return true;
  3778.           sibling = sibling.previousSibling;
  3779.         }
  3780.       }
  3781.       return false;  
  3782.     }
  3783. };
  3784.  
  3785. /*************************************************************************
  3786.  *
  3787.  *   nsDefaultEngine : nsIObserver
  3788.  *
  3789.  *************************************************************************/
  3790. function nsDefaultEngine()
  3791. {
  3792.     try
  3793.     {
  3794.         var pb = Components.classes["@mozilla.org/preferences-service;1"].
  3795.                    getService(Components.interfaces.nsIPrefBranch);
  3796.         var pbi = pb.QueryInterface(
  3797.                     Components.interfaces.nsIPrefBranchInternal);
  3798.         pbi.addObserver(this.domain, this, false);
  3799.  
  3800.         // reuse code by explicitly invoking initial |observe| call
  3801.         // to initialize the |icon| and |name| member variables
  3802.         this.observe(pb, "", this.domain);
  3803.     }
  3804.     catch (ex)
  3805.     {
  3806.     }
  3807. }
  3808.  
  3809. nsDefaultEngine.prototype = 
  3810. {
  3811.     name: "",
  3812.     icon: "",
  3813.     domain: "browser.search.defaultengine",
  3814.  
  3815.     // nsIObserver implementation
  3816.     observe: function(aPrefBranch, aTopic, aPrefName)
  3817.     {
  3818.         try
  3819.         {
  3820.             var rdf = Components.
  3821.                         classes["@mozilla.org/rdf/rdf-service;1"].
  3822.                         getService(Components.interfaces.nsIRDFService);
  3823.             var ds = rdf.GetDataSource("rdf:internetsearch");
  3824.             var defaultEngine = aPrefBranch.getCharPref(aPrefName);
  3825.             var res = rdf.GetResource(defaultEngine);
  3826.  
  3827.             // get engine ``pretty'' name
  3828.             const kNC_Name = rdf.GetResource(
  3829.                                "http://home.netscape.com/NC-rdf#Name");
  3830.             var engineName = ds.GetTarget(res, kNC_Name, true);
  3831.             if (engineName)
  3832.             {
  3833.                 this.name = engineName.QueryInterface(
  3834.                               Components.interfaces.nsIRDFLiteral).Value;
  3835.             }
  3836.  
  3837.             // get URL to engine vendor icon
  3838.             const kNC_Icon = rdf.GetResource(
  3839.                                "http://home.netscape.com/NC-rdf#Icon");
  3840.             var iconURL = ds.GetTarget(res, kNC_Icon, true);
  3841.             if (iconURL)
  3842.             {
  3843.                 this.icon = iconURL.QueryInterface(
  3844.                   Components.interfaces.nsIRDFLiteral).Value;
  3845.             }
  3846.         }
  3847.         catch (ex)
  3848.         {
  3849.         }
  3850.     }
  3851. }
  3852.  
  3853. /*
  3854.  * - [ Dependencies ] ---------------------------------------------------------
  3855.  *  utilityOverlay.js:
  3856.  *    - gatherTextUnder
  3857.  */
  3858.  
  3859.  // Called whenever the user clicks in the content area,
  3860.  // except when left-clicking on links (special case)
  3861.  // should always return true for click to go through
  3862.  function contentAreaClick(event) 
  3863.  {
  3864.    var target = event.target;
  3865.    var linkNode;
  3866.  
  3867.    var local_name = target.localName;
  3868.  
  3869.    if (local_name) {
  3870.      local_name = local_name.toLowerCase();
  3871.    }
  3872.  
  3873.    switch (local_name) {
  3874.      case "a":
  3875.      case "area":
  3876.      case "link":
  3877.        if (target.hasAttribute("href")) 
  3878.          linkNode = target;
  3879.        break;
  3880.      default:
  3881.        linkNode = findParentNode(event.originalTarget, "a");
  3882.        // <a> cannot be nested.  So if we find an anchor without an
  3883.        // href, there is no useful <a> around the target
  3884.        if (linkNode && !linkNode.hasAttribute("href"))
  3885.          linkNode = null;
  3886.        break;
  3887.    }
  3888.    if (linkNode) {
  3889.      handleLinkClick(event, linkNode.href, linkNode);
  3890.      return true;
  3891.    } else {
  3892.      // Try simple XLink
  3893.      var href;
  3894.      linkNode = target;
  3895.      while (linkNode) {
  3896.        if (linkNode.nodeType == Node.ELEMENT_NODE) {
  3897.          href = linkNode.getAttributeNS("http://www.w3.org/1999/xlink", "href");
  3898.          break;
  3899.        }
  3900.        linkNode = linkNode.parentNode;
  3901.      }
  3902.      if (href && href != "") {
  3903.        href = makeURLAbsolute(target.baseURI,href);
  3904.        handleLinkClick(event, href, null);
  3905.        return true;
  3906.      }
  3907.    }
  3908.    if (event.button == 1 &&
  3909.        !findParentNode(event.originalTarget, "scrollbar") &&
  3910.        gPrefService.getBoolPref("middlemouse.contentLoadURL")) {
  3911.      if (middleMousePaste(event)) {
  3912.        event.preventBubble();
  3913.      }
  3914.    }
  3915.    return true;
  3916.  }
  3917.  
  3918. function handleLinkClick(event, href, linkNode)
  3919. {
  3920.   switch (event.button) {                                   
  3921.     case 0:  
  3922.       if (event.ctrlKey) {
  3923.         openNewTabWith(href, linkNode, event, true);
  3924.         event.preventBubble();
  3925.         return true;
  3926.       } 
  3927.                                                        // if left button clicked
  3928.       if (event.shiftKey) {
  3929.         openNewWindowWith(href, linkNode, true);
  3930.         event.preventBubble();
  3931.         return true;
  3932.       }
  3933.       
  3934.       if (event.altKey) {
  3935.         saveURL(href, linkNode ? gatherTextUnder(linkNode) : "");
  3936.         return true;
  3937.       }
  3938.  
  3939.       return false;
  3940.     case 1:                                                         // if middle button clicked
  3941.       var tab;
  3942.       try {
  3943.         tab = gPrefService.getBoolPref("browser.tabs.opentabfor.middleclick")
  3944.       }
  3945.       catch(ex) {
  3946.         tab = true;
  3947.       }
  3948.       if (tab)
  3949.         openNewTabWith(href, linkNode, event, true);
  3950.       else
  3951.         openNewWindowWith(href, linkNode, true);
  3952.       event.preventBubble();
  3953.       return true;
  3954.   }
  3955.   return false;
  3956. }
  3957.  
  3958. function middleMousePaste(event)
  3959. {
  3960.   var url = readFromClipboard();
  3961.   if (!url)
  3962.     return false;
  3963.   url = getShortcutOrURI(url);
  3964.   if (!url)
  3965.     return false;
  3966.  
  3967.   // On ctrl-middleclick, open in new tab.
  3968.   if (event.ctrlKey)
  3969.     openNewTabWith(url, null, event, true);
  3970.  
  3971.   // If ctrl wasn't down, then just load the url in the current win/tab.
  3972.   loadURI(url);
  3973.   event.preventBubble();
  3974.   return true;
  3975. }
  3976.  
  3977. function makeURLAbsolute( base, url ) 
  3978. {
  3979.   // Construct nsIURL.
  3980.   var ioService = Components.classes["@mozilla.org/network/io-service;1"]
  3981.                 .getService(Components.interfaces.nsIIOService);
  3982.   var baseURI  = ioService.newURI(base, null, null);
  3983.  
  3984.   return ioService.newURI(baseURI.resolve(url), null, null).spec;
  3985. }
  3986.  
  3987. function findParentNode(node, parentNode)
  3988. {
  3989.   if (node && node.nodeType == Node.TEXT_NODE) {
  3990.     node = node.parentNode;
  3991.   }
  3992.   while (node) {
  3993.     var nodeName = node.localName;
  3994.     if (!nodeName)
  3995.       return null;
  3996.     nodeName = nodeName.toLowerCase();
  3997.     if (nodeName == "body" || nodeName == "html" ||
  3998.         nodeName == "#document") {
  3999.       return null;
  4000.     }
  4001.     if (nodeName == parentNode)
  4002.       return node;
  4003.     node = node.parentNode;
  4004.   }
  4005.   return null;
  4006. }
  4007.  
  4008. function saveFrameDocument()
  4009. {
  4010.   var focusedWindow = document.commandDispatcher.focusedWindow;
  4011.   if (isContentFrame(focusedWindow))
  4012.     saveDocument(focusedWindow.document);
  4013. }
  4014.  
  4015. /*
  4016.  * Note that most of this routine has been moved into C++ in order to
  4017.  * be available for all <browser> tags as well as gecko embedding. See
  4018.  * mozilla/content/base/src/nsContentAreaDragDrop.cpp.
  4019.  *
  4020.  * Do not add any new fuctionality here other than what is needed for
  4021.  * a standalone product.
  4022.  */
  4023.  
  4024. var contentAreaDNDObserver = {
  4025.   onDrop: function (aEvent, aXferData, aDragSession)
  4026.     {
  4027.       var url = transferUtils.retrieveURLFromData(aXferData.data, aXferData.flavour.contentType);
  4028.  
  4029.       // valid urls don't contain spaces ' '; if we have a space it isn't a valid url so bail out
  4030.       if (!url || !url.length || url.indexOf(" ", 0) != -1) 
  4031.         return;
  4032.  
  4033.       switch (document.firstChild.getAttribute('windowtype')) {
  4034.         case "navigator:browser":
  4035.           loadURI(getShortcutOrURI(url));
  4036.           break;
  4037.         case "navigator:view-source":
  4038.           viewSource(url);
  4039.           break;
  4040.       }
  4041.       
  4042.       // keep the event from being handled by the dragDrop listeners
  4043.       // built-in to gecko if they happen to be above us.    
  4044.       aEvent.preventDefault();
  4045.     },
  4046.  
  4047.   getSupportedFlavours: function ()
  4048.     {
  4049.       var flavourSet = new FlavourSet();
  4050.       flavourSet.appendFlavour("text/x-moz-url");
  4051.       flavourSet.appendFlavour("text/unicode");
  4052.       flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  4053.       return flavourSet;
  4054.     }
  4055.   
  4056. };
  4057.  
  4058. // For extensions
  4059. function getBrowser()
  4060. {
  4061.   if (!gBrowser)
  4062.     gBrowser = document.getElementById("content");
  4063.   return gBrowser;
  4064. }
  4065.  
  4066. function MultiplexHandler(event)
  4067. { try {
  4068.     var node = event.target;
  4069.     var name = node.getAttribute('name');
  4070.  
  4071.     if (name == 'detectorGroup') {
  4072.         SetForcedDetector(true);
  4073.         SelectDetector(event, false);
  4074.     } else if (name == 'charsetGroup') {
  4075.         var charset = node.getAttribute('id');
  4076.         charset = charset.substring('charset.'.length, charset.length)
  4077.         SetForcedCharset(charset);
  4078.         SetDefaultCharacterSet(charset);
  4079.     } else if (name == 'charsetCustomize') {
  4080.         //do nothing - please remove this else statement, once the charset prefs moves to the pref window
  4081.     } else {
  4082.         SetForcedCharset(node.getAttribute('id'));
  4083.         SetDefaultCharacterSet(node.getAttribute('id'));
  4084.     }
  4085.     } catch(ex) { alert(ex); }
  4086. }
  4087.  
  4088. function SetDefaultCharacterSet(charset)
  4089. {
  4090.     BrowserSetDefaultCharacterSet(charset);
  4091. }
  4092.  
  4093. function SelectDetector(event, doReload)
  4094. {
  4095.     var uri =  event.target.getAttribute("id");
  4096.     var prefvalue = uri.substring('chardet.'.length, uri.length);
  4097.     if ("off" == prefvalue) { // "off" is special value to turn off the detectors
  4098.         prefvalue = "";
  4099.     }
  4100.  
  4101.     try {
  4102.         var pref = Components.classes["@mozilla.org/preferences-service;1"]
  4103.                              .getService(Components.interfaces.nsIPrefBranch);
  4104.         var str =  Components.classes["@mozilla.org/supports-string;1"]
  4105.                              .createInstance(Components.interfaces.nsISupportsString);
  4106.  
  4107.         str.data = prefvalue;
  4108.         pref.setComplexValue("intl.charset.detector",
  4109.                              Components.interfaces.nsISupportsString, str);
  4110.         if (doReload) window._content.location.reload();
  4111.     }
  4112.     catch (ex) {
  4113.         dump("Failed to set the intl.charset.detector preference.\n");
  4114.     }
  4115. }
  4116.  
  4117. function SetForcedDetector(doReload)
  4118. {
  4119.     BrowserSetForcedDetector(doReload);
  4120. }
  4121.  
  4122. function SetForcedCharset(charset)
  4123. {
  4124.     BrowserSetForcedCharacterSet(charset);
  4125. }
  4126.  
  4127. function BrowserSetDefaultCharacterSet(aCharset)
  4128. {
  4129.   // no longer needed; set when setting Force; see bug 79608
  4130. }
  4131.  
  4132. function BrowserSetForcedCharacterSet(aCharset)
  4133. {
  4134.   var docCharset = getBrowser().docShell.QueryInterface(
  4135.                             Components.interfaces.nsIDocCharset);
  4136.   docCharset.charset = aCharset;
  4137.   BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
  4138. }
  4139.  
  4140. function BrowserSetForcedDetector(doReload)
  4141. {
  4142.   getBrowser().documentCharsetInfo.forcedDetector = true;
  4143.   if (doReload)
  4144.     BrowserReloadWithFlags(nsIWebNavigation.LOAD_FLAGS_CHARSET_CHANGE);
  4145. }
  4146.  
  4147. function UpdateCurrentCharset()
  4148. {
  4149.     var menuitem = null;
  4150.  
  4151.     // exctract the charset from DOM
  4152.     var wnd = document.commandDispatcher.focusedWindow;
  4153.     if ((window == wnd) || (wnd == null)) wnd = window._content;
  4154.     menuitem = document.getElementById('charset.' + wnd.document.characterSet);
  4155.  
  4156.     if (menuitem) {
  4157.         // uncheck previously checked item to workaround Mac checkmark problem
  4158.         // bug 98625
  4159.         if (gPrevCharset) {
  4160.             var pref_item = document.getElementById('charset.' + gPrevCharset);
  4161.             if (pref_item)
  4162.               pref_item.setAttribute('checked', 'false');
  4163.         }
  4164.         menuitem.setAttribute('checked', 'true');
  4165.     }
  4166. }
  4167.  
  4168. function UpdateCharsetDetector()
  4169. {
  4170.     var prefvalue;
  4171.  
  4172.     try {
  4173.         var pref = Components.classes["@mozilla.org/preferences-service;1"]
  4174.                              .getService(Components.interfaces.nsIPrefBranch);
  4175.         prefvalue = pref.getComplexValue("intl.charset.detector",
  4176.                                          Components.interfaces.nsIPrefLocalizedString).data;
  4177.     }
  4178.     catch (ex) {
  4179.         prefvalue = "";
  4180.     }
  4181.  
  4182.     if (prefvalue == "") prefvalue = "off";
  4183.     dump("intl.charset.detector = "+ prefvalue + "\n");
  4184.  
  4185.     prefvalue = 'chardet.' + prefvalue;
  4186.     var menuitem = document.getElementById(prefvalue);
  4187.  
  4188.     if (menuitem) {
  4189.         menuitem.setAttribute('checked', 'true');
  4190.     }
  4191. }
  4192.  
  4193. function UpdateMenus(event)
  4194. {
  4195.     // use setTimeout workaround to delay checkmark the menu
  4196.     // when onmenucomplete is ready then use it instead of oncreate
  4197.     // see bug 78290 for the detail
  4198.     UpdateCurrentCharset();
  4199.     setTimeout("UpdateCurrentCharset()", 0);
  4200.     UpdateCharsetDetector();
  4201.     setTimeout("UpdateCharsetDetector()", 0);
  4202. }
  4203.  
  4204. function CreateMenu(node)
  4205. {
  4206.   var observerService = Components.classes["@mozilla.org/observer-service;1"].getService(Components.interfaces.nsIObserverService);
  4207.   observerService.notifyObservers(null, "charsetmenu-selected", node);
  4208. }
  4209.  
  4210. function charsetLoadListener (event)
  4211. {
  4212.     var charset = window._content.document.characterSet;
  4213.  
  4214.     if (charset.length > 0 && (charset != gLastBrowserCharset)) {
  4215.         if (!gCharsetMenu)
  4216.           gCharsetMenu = Components.classes['@mozilla.org/rdf/datasource;1?name=charset-menu'].getService().QueryInterface(Components.interfaces.nsICurrentCharsetListener);
  4217.         gCharsetMenu.SetCurrentCharset(charset);
  4218.         gPrevCharset = gLastBrowserCharset;
  4219.         gLastBrowserCharset = charset;
  4220.     }
  4221. }
  4222.