diff --git a/mozilla/browser/base/resources/content/browser.js b/mozilla/browser/base/resources/content/browser.js index 19234542e6f..62f9baeddb0 100644 --- a/mozilla/browser/base/resources/content/browser.js +++ b/mozilla/browser/base/resources/content/browser.js @@ -20,10 +20,13 @@ * the Initial Developer. All Rights Reserved. * * Contributor(s): - * Blake Ross + * Blake Ross * Peter Annema - * Samir Gehani - * + * Dean Tessman + * Kevin Puetz (puetzk@iastate.edu) + * Ben Goodger + * Pierre Chanial + * Jason Eager * * Alternatively, the contents of this file may be used under the terms of * either the GNU General Public License Version 2 or later (the "GPL"), or @@ -47,10 +50,15 @@ var gProxyDeck = null; var gBookmarksService = null; var gSearchService = null; var gNavigatorBundle; +var gBrandBundle; var gNavigatorRegionBundle; +var gBrandRegionBundle; var gLastValidURLStr = ""; +var gLastValidURL = null; var gHaveUpdatedToolbarState = false; -var gClickSelectsAll = -1; +var gClickSelectsAll = false; +var gIgnoreFocus = false; +var gIgnoreClick = false; var pref = null; @@ -63,6 +71,24 @@ var gBrowser = null; var gFocusedURL = null; var gFocusedDocument = null; +// Global variable that holds the nsContextMenu instance. +var gContextMenu = null; + +// Global variable that caches the default search engine info +var gDefaultEngine = null; + +var gBookmarkPopup = null; + +const nsIWebNavigation = Components.interfaces.nsIWebNavigation; +var gPrintSettingsAreGlobal = true; +var gSavePrintSettings = true; +var gPrintSettings = null; +var gChromeState = null; // chrome state before we went into print preview +var gOldCloseHandler = null; // close handler before we went into print preview +var gInPrintPreviewMode = false; +var gWebProgress = null; + + // Pref listener constants const gButtonPrefListener = { @@ -84,6 +110,12 @@ const gButtonPrefListener = button.setAttribute("hidden","false"); else button.setAttribute("hidden", "true"); + + // If all buttons before the separator are hidden, also hide the separator + if (allLeftButtonsAreHidden()) + document.getElementById("home-bm-separator").setAttribute("hidden", "true"); + else + document.getElementById("home-bm-separator").removeAttribute("hidden"); } }; @@ -97,8 +129,10 @@ const gTabStripPrefListener = return; var stripVisibility = !pref.getBoolPref(prefName); - if (gBrowser.mTabContainer.childNodes.length == 1) + if (gBrowser.mTabContainer.childNodes.length == 1) { gBrowser.setStripVisibilityTo(stripVisibility); + pref.setBoolPref("browser.tabs.forceHide", false); + } } }; @@ -127,156 +161,6 @@ function removePrefListener(observer) } } -function ZoomManager() { -} - -ZoomManager.prototype = { - instance : null, - - getInstance : function() { - if (!ZoomManager.prototype.instance) - ZoomManager.prototype.instance = new ZoomManager(); - - return ZoomManager.prototype.instance; - }, - - MIN : 1, - MAX : 2000, - - zoomFactorsString : "", // cache - zoomFactors : null, - - factorAnchor : 300, - steps : 0, - - get textZoom() { - var currentZoom; - try { - currentZoom = Math.round(getMarkupDocumentViewer().textZoom * 100); - } catch (e) { - currentZoom = 100; - } - return currentZoom; - }, - - set textZoom(aZoom) { - if (aZoom < this.MIN || aZoom > this.MAX) - throw Components.results.NS_ERROR_INVALID_ARG; - - getMarkupDocumentViewer().textZoom = aZoom / 100; - }, - - enlarge : function() { - this.jump(1); - }, - - reduce : function() { - this.jump(-1); - }, - - reset : function() { - this.textZoom = 100; - }, - - getZoomFactors : function() { - this.ensureZoomFactors(); - - return this.zoomFactors; - }, - - indexOf : function(aZoom) { - this.ensureZoomFactors(); - - var index = -1; - if (this.isZoomInRange(aZoom)) { - index = this.zoomFactors.length - 1; - while (index >= 0 && this.zoomFactors[index] != aZoom) - --index; - } - - return index; - }, - - /***** internal helper functions below here *****/ - - ensureZoomFactors : function() { - var zoomFactorsString = gNavigatorBundle.getString("values"); - if (this.zoomFactorsString != zoomFactorsString) { - this.zoomFactorsString = zoomFactorsString; - this.zoomFactors = zoomFactorsString.split(","); - for (var i = 0; i= 0 && aLevel < this.zoomFactors.length); - }, - - isZoomInRange : function(aZoom) { - return (aZoom >= this.zoomFactors[0] && aZoom <= this.zoomFactors[this.zoomFactors.length - 1]); - }, - - jump : function(aDirection) { - if (aDirection != -1 && aDirection != 1) - throw Components.results.NS_ERROR_INVALID_ARG; - - this.ensureZoomFactors(); - - var currentZoom = this.textZoom; - var insertIndex = -1; - var stepFactor = parseFloat(gNavigatorBundle.getString("stepFactor")); - - var factor; - var done = false; - - if (this.isZoomInRange(currentZoom)) { - var index = this.indexOf(currentZoom); - if (aDirection == -1 && index == 0 || - aDirection == 1 && index == this.zoomFactors.length - 1) { - this.steps = 0; - this.factorAnchor = this.zoomFactors[index]; - } else { - factor = this.zoomFactors[index + aDirection]; - done = true; - } - } - - if (!done) { - this.steps += aDirection; - factor = this.factorAnchor * Math.pow(stepFactor, this.steps); - if (factor < this.MIN || factor > this.MAX) { - this.steps -= aDirection; - factor = this.factorAnchor * Math.pow(stepFactor, this.steps); - } - factor = Math.round(factor); - if (this.isZoomInRange(factor)) - factor = this.snap(factor); - } - - if (insertIndex != -1) - this.zoomFactors.splice(insertIndex, 1); - - this.textZoom = factor; - }, - - snap : function(aZoom) { - if (this.isZoomInRange(aZoom)) { - var level = 0; - while (this.zoomFactors[level + 1] < aZoom) - ++level; - - // if aZoom closer to [level + 1] than [level], snap to [level + 1] - if ((this.zoomFactors[level + 1] - aZoom) < (aZoom - this.zoomFactors[level])) - ++level; - - aZoom = this.zoomFactors[level]; - } - - return aZoom; - } -} - /** * We can avoid adding multiple load event listeners and save some time by adding * one listener that calls all real handlers. @@ -344,6 +228,32 @@ function HandleBookmarkIcon(iconURL, addFlag) } } +function UpdateInternetSearchResults(event) +{ + var url = getWebNavigation().currentURI.spec; + if (url) { + try { + var autoOpenSearchPanel = + pref.getBoolPref("browser.search.opensidebarsearchpanel"); + + if (autoOpenSearchPanel || isSearchPanelOpen()) + { + if (!gSearchService) + gSearchService = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"] + .getService(Components.interfaces.nsIInternetSearchService); + + var searchInProgressFlag = gSearchService.FindInternetSearchResults(url); + + if (searchInProgressFlag) { + if (autoOpenSearchPanel) + RevealSearchPanel(); + } + } + } catch (ex) { + } + } +} + function getBrowser() { if (!gBrowser) @@ -394,17 +304,48 @@ function UpdateBackForwardButtons() } } +// Function allLeftButtonsAreHidden +// Returns true if all the buttons left of the separator in the personal +// toolbar are hidden, false otherwise. +// Used by nsButtonPrefListener to hide the separator if needed +function allLeftButtonsAreHidden() +{ + var buttonNode = document.getElementById("PersonalToolbar").firstChild; + while(buttonNode.tagName != "toolbarseparator") { + if(!buttonNode.hasAttribute("hidden") || buttonNode.getAttribute("hidden") == "false") + return false; + buttonNode = buttonNode.nextSibling; + } + return true; +} + +function RegisterTabOpenObserver() +{ + const observer = { + observe: function(subject, topic, data) + { + if (topic != "open-new-tab-request" || subject != window) + return; + + delayedOpenTab(data); + } + }; + + const service = Components.classes["@mozilla.org/observer-service;1"] + .getService(Components.interfaces.nsIObserverService); + service.addObserver(observer, "open-new-tab-request", false); +} + function Startup() { // init globals gNavigatorBundle = document.getElementById("bundle_navigator"); + gBrandBundle = document.getElementById("bundle_brand"); gNavigatorRegionBundle = document.getElementById("bundle_navigator_region"); + gBrandRegionBundle = document.getElementById("bundle_brand_region"); gBrowser = document.getElementById("content"); gURLBar = document.getElementById("urlbar"); - - registerZoomManager(); - utilityOnLoad(); SetPageProxyState("invalid", null); @@ -450,8 +391,9 @@ function Startup() appCore.setWebShellWindow(window); // Add a capturing event listener to the content area + // (rjc note: not the entire window, otherwise we'll get sidebar pane loads too!) // so we'll be notified when onloads complete. - var contentArea = document.getElementById("content"); + var contentArea = document.getElementById("appcontent"); contentArea.addEventListener("load", loadEventHandlers, true); contentArea.addEventListener("focus", contentAreaFrameFocus, true); @@ -469,10 +411,13 @@ function Startup() } } + //initConsoleListener(); + // XXXjag work-around for bug 113076 // there's another bug where we throw an exception when getting // sessionHistory if it is null, which I'm exploiting here to // detect the situation described in bug 113076. + // The same problem caused bug 139522, also worked around below. try { getBrowser().sessionHistory; } catch (e) { @@ -488,10 +433,14 @@ function Startup() var globalHistory = Components.classes["@mozilla.org/browser/global-history;1"] .getService(Components.interfaces.nsIGlobalHistory); getBrowser().docShell.QueryInterface(Components.interfaces.nsIDocShellHistory).globalHistory = globalHistory; + + const selectedBrowser = getBrowser().selectedBrowser; + if (selectedBrowser.securityUI) + selectedBrowser.securityUI.init(selectedBrowser.contentWindow); } // hook up UI through progress listener - getBrowser().addProgressListener(window.XULBrowserWindow); + getBrowser().addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL); // load appropriate initial page from commandline var isPageCycling = false; @@ -510,8 +459,8 @@ function Startup() if (uriToLoad && uriToLoad != "about:blank") { gURLBar.value = uriToLoad; - if ("arguments" in window && window.arguments.length >= 4) { - loadURI(uriToLoad, window.arguments[3]); + if ("arguments" in window && window.arguments.length >= 3) { + loadURI(uriToLoad, window.arguments[2]); } else { loadURI(uriToLoad); } @@ -528,12 +477,12 @@ function Startup() return; } - // Focus the content area if the caller instructed us to. - if ("arguments" in window && window.arguments.length >= 3 && window.arguments[2] == true || - !window.locationbar.visible) - setTimeout(WindowFocusTimerCallback, 0, _content); - else + // Focus the content area unless we're loading a blank page + var navBar = document.getElementById("nav-bar"); + if (uriToLoad == "about:blank" && !navBar.hidden && window.locationbar.visible) setTimeout(WindowFocusTimerCallback, 0, gURLBar); + else + setTimeout(WindowFocusTimerCallback, 0, _content); // Perform default browser checking (after window opens). setTimeout( checkForDefaultBrowser, 0 ); @@ -544,6 +493,8 @@ function Startup() remoteService = Components.classes[XREMOTESERVICE_CONTRACTID] .getService(Components.interfaces.nsIXRemoteService); remoteService.addBrowserInstance(window); + + RegisterTabOpenObserver(); } } @@ -551,9 +502,11 @@ function Startup() // initiated by a web page script addEventListener("fullscreen", onFullScreen, false); + // does clicking on the urlbar select its contents? + gClickSelectsAll = pref.getBoolPref("browser.urlbar.clickSelectsAll"); + // now load bookmarks after a delay setTimeout(LoadBookmarksCallback, 0); - } function LoadBookmarksCallback() @@ -564,7 +517,7 @@ function LoadBookmarksCallback() .getService(Components.interfaces.nsIBookmarksService); gBookmarksService.ReadBookmarks(); // tickle personal toolbar to load personal toolbar items - var personalToolbar = document.getElementById("innermostBox"); + var personalToolbar = document.getElementById("NC:PersonalToolbarFolder"); personalToolbar.builder.rebuild(); } catch (e) { } @@ -623,8 +576,6 @@ function Shutdown() window.XULBrowserWindow = null; BrowserFlushBookmarksAndHistory(); - - utilityOnUnload(); // unregister us as a pref listener removePrefListener(gButtonPrefListener); @@ -636,6 +587,20 @@ function Shutdown() appCore.close(); } +function Translate() +{ + var service = pref.getCharPref("browser.translation.service"); + var serviceDomain = pref.getCharPref("browser.translation.serviceDomain"); + var targetURI = getWebNavigation().currentURI.spec; + + // if we're already viewing a translated page, then just reload + if (targetURI.indexOf(serviceDomain) >= 0) + BrowserReload(); + else { + loadURI(service + escape(targetURI)); + } +} + function gotoHistoryIndex(aEvent) { var index = aEvent.target.getAttribute("index"); @@ -717,7 +682,7 @@ function OpenBookmarkGroup(element, datasource) var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"] .getService(Components.interfaces.nsIRDFService); var resource = rdf.GetResource(id, true); - return OpenBookmarkGroupFromResource(resource, datasource, rdf); + OpenBookmarkGroupFromResource(resource, datasource, rdf); } function OpenBookmarkGroupFromResource(resource, datasource, rdf) { @@ -728,16 +693,12 @@ function OpenBookmarkGroupFromResource(resource, datasource, rdf) { var tabPanels = gBrowser.mPanelContainer.childNodes; var tabCount = tabPanels.length; var index = 0; - while (containerChildren.hasMoreElements()) { - var resource = containerChildren.getNext().QueryInterface(Components.interfaces.nsIRDFResource); - var target = datasource.GetTarget(resource, urlResource, true); + for (; containerChildren.hasMoreElements(); ++index) { + var res = containerChildren.getNext().QueryInterface(Components.interfaces.nsIRDFResource); + var target = datasource.GetTarget(res, urlResource, true); if (target) { var uri = target.QueryInterface(Components.interfaces.nsIRDFLiteral).Value; - if (index < tabCount) - tabPanels[index].loadURI(uri, null, nsIWebNavigation.LOAD_FLAGS_NONE); - else - gBrowser.addTab(uri); - index++; + gBrowser.addTab(uri); } } @@ -746,11 +707,7 @@ function OpenBookmarkGroupFromResource(resource, datasource, rdf) { // Select the first tab in the group. var tabs = gBrowser.mTabContainer.childNodes; - gBrowser.selectedTab = tabs[0]; - - // Close any remaining open tabs that are left over. - for (var i = tabCount-1; i >= index; i--) - gBrowser.removeTab(tabs[i]); + gBrowser.selectedTab = tabs[tabCount]; } function OpenBookmarkURL(node, datasources) @@ -795,6 +752,26 @@ function OpenBookmarkURL(node, datasources) openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", url); } +function addBookmarkAs() +{ + const browsers = gBrowser.browsers; + if (browsers.length > 1) + BookmarksUtils.addBookmarkForTabBrowser(gBrowser); + else + BookmarksUtils.addBookmarkForBrowser(gBrowser.webNavigation, true); +} + +function addGroupmarkAs() +{ + BookmarksUtils.addBookmarkForTabBrowser(gBrowser, true); +} + +function updateGroupmarkMenuitem(id) +{ + const disabled = gBrowser.browsers.length == 1; + document.getElementById(id).setAttribute("disabled", disabled); +} + function readRDFString(aDS,aRes,aProp) { var n = aDS.GetTarget(aRes, aProp, true); @@ -824,7 +801,8 @@ function ensureSearchPref() var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var ds = rdf.GetDataSource("rdf:internetsearch"); var mPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); - kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name"); + var kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name"); + var defaultEngine; try { defaultEngine = mPrefs.getCharPref("browser.search.defaultengine"); } catch(ex) { @@ -847,11 +825,21 @@ function getSearchUrl(attr) return searchURL; } +function QualifySearchTerm() +{ + // If the text in the URL bar is the same as the currently loaded + // page's URL then treat this as an empty search term. This way + // the user is taken to the search page where s/he can enter a term. + if (window.XULBrowserWindow.userTyped.value) + return document.getElementById("urlbar").value; + return ""; +} function OpenSearch(tabName, forceDialogFlag, searchStr, newWindowFlag) { //This function needs to be split up someday. + var autoOpenSearchPanel = false; var defaultSearchURL = null; var fallbackDefaultSearchURL = gNavigatorRegionBundle.getString("fallbackDefaultSearchURL"); ensureSearchPref() @@ -862,6 +850,7 @@ function OpenSearch(tabName, forceDialogFlag, searchStr, newWindowFlag) var forceAsURL = urlmatch.test(searchStr); try { + autoOpenSearchPanel = pref.getBoolPref("browser.search.opensidebarsearchpanel"); defaultSearchURL = pref.getComplexValue("browser.search.defaulturl", Components.interfaces.nsIPrefLocalizedString).data; } catch (ex) { @@ -872,7 +861,7 @@ function OpenSearch(tabName, forceDialogFlag, searchStr, newWindowFlag) defaultSearchURL = fallbackDefaultSearchURL; if (!searchStr) { - loadURI(gNavigatorRegionBundle.getString("otherSearchURL")); + BrowserSearchInternet(); } else { //Check to see if location bar field is a url @@ -889,7 +878,7 @@ function OpenSearch(tabName, forceDialogFlag, searchStr, newWindowFlag) if (forceDialogFlag || searchMode == 1) { // Use a single search dialog - var windowManager = Components.classes["@mozilla.org/rdf/datasource;1?name=window-mediator"] + var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"] .getService(Components.interfaces.nsIWindowMediator); var searchWindow = windowManager.getMostRecentWindow("search:window"); @@ -933,12 +922,81 @@ function OpenSearch(tabName, forceDialogFlag, searchStr, newWindowFlag) } } } + + // should we try and open up the sidebar to show the "Search Results" panel? + if (autoOpenSearchPanel) + RevealSearchPanel(); +} + +function RevealSearchPanel() +{ + var searchPanel = document.getElementById("urn:sidebar:panel:search"); + if (searchPanel) + SidebarSelectPanel(searchPanel, true, true); // lives in sidebarOverlay.js +} + +function isSearchPanelOpen() +{ + return ( !sidebar_is_hidden() && + !sidebar_is_collapsed() && + SidebarGetLastSelectedPanel() == "urn:sidebar:panel:search" + ); +} + +function BrowserSearchInternet() +{ + try { + var searchEngineURI = pref.getCharPref("browser.search.defaultengine"); + if (searchEngineURI) { + var searchRoot = getSearchUrl("searchForm"); + if (searchRoot) { + loadURI(searchRoot); + return; + } else { + // Get a search URL and guess that the front page of the site has a search form. + var searchDS = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"] + .getService(Components.interfaces.nsIInternetSearchService); + searchURL = searchDS.GetInternetSearchURL(searchEngineURI, "ABC", 0, 0, {value:0}); + if (searchURL) { + searchRoot = searchURL.match(/[a-z]+:\/\/[a-z.-]+/); + if (searchRoot) { + loadURI(searchRoot + "/"); + return; + } + } + } + } + } catch (ex) { + } + + // Fallback if the stuff above fails: use the hard-coded search engine + loadURI(gNavigatorRegionBundle.getString("otherSearchURL")); +} + + +//Note: BrowserNewEditorWindow() was moved to globalOverlay.xul and renamed to NewEditorWindow() + +function BrowserOpenWindow() +{ + //opens a window where users can select a web location to open + openDialog("chrome://communicator/content/openLocation.xul", "_blank", "chrome,modal,titlebar", window); } function BrowserOpenTab() { - gBrowser.selectedTab = gBrowser.addTab('about:blank'); - setTimeout("gURLBar.focus();", 0); + if (!gInPrintPreviewMode) { + gBrowser.selectedTab = gBrowser.addTab('about:blank'); + setTimeout("gURLBar.focus();", 0); + } +} + +/* Called from the openLocation dialog. This allows that dialog to instruct + its opener to open a new window and then step completely out of the way. + Anything less byzantine is causing horrible crashes, rather believably, + though oddly only on Linux. */ +function delayedOpenWindow(chrome,flags,url) +{ + setTimeout("openDialog('"+chrome+"','_blank','"+flags+"','"+url+"')", 10); } /* Required because the tab needs time to set up its content viewers and get the load of @@ -964,10 +1022,34 @@ function BrowserOpenFileWindow() } } +// Set up a lame hack to avoid opening two bookmarks. +// Could otherwise happen with two Ctrl-B's in a row. +var gDisableBookmarks = false; +function enableBookmarks() +{ + gDisableBookmarks = false; +} + function BrowserEditBookmarks() { - openDialog("chrome://communicator/content/bookmarks/bookmarks.xul", "Bookmarks", - "chrome,all,dialog=no"); + // Use a single sidebar bookmarks dialog + var windowManager = Components.classes["@mozilla.org/appshell/window-mediator;1"] + .getService(Components.interfaces.nsIWindowMediator); + + var bookmarksWindow = windowManager.getMostRecentWindow("bookmarks:manager"); + + if (bookmarksWindow) { + bookmarksWindow.focus(); + } else { + // while disabled, don't open new bookmarks window + if (!gDisableBookmarks) { + gDisableBookmarks = true; + + open("chrome://communicator/content/bookmarks/bookmarks.xul", "_blank", + "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar"); + setTimeout(enableBookmarks, 2000); + } + } } function BrowserCloseTabOrWindow() @@ -1018,7 +1100,7 @@ function BrowserLoadURL(aTriggeringEvent) { var url = gURLBar.value; if (url.match(/^view-source:/)) { - BrowserViewSourceOfURL(url.replace(/^view-source:/, ""), null); + BrowserViewSourceOfURL(url.replace(/^view-source:/, ""), null, null); } else { if (pref && pref.getBoolPref("browser.tabs.opentabfor.urlbar") && getBrowser().localName == "tabbrowser" && @@ -1098,6 +1180,18 @@ function readFromClipboard() return url; } +function OpenMessenger() +{ + open("chrome://messenger/content/messenger.xul", "_blank", + "chrome,extrachrome,menubar,resizable,status,toolbar"); +} + +function OpenAddressbook() +{ + open("chrome://messenger/content/addressbook/addressbook.xul", "_blank", + "chrome,extrachrome,menubar,resizable,status,toolbar"); +} + function BrowserViewSourceOfDocument(aDocument) { var docCharset; @@ -1144,24 +1238,88 @@ function BrowserViewSourceOfDocument(aDocument) BrowserViewSourceOfURL(webNav.currentURI.spec, docCharset, pageCookie); } -function BrowserViewSourceOfURL(url, charset) +function BrowserViewSourceOfURL(url, charset, pageCookie) { // try to open a view-source window while inheriting the charset (if any) - openDialog("chrome://browser/content/viewSource.xul", + openDialog("chrome://navigator/content/viewSource.xul", "_blank", "scrollbars,resizable,chrome,dialog=no", - url, charset); + url, charset, pageCookie); } // doc=null for regular page info, doc=owner document for frame info. function BrowserPageInfo(doc) { - window.openDialog("chrome://browser/content/pageInfo.xul", + window.openDialog("chrome://navigator/content/pageInfo.xul", "_blank", "chrome,dialog=no", doc); } +function hiddenWindowStartup() +{ + // focus the hidden window + window.focus(); + + // Disable menus which are not appropriate + var disabledItems = ['cmd_close', 'Browser:SendPage', 'Browser:EditPage', 'Browser:PrintSetup', /*'Browser:PrintPreview',*/ + 'Browser:Print', 'canGoBack', 'canGoForward', 'Browser:Home', 'Browser:AddBookmark', 'cmd_undo', + 'cmd_redo', 'cmd_cut', 'cmd_copy','cmd_paste', 'cmd_delete', 'cmd_selectAll', 'menu_textZoom']; + for (var id in disabledItems) { + var broadcaster = document.getElementById(disabledItems[id]); + if (broadcaster) + broadcaster.setAttribute("disabled", "true"); + } +} + +// Initialize the LeakDetector class. +function LeakDetector(verbose) +{ + this.verbose = verbose; +} + +const NS_LEAKDETECTOR_CONTRACTID = "@mozilla.org/xpcom/leakdetector;1"; + +if (NS_LEAKDETECTOR_CONTRACTID in Components.classes) { + try { + LeakDetector.prototype = Components.classes[NS_LEAKDETECTOR_CONTRACTID] + .createInstance(Components.interfaces.nsILeakDetector); + } catch (err) { + LeakDetector.prototype = Object.prototype; + } +} else { + LeakDetector.prototype = Object.prototype; +} + +var leakDetector = new LeakDetector(false); + +// Dumps current set of memory leaks. +function dumpMemoryLeaks() +{ + leakDetector.dumpLeaks(); +} + +// Traces all objects reachable from the chrome document. +function traceChrome() +{ + leakDetector.traceObject(document, leakDetector.verbose); +} + +// Traces all objects reachable from the content document. +function traceDocument() +{ + // keep the chrome document out of the dump. + leakDetector.markObject(document, true); + leakDetector.traceObject(_content, leakDetector.verbose); + leakDetector.markObject(document, false); +} + +// Controls whether or not we do verbose tracing. +function traceVerbose(verbose) +{ + leakDetector.verbose = (verbose == "true"); +} + var consoleListener = { observe: function (aMsgObject) { @@ -1346,28 +1504,103 @@ function stylesheetSwitchAll(frameset, title) { } } +function applyTheme(themeName) +{ + var id = themeName.getAttribute('id'); + var name=id.substring('urn:mozilla.skin.'.length, id.length); + if (!name) + return; + + var chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); + + var oldTheme = false; + try { + oldTheme = !chromeRegistry.checkThemeVersion(name); + } + catch(e) { + } + + var str = Components.classes["@mozilla.org/supports-wstring;1"] + .createInstance(Components.interfaces.nsISupportsWString); + + var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); + if (oldTheme) { + var title = gNavigatorBundle.getString("oldthemetitle"); + var message = gNavigatorBundle.getString("oldTheme"); + + message = message.replace(/%theme_name%/, themeName.getAttribute("displayName")); + message = message.replace(/%brand%/g, gBrandBundle.getString("brandShortName")); + + if (promptService.confirm(window, title, message)){ + var inUse = chromeRegistry.isSkinSelected(name, true); + + chromeRegistry.uninstallSkin( name, true ); + // XXX - this sucks and should only be temporary. + + str.data = true; + pref.setComplexValue("general.skins.removelist." + name, + Components.interfaces.nsISupportsWString, str); + + if (inUse) + chromeRegistry.refreshSkins(); + } + + return; + } + + // XXX XXX BAD BAD BAD BAD !! XXX XXX + // we STILL haven't fixed editor skin switch problems + // hacking around it yet again + + str.data = name; + pref.setComplexValue("general.skins.selectedSkin", Components.interfaces.nsISupportsWString, str); + + // shut down quicklaunch so the next launch will have the new skin + var appShell = Components.classes['@mozilla.org/appshell/appShellService;1'].getService(); + appShell = appShell.QueryInterface(Components.interfaces.nsIAppShellService); + try { + appShell.nativeAppSupport.isServerMode = false; + } + catch(ex) { + } + + if (promptService) { + var dialogTitle = gNavigatorBundle.getString("switchskinstitle"); + var brandName = gBrandBundle.getString("brandShortName"); + var msg = gNavigatorBundle.getFormattedString("switchskins", [brandName]); + promptService.alert(window, dialogTitle, msg); + } +} + +function getNewThemes() +{ + loadURI(gBrandRegionBundle.getString("getNewThemesURL")); +} + function URLBarFocusHandler(aEvent) { - if (gURLBar) { - if (gClickSelectsAll == -1) - gClickSelectsAll = pref.getBoolPref("browser.urlbar.clickSelectsAll"); - if (gClickSelectsAll) - gURLBar.setSelectionRange(0, gURLBar.textLength); - } + if (gIgnoreFocus) + gIgnoreFocus = false; + else if (gClickSelectsAll) + gURLBar.select(); } -function URLBarBlurHandler(aEvent) +function URLBarMouseDownHandler(aEvent) { - // XXX why the hell do we have to do this? - if (gClickSelectsAll) + if (gURLBar.hasAttribute("focused")) { + gIgnoreClick = true; + } else { + gIgnoreFocus = true; + gIgnoreClick = false; gURLBar.setSelectionRange(0, 0); + } } -function URLBarKeyupHandler(aEvent) +function URLBarClickHandler(aEvent) { - if (aEvent.keyCode == aEvent.DOM_VK_TAB ) { - ShowAndSelectContentsOfURLBar(); - } + if (!gIgnoreClick && gClickSelectsAll && gURLBar.selectionStart == gURLBar.selectionEnd) + gURLBar.select(); } // This function gets the "windows hooks" service and has it check its setting @@ -1383,16 +1616,23 @@ function checkForDefaultBrowser() .checkSettings(window); } catch(e) { } + + if (dialogShown) + { + // Force the sidebar to build since the windows + // integration dialog may have come up. + SidebarRebuild(); + } } } function ShowAndSelectContentsOfURLBar() { - var navBar = document.getElementById("LocationToolbar"); + var navBar = document.getElementById("nav-bar"); // If it's hidden, show it. if (navBar.getAttribute("hidden") == "true") - goToggleToolbar('LocationToolbar','cmd_viewlocationbar'); + goToggleToolbar('nav-bar','cmd_viewnavbar'); if (gURLBar.value) gURLBar.select(); @@ -1485,29 +1725,63 @@ function PageProxyDragGesture(aEvent) return false; } +function updateComponentBarBroadcaster() +{ + var compBarBroadcaster = document.getElementById('cmd_viewcomponentbar'); + var taskBarBroadcaster = document.getElementById('cmd_viewtaskbar'); + var compBar = document.getElementById('component-bar'); + if (taskBarBroadcaster.getAttribute('checked') == 'true') { + compBarBroadcaster.removeAttribute('disabled'); + if (compBar.getAttribute('hidden') != 'true') + compBarBroadcaster.setAttribute('checked', 'true'); + } + else { + compBarBroadcaster.setAttribute('disabled', 'true'); + compBarBroadcaster.removeAttribute('checked'); + } +} + function updateToolbarStates(toolbarMenuElt) { - if (gHaveUpdatedToolbarState) - return; - - var mainWindow = document.getElementById("main-window"); - if (mainWindow.hasAttribute("chromehidden")) { - gHaveUpdatedToolbarState = true; - var i; - for (i = 0; i < toolbarMenuElt.childNodes.length; ++i) - document.getElementById(toolbarMenuElt.childNodes[i].getAttribute("observes")).removeAttribute("checked"); - var toolbars = document.getElementsByTagName("toolbar"); - for (i = 0; i < toolbars.length; ++i) { - if (toolbars[i].getAttribute("class").indexOf("chromeclass") != -1) - toolbars[i].setAttribute("hidden", "true"); + if (!gHaveUpdatedToolbarState) { + var mainWindow = document.getElementById("main-window"); + if (mainWindow.hasAttribute("chromehidden")) { + gHaveUpdatedToolbarState = true; + var i; + for (i = 0; i < toolbarMenuElt.childNodes.length; ++i) + document.getElementById(toolbarMenuElt.childNodes[i].getAttribute("observes")).removeAttribute("checked"); + var toolbars = document.getElementsByTagName("toolbar"); + for (i = 0; i < toolbars.length; ++i) { + if (toolbars[i].getAttribute("class").indexOf("chromeclass") != -1) + toolbars[i].setAttribute("hidden", "true"); + } + var statusbars = document.getElementsByTagName("statusbar"); + for (i = 0; i < statusbars.length; ++i) { + if (statusbars[i].getAttribute("class").indexOf("chromeclass") != -1) + statusbars[i].setAttribute("hidden", "true"); + } + mainWindow.removeAttribute("chromehidden"); } - var statusbars = document.getElementsByTagName("statusbar"); - for (i = 0; i < statusbars.length; ++i) { - if (statusbars[i].getAttribute("class").indexOf("chromeclass") != -1) - statusbars[i].setAttribute("hidden", "true"); - } - mainWindow.removeAttribute("chromehidden"); } + updateComponentBarBroadcaster(); + + const tabbarMenuItem = document.getElementById("menuitem_showhide_tabbar"); + // Make show/hide menu item reflect current state + const visibility = gBrowser.getStripVisibility(); + tabbarMenuItem.setAttribute("checked", visibility); + + // Don't allow the tab bar to be shown/hidden when more than one tab is open + // or when we have 1 tab and the autoHide pref is set + const disabled = gBrowser.browsers.length > 1 || + pref.getBoolPref("browser.tabs.autoHide"); + tabbarMenuItem.setAttribute("disabled", disabled); +} + +function showHideTabbar() +{ + const visibility = gBrowser.getStripVisibility(); + pref.setBoolPref("browser.tabs.forceHide", visibility); + gBrowser.setStripVisibilityTo(!visibility); } // Fill in tooltips for personal toolbar @@ -1552,158 +1826,61 @@ function onFullScreen() FullScreen.toggle(); } -function displayPageInfo() -{ - window.openDialog("chrome://navigator/content/pageInfo.xul", "_blank", - "dialog=no", null, "securityTab"); -} - -/** Document Zoom Management Code - * - * To use this, you'll need to have a - * and a getMarkupDocumentViewer() function which returns a - * nsIMarkupDocumentViewer. - * - **/ - -function registerZoomManager() -{ - var textZoomMenu = document.getElementById("menu_textZoom"); - var zoom = ZoomManager.prototype.getInstance(); - - var parentMenu = textZoomMenu.parentNode; - parentMenu.addEventListener("popupshowing", updateViewMenu, false); - - var popup = document.getElementById("menu_textZoomPopup"); - var accessKeys = gNavigatorBundle.getString("accessKeys").split(","); - var zoomFactors = zoom.getZoomFactors(); - for (var i = 0; i < zoomFactors.length; ++i) { - var menuItem = document.createElement("menuitem"); - menuItem.setAttribute("type", "radio"); - menuItem.setAttribute("name", "textZoom"); - - var label; - if (zoomFactors[i] == 100) - label = gNavigatorBundle.getString("labelOriginal"); - else - label = gNavigatorBundle.getString("label"); - - menuItem.setAttribute("label", label.replace(/%zoom%/, zoomFactors[i])); - menuItem.setAttribute("accesskey", accessKeys[i]); - menuItem.setAttribute("oncommand", "ZoomManager.prototype.getInstance().textZoom = this.value;"); - menuItem.setAttribute("value", zoomFactors[i]); - popup.appendChild(menuItem); - } -} - -function updateViewMenu() -{ - var zoom = ZoomManager.prototype.getInstance(); - - var textZoomMenu = document.getElementById("menu_textZoom"); - var menuLabel = gNavigatorBundle.getString("menuLabel").replace(/%zoom%/, zoom.textZoom); - textZoomMenu.setAttribute("label", menuLabel); -} - -function updateTextZoomMenu() -{ - var zoom = ZoomManager.prototype.getInstance(); - - var currentZoom = zoom.textZoom; - - var popup = document.getElementById("menu_textZoomPopup"); - var item = popup.firstChild; - while (item) { - if (item.getAttribute("name") == "textZoom") { - if (item.getAttribute("value") == currentZoom) - item.setAttribute("checked","true"); - else - item.removeAttribute("checked"); - } - item = item.nextSibling; - } +// Set up a lame hack to avoid opening two bookmarks. +// Could otherwise happen with two Ctrl-B's in a row. +var gDisableHistory = false; +function enableHistory() { + gDisableHistory = false; } function toHistory() { - openDialog("chrome://communicator/content/history/history.xul", "History", - "chrome,all,dialog=no" ); -} + // Use a single sidebar history dialog -function toDownloadManager() -{ - var dlmgr = Components.classes['@mozilla.org/download-manager;1'].getService(); - dlmgr = dlmgr.QueryInterface(Components.interfaces.nsIDownloadManager); - dlmgr.open(window); -} - -function toJavaScriptConsole() -{ - openDialog("chrome://global/content/console.xul", "JSConsole", - "chrome,all,dialog=no" ); -} + var cwindowManager = Components.classes['@mozilla.org/appshell/window-mediator;1'].getService(); + var iwindowManager = Components.interfaces.nsIWindowMediator; + var windowManager = cwindowManager.QueryInterface(iwindowManager); -function javaItemEnabling() -{ - var element = document.getElementById("java"); - if (navigator.javaEnabled()) - element.removeAttribute("hidden"); - else - element.setAttribute("hidden", "true"); -} - -function toJavaConsole() -{ - var jvmMgr = Components.classes['@mozilla.org/oji/jvm-mgr;1'] - .getService(Components.interfaces.nsIJVMManager) - jvmMgr.showJavaConsole(); -} + var historyWindow = windowManager.getMostRecentWindow('history:manager'); -function toOpenWindowByType( inType, uri ) -{ - var windowManager = Components.classes['@mozilla.org/rdf/datasource;1?name=window-mediator'].getService(); + if (historyWindow) { + //debug("Reuse existing history window"); + historyWindow.focus(); + } else { + //debug("Open a new history dialog"); - var windowManagerInterface = windowManager.QueryInterface( Components.interfaces.nsIWindowMediator); + if (true == gDisableHistory) { + //debug("Recently opened one. Wait a little bit."); + return; + } + gDisableHistory = true; - var topWindow = windowManagerInterface.getMostRecentWindow( inType ); - - if ( topWindow ) - topWindow.focus(); - else - window.open(uri, "_blank", "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar"); -} - -function OpenBrowserWindow() -{ - var charsetArg = new String(); - var handler = Components.classes['@mozilla.org/commandlinehandler/general-startup;1?type=browser']; - handler = handler.getService(); - handler = handler.QueryInterface(Components.interfaces.nsICmdLineHandler); - var startpage = handler.defaultArgs; - const url = "chrome://browser/content/browser.xul"; - var wintype = document.firstChild.getAttribute('windowtype'); - - // if and only if the current window is a browser window and it has a document with a character - // set, then extract the current charset menu setting from the current document and use it to - // initialize the new browser window... - if (window && (wintype == "navigator:browser") && window._content && window._content.document) - { - var DocCharset = window._content.document.characterSet; - charsetArg = "charset="+DocCharset; - - //we should "inherit" the charset menu setting in a new window - window.openDialog(url, "_blank", "chrome,all,dialog=no", startpage, charsetArg); - } - else // forget about the charset information. - { - window.openDialog(url, "_blank", "chrome,all,dialog=no", startpage); + window.open( "chrome://communicator/content/history/history.xul", "_blank", + "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar" ); + setTimeout(enableHistory, 2000); } + } -const nsIWebNavigation = Components.interfaces.nsIWebNavigation; -var gPrintSettings = null; -var gChromeState = null; // chrome state before we went into print preview -var gOldCloseHandler = null; // close handler before we went into print preview +function checkTheme() +{ + var theSkinKids = document.getElementById("theme"); + var chromeRegistry = Components.classes["@mozilla.org/chrome/chrome-registry;1"] + .getService(Components.interfaces.nsIXULChromeRegistry); + for (var i = 0; i < theSkinKids.childNodes.length; ++i) { + var child = theSkinKids.childNodes[i]; + var id=child.getAttribute("id"); + if (id.length > 0) { + var themeName = id.substring('urn:mozilla:skin:'.length, id.length); + var selected = chromeRegistry.isSkinSelected(themeName, true); + if (selected == Components.interfaces.nsIChromeRegistry.FULL) { + var menuitem=document.getElementById(id); + menuitem.setAttribute("checked", true); + break; + } + } + } +} function getWebNavigation() { @@ -1743,42 +1920,52 @@ function toggleAffectedChrome(aHide) // (*) navigation bar // (*) personal toolbar // (*) tab browser ``strip'' + // (*) sidebar if (!gChromeState) gChromeState = new Object; - var chrome = new Array; - var i = 0; - chrome[i++] = document.getElementById("main-menubar"); - chrome[i++] = document.getElementById("nav-bar"); - chrome[i++] = document.getElementById("LocationToolbar"); - chrome[i++] = document.getElementById("PersonalToolbar"); - chrome[i++] = document.getElementById("status-bar"); - - // now that we've figured out which elements we're interested, toggle 'em - for (i = 0; i < chrome.length; ++i) - { - if (aHide) - chrome[i].hidden = true; - else - chrome[i].hidden = false; - } - - // now deal with the tab browser ``strip'' + var navToolbox = document.getElementById("navigator-toolbox"); + navToolbox.hidden = aHide; var theTabbrowser = document.getElementById("content"); - if (aHide) // normal mode -> print preview + + // sidebar states map as follows: + // was-hidden => hide/show nothing + // was-collapsed => hide/show only the splitter + // was-shown => hide/show the splitter and the box + if (aHide) { + // going into print preview mode + if (sidebar_is_collapsed()) + { + gChromeState.sidebar = "was-collapsed"; + } + else if (sidebar_is_hidden()) + gChromeState.sidebar = "was-hidden"; + else + { + gChromeState.sidebar = "was-visible"; + } + document.getElementById("sidebar-box").hidden = true; + document.getElementById("sidebar-splitter").hidden = true; + //deal with tab browser gChromeState.hadTabStrip = theTabbrowser.getStripVisibility(); theTabbrowser.setStripVisibilityTo(false); } - else // print preview -> normal mode + else { - // tabs were showing before entering print preview - if (gChromeState.hadTabStrip) - { - theTabbrowser.setStripVisibilityTo(true); - gChromeState.hadTabStrip = false; // reset - } + // restoring normal mode (i.e., leaving print preview mode) + //restore tab browser + theTabbrowser.setStripVisibilityTo(gChromeState.hadTabStrip); + if (gChromeState.sidebar == "was-collapsed" || + gChromeState.sidebar == "was-visible") + document.getElementById("sidebar-splitter").hidden = false; + if (gChromeState.sidebar == "was-visible") + document.getElementById("sidebar-box").hidden = false; } + + // if we are unhiding and sidebar used to be there rebuild it + if (!aHide && gChromeState.sidebar == "was-visible") + SidebarRebuild(); } function showPrintPreviewToolbar() @@ -1790,12 +1977,18 @@ function showPrintPreviewToolbar() var printPreviewTB = document.createElementNS(kXULNS, "toolbar"); printPreviewTB.setAttribute("printpreview", true); printPreviewTB.setAttribute("id", "print-preview-toolbar"); - var navTB = document.getElementById("nav-bar"); - navTB.parentNode.appendChild(printPreviewTB); + + var navToolbox = document.getElementById("navigator-toolbox"); + navToolbox.parentNode.insertBefore(printPreviewTB, navToolbox); } function BrowserExitPrintPreview() { + gInPrintPreviewMode = false; + + var browser = getBrowser(); + browser.setAttribute("handleCtrlPageUpDown", "true"); + // exit print preview galley mode in content area var ifreq = _content.QueryInterface( Components.interfaces.nsIInterfaceRequestor); @@ -1805,9 +1998,9 @@ function BrowserExitPrintPreview() _content.focus(); // remove the print preview toolbar - var navTB = document.getElementById("nav-bar"); + var navToolbox = document.getElementById("navigator-toolbox"); var printPreviewTB = document.getElementById("print-preview-toolbar"); - navTB.parentNode.removeChild(printPreviewTB); + navToolbox.parentNode.removeChild(printPreviewTB); // restore chrome to original state toggleAffectedChrome(false); @@ -1817,23 +2010,28 @@ function BrowserExitPrintPreview() mainWin.setAttribute("onclose", gOldCloseHandler); } -function GetPrintSettings(webBrowserPrint) +function GetPrintSettings() { var prevPS = gPrintSettings; try { if (gPrintSettings == null) { - var useGlobalPrintSettings = true; var pref = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefBranch); if (pref) { - useGlobalPrintSettings = pref.getBoolPref("print.use_global_printsettings", false); + gPrintSettingsAreGlobal = pref.getBoolPref("print.use_global_printsettings", false); + gSavePrintSettings = pref.getBoolPref("print.save_print_settings", false); } - if (useGlobalPrintSettings) { - gPrintSettings = webBrowserPrint.globalPrintSettings; + var psService = Components.classes["@mozilla.org/gfx/printsettings-service;1"] + .getService(Components.interfaces.nsIPrintSettingsService); + if (gPrintSettingsAreGlobal) { + gPrintSettings = psService.globalPrintSettings; + if (gSavePrintSettings) { + psService.initPrintSettingsFromPrefs(gPrintSettings, false, gPrintSettings.kInitSaveNativeData); + } } else { - gPrintSettings = webBrowserPrint.newPrintSettings; + gPrintSettings = psService.newPrintSettings; } } } catch (e) { @@ -1843,26 +2041,97 @@ function GetPrintSettings(webBrowserPrint) return gPrintSettings; } +// This observer is called once the progress dialog has been "opened" +var gPrintPreviewObs = { + observe: function(aSubject, aTopic, aData) + { + setTimeout(FinishPrintPreview, 0); + }, + + QueryInterface : function(iid) + { + if (iid.equals(Components.interfaces.nsIObserver) || iid.equals(Components.interfaces.nsISupportsWeakReference)) + return this; + + throw Components.results.NS_NOINTERFACE; + } +}; + function BrowserPrintPreview() { - var mainWin = document.getElementById("main-window"); - - // save previous close handler to restoreon exiting print preview mode - if (mainWin.hasAttribute("onclose")) - gOldCloseHandler = mainWin.getAttribute("onclose"); - else - gOldCloseHandler = null; - mainWin.setAttribute("onclose", "BrowserExitPrintPreview(); return false;"); - + var ifreq; + var webBrowserPrint; try { - var ifreq = _content.QueryInterface( - Components.interfaces.nsIInterfaceRequestor); - var webBrowserPrint = ifreq.getInterface( - Components.interfaces.nsIWebBrowserPrint); - if (webBrowserPrint) { - gPrintSettings = GetPrintSettings(webBrowserPrint); - webBrowserPrint.printPreview(gPrintSettings); + ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor); + webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint); + gPrintSettings = GetPrintSettings(); + + } catch (e) { + // Pressing cancel is expressed as an NS_ERROR_ABORT return value, + // causing an exception to be thrown which we catch here. + // Unfortunately this will also consume helpful failures, so add a + // dump(e); // if you need to debug + } + + // Here we get the PrintingPromptService tso we can display the PP Progress from script + // For the browser implemented via XUL with the PP toolbar we cannot let it be + // automatically opened from the print engine because the XUL scrollbars in the PP window + // will layout before the content window and a crash will occur. + // + // Doing it all from script, means it lays out before hand and we can let printing do it's own thing + gWebProgress = new Object(); + + var printPreviewParams = new Object(); + var notifyOnOpen = new Object(); + var printingPromptService = Components.classes["@mozilla.org/embedcomp/printingprompt-service;1"] + .getService(Components.interfaces.nsIPrintingPromptService); + if (printingPromptService) { + // just in case we are already printing, + // an error code could be returned if the Prgress Dialog is already displayed + try { + printingPromptService.showProgress(this, webBrowserPrint, gPrintSettings, gPrintPreviewObs, false, gWebProgress, + printPreviewParams, notifyOnOpen); + if (printPreviewParams.value) { + var webNav = getWebNavigation(); + printPreviewParams.value.docTitle = webNav.document.title; + printPreviewParams.value.docURL = webNav.currentURI.spec; + } + + // this tells us whether we should continue on with PP or + // wait for the callback via the observer + if (!notifyOnOpen.value.valueOf() || gWebProgress.value == null) { + FinishPrintPreview(); + } + } catch (e) { + FinishPrintPreview(); } + } +} + +function FinishPrintPreview() +{ + gInPrintPreviewMode = true; + + var browser = getBrowser(); + try { + var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor); + var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint); + if (webBrowserPrint) { + gPrintSettings = GetPrintSettings(); + webBrowserPrint.printPreview(gPrintSettings, null, gWebProgress.value); + } + + browser.setAttribute("handleCtrlPageUpDown", "false"); + + var mainWin = document.getElementById("main-window"); + + // save previous close handler to restoreon exiting print preview mode + if (mainWin.hasAttribute("onclose")) + gOldCloseHandler = mainWin.getAttribute("onclose"); + else + gOldCloseHandler = null; + mainWin.setAttribute("onclose", "BrowserExitPrintPreview(); return false;"); + // show the toolbar after we go into print preview mode so // that we can initialize the toolbar with total num pages showPrintPreviewToolbar(); @@ -1879,25 +2148,29 @@ function BrowserPrintPreview() function BrowserPrintSetup() { - + var didOK = false; try { var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor); var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint); if (webBrowserPrint) { - gPrintSettings = GetPrintSettings(webBrowserPrint); + gPrintSettings = GetPrintSettings(); } - goPageSetup(gPrintSettings); // from utilityOverlay.js + didOK = goPageSetup(window, gPrintSettings); // from utilityOverlay.js + if (didOK) { // from utilityOverlay.js - if (webBrowserPrint) { - if (webBrowserPrint.doingPrintPreview) { - webBrowserPrint.printPreview(gPrintSettings); + if (webBrowserPrint) { + if (gPrintSettingsAreGlobal && gSavePrintSettings) { + var psService = Components.classes["@mozilla.org/gfx/printsettings-service;1"] + .getService(Components.interfaces.nsIPrintSettingsService); + psService.savePrintSettingsToPrefs(gPrintSettings, false, gPrintSettings.kInitSaveNativeData); + } } } - } catch (e) { dump("BrowserPrintSetup "+e); } + return didOK; } function BrowserPrint() @@ -1906,7 +2179,7 @@ function BrowserPrint() var ifreq = _content.QueryInterface(Components.interfaces.nsIInterfaceRequestor); var webBrowserPrint = ifreq.getInterface(Components.interfaces.nsIWebBrowserPrint); if (webBrowserPrint) { - gPrintSettings = GetPrintSettings(webBrowserPrint); + gPrintSettings = GetPrintSettings(); webBrowserPrint.print(gPrintSettings, null); } } catch (e) { @@ -2010,83 +2283,1489 @@ function FillInHTMLTooltip(tipElement) return retVal; } -function openPanel(aURI, aTitle) +var gBookmarksShell = null; + +/////////////////////////////////////////////////////////////////////////////// +// Class which defines methods for a bookmarks UI implementation based around +// a toolbar. Subclasses BookmarksBase in bookmarksOverlay.js. Some methods +// are required by the base class, others are for event handling. Window specific +// glue code should go into the BookmarksWindow class in bookmarks.js +function BookmarksToolbar (aID) { - var sidebarPane = document.getElementById("browserSidebar"); - var isHidden = sidebar_is_hidden(); - if (!isHidden && sidebarPane.getAttribute("src") == aURI) - SidebarHide(); - else if (isHidden) - SidebarShow(); - - sidebarPane.setAttribute("src", aURI); - var sidebarHeader = document.getElementById("sidebarhdrSidebar"); - sidebarHeader.setAttribute("label", aTitle); + this.id = aID; } -function SidebarShow() { - var sidebar_box = document.getElementById('boxSidebar'); - var sidebar_splitter = document.getElementById('splitterSidebar'); +BookmarksToolbar.prototype = { + __proto__: BookmarksUIElement.prototype, - // for older profiles: - sidebar_box.setAttribute('hidden', 'false'); - sidebar_splitter.removeAttribute('hidden'); - persist_width(); - window._content.focus(); -} + ///////////////////////////////////////////////////////////////////////////// + // Personal Toolbar Specific Stuff + + get db () + { + return this.element.database; + }, -function SidebarHide() { - var sidebar_box = document.getElementById('boxSidebar'); - var sidebar_splitter = document.getElementById('splitterSidebar'); - sidebar_box.setAttribute('hidden', 'true'); - sidebar_splitter.setAttribute('hidden', 'true'); - persist_width(); - window._content.focus(); -} + get element () + { + return document.getElementById(this.id); + }, -// sidebar_is_hidden() - Helper function for SidebarShowHide(). -function sidebar_is_hidden() { - var sidebar_box = document.getElementById('boxSidebar'); - return sidebar_box.getAttribute('hidden') == 'true'; -} + ///////////////////////////////////////////////////////////////////////////// + // This method constructs a menuitem for a context menu for the given command. + // This is implemented by the client so that it can intercept menuitem naming + // as appropriate. + createMenuItem: function (aDisplayName, aCommandName, aItemNode) + { + const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + var xulElement = document.createElementNS(kXULNS, "menuitem"); + xulElement.setAttribute("cmd", aCommandName); + var cmd = "cmd_" + aCommandName.substring(NC_NS_CMD.length) + xulElement.setAttribute("command", cmd); + + switch (aCommandName) { + case NC_NS_CMD + "bm_open": + xulElement.setAttribute("label", aDisplayName); + xulElement.setAttribute("default", "true"); + break; + case NC_NS_CMD + "bm_openfolder": + xulElement.setAttribute("default", "true"); + if (aItemNode.localName == "hbox") + // Don't show an "Open Folder" item for clicks on the toolbar itself. + return null; + default: + xulElement.setAttribute("label", aDisplayName); + break; + } + return xulElement; + }, -function persist_width() { - // XXX Mini hack. Persist isn't working too well. Force the persist, - // but wait until the width change has commited. - setTimeout("document.persist('boxSidebar', 'width');",100); -} + // Command implementation + commands: { + openFolder: function (aSelectedItem) + { + var mbo = aSelectedItem.boxObject.QueryInterface(Components.interfaces.nsIMenuBoxObject); + mbo.openMenu(true); + }, -function SidebarFinishClick() { + editCell: function (aSelectedItem, aXXXLameAssIndex) + { + goDoCommand("cmd_bm_properties"); + return; // Disable Inline Edit for now. See bug 77125 for why this is being disabled + // on the personal toolbar for the moment. - // XXX Semi-hack for bug #16516. - // If we had the proper drag event listener, we would not need this - // timeout. The timeout makes sure the width is written to disk after - // the sidebar-box gets the newly dragged width. - setTimeout("persist_width()",100); -} + if (aSelectedItem.getAttribute("editable") != "true") + return; + var property = "http://home.netscape.com/NC-rdf#Name"; + aSelectedItem.setMode("edit"); + aSelectedItem.addObserver(this.postModifyCallback, "accept", + [gBookmarksShell, aSelectedItem, property]); + }, -function UpdateInternetSearchResults(event) -{ - var url = getWebNavigation().currentURI.spec; - if (url) { - try { - var autoOpenSearchPanel = - pref.getBoolPref("browser.search.opensidebarsearchpanel"); + /////////////////////////////////////////////////////////////////////////// + // Called after an inline-edit cell has left inline-edit mode, and data + // needs to be modified in the datasource. + postModifyCallback: function (aParams) + { + aParams[0].propertySet(aParams[1].id, aParams[2], aParams[3]); + }, - if (autoOpenSearchPanel || isSearchPanelOpen()) - { - if (!gSearchService) - gSearchService = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"] - .getService(Components.interfaces.nsIInternetSearchService); + /////////////////////////////////////////////////////////////////////////// + // Creates a dummy item that can be placed in edit mode to retrieve data + // to create new bookmarks/folders. + createBookmarkItem: function (aMode, aSelectedItem) + { + ///////////////////////////////////////////////////////////////////////// + // HACK HACK HACK HACK HACK + // Disable Inline-Edit for now and just use a dialog. + + // XXX - most of this is just copy-pasted from the other two folder + // creation functions. Yes it's ugly, but it'll do the trick for + // now as this is in no way intended to be a long-term solution. - var searchInProgressFlag = gSearchService.FindInternetSearchResults(url); + const kPromptSvcContractID = "@mozilla.org/embedcomp/prompt-service;1"; + const kPromptSvcIID = Components.interfaces.nsIPromptService; + const kPromptSvc = Components.classes[kPromptSvcContractID].getService(kPromptSvcIID); + + var defaultValue = gBookmarksShell.getLocaleString("ile_newfolder"); + var dialogTitle = gBookmarksShell.getLocaleString("newfolder_dialog_title"); + var dialogMsg = gBookmarksShell.getLocaleString("newfolder_dialog_msg"); + var stringValue = { value: defaultValue }; + if (kPromptSvc.prompt(window, dialogTitle, dialogMsg, stringValue, null, { value: 0 })) { + var relativeNode = aSelectedItem || gBookmarksShell.element; + var parentNode = relativeNode ? gBookmarksShell.findRDFNode(relativeNode, false) : gBookmarksShell.element; - if (searchInProgressFlag) { - if (autoOpenSearchPanel) - RevealSearchPanel(); - } + var args = [{ property: NC_NS + "parent", + resource: parentNode.id }, + { property: NC_NS + "Name", + literal: stringValue.value }]; + + const kBMDS = gBookmarksShell.RDF.GetDataSource("rdf:bookmarks"); + var relId = relativeNode ? relativeNode.id : "NC:PersonalToolbarFolder"; + BookmarksUtils.doBookmarksCommand(relId, NC_NS_CMD + "newfolder", args); } - } catch (ex) { + + return; + + // HACK HACK HACK HACK HACK + ///////////////////////////////////////////////////////////////////////// + + const kXULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; + var dummyButton = document.createElementNS(kXULNS, "menubutton"); + dummyButton = gBookmarksShell.createBookmarkFolderDecorations(dummyButton); + dummyButton.setAttribute("class", "button-toolbar bookmark-item"); + + dummyButton.setAttribute("label", gBookmarksShell.getLocaleString("ile_newfolder") + " "); + // By default, create adjacent to the selected button. If there is no button after + // the selected button, or the target is the toolbar itself, just append. + var bIsButton = aSelectedItem.localName == "button" || aSelectedItem.localName == "menubutton"; + if (aSelectedItem.nextSibling && bIsButton) + aSelectedItem.parentNode.insertBefore(dummyButton, aSelectedItem.nextSibling); + else + (bIsButton ? aSelectedItem.parentNode : aSelectedItem).appendChild(dummyButton); + + gBookmarksShell._focusElt = document.commandDispatcher.focusedElement; + dummyButton.setMode("edit"); + // |aSelectedItem| will be the node we create the new folder relative to. + dummyButton.addObserver(this.onEditFolderName, "accept", + [dummyButton, aSelectedItem, dummyButton]); + dummyButton.addObserver(this.onEditFolderName, "reject", + [dummyButton, aSelectedItem, dummyButton]); + }, + + /////////////////////////////////////////////////////////////////////////// + // Edit folder name & update the datasource if name is valid + onEditFolderName: function (aParams, aTopic) + { + // Because the toolbar has no concept of selection, this function + // is much simpler than the one in bookmarksTree.js. However it may + // become more complex if pink ever lets me put context menus on menus ;) + var name = aParams[3]; + var dummyButton = aParams[2]; + var relativeNode = aParams[1]; + var parentNode = gBookmarksShell.findRDFNode(relativeNode, false); + + dummyButton.parentNode.removeChild(dummyButton); + + if (!gBookmarksShell.commands.validateNameAndTopic(name, aTopic, relativeNode, dummyButton)) + return; + + parentNode = relativeNode.parentNode; + if (relativeNode.localName == "hbox") { + parentNode = relativeNode; + relativeNode = (gBookmarksShell.commands.nodeIsValidType(relativeNode) && + relativeNode.lastChild) || relativeNode; + } + + var args = [{ property: NC_NS + "parent", + resource: parentNode.id }, + { property: NC_NS + "Name", + literal: name }]; + + BookmarksUtils.doBookmarksCommand(relativeNode.id, NC_NS_CMD + "newfolder", args); + // We need to do this because somehow focus shifts and no commands + // operate any more. + //gBookmarksShell._focusElt.focus(); + }, + + nodeIsValidType: function (aNode) + { + switch (aNode.localName) { + case "button": + case "menubutton": + // case "menu": + // case "menuitem": + return true; + } + return false; + }, + + /////////////////////////////////////////////////////////////////////////// + // Performs simple validation on what the user has entered: + // 1) prevents entering an empty string + // 2) in the case of a canceled operation, remove the dummy item and + // restore selection. + validateNameAndTopic: function (aName, aTopic, aOldSelectedItem, aDummyItem) + { + // Don't allow user to enter an empty string ""; + if (!aName) return false; + + // If the user hit escape, go no further. + return !(aTopic == "reject"); + } + }, + + _focusElt: null, + + ///////////////////////////////////////////////////////////////////////////// + // Evaluates an event to determine whether or not it affords opening a tree + // item. Typically, this is when the left mouse button is used, and provided + // the click-rate matches that specified by our owning tree class. For example, + // some trees open an item when double clicked (bookmarks/history windows) and + // others on a single click (sidebar panels). + isValidOpenEvent: function (aEvent) + { + return !(aEvent.type == "click" && + (aEvent.button != 0 || aEvent.detail != this.openClickCount)) + }, + + ///////////////////////////////////////////////////////////////////////////// + // For the given selection, selects the best adjacent element. This method is + // useful when an action such as a cut or a deletion is performed on a + // selection, and focus/selection needs to be restored after the operation + // is performed. + getNextElement: function (aElement) + { + if (aElement.nextSibling) + return aElement.nextSibling; + else if (aElement.previousSibling) + return aElement.previousSibling; + else + return aElement.parentNode; + }, + + selectElement: function (aElement) + { + }, + + ////////////////////////////////////////////////////////////////////////////// + // Add the treeitem element specified by aURI to the tree's current selection. + addItemToSelection: function (aURI) + { + }, + + ///////////////////////////////////////////////////////////////////////////// + // Return a set of DOM nodes that represents the current item in the Bookmarks + // Toolbar. This is always |document.popupNode|. + getSelection: function () + { + return [document.popupNode]; + }, + + ///////////////////////////////////////////////////////////////////////////// + // Return a set of DOM nodes that represent the selection in the tree widget. + // This method is takes a node parameter which is the popupNode for the + // document. If the popupNode is not contained by the selection, the + // popupNode is selected and the new selection returned. + getContextSelection: function (aItemNode) + { + return [aItemNode]; + }, + + getSelectedFolder: function () + { + return "NC:PersonalToolbarFolder"; + }, + + ///////////////////////////////////////////////////////////////////////////// + // For a given start DOM element, find the enclosing DOM element that contains + // the template builder RDF resource decorations (id, ref, etc). In the + // Toolbar case, this is always the popup node (until we're proven wrong ;) + findRDFNode: function (aStartNode, aIncludeStartNodeFlag) + { + var temp = aStartNode; + while (temp && temp.localName != (aIncludeStartNodeFlag ? "toolbarbutton" : "hbox")) + temp = temp.parentNode; + return temp || this.element; + }, + + selectFolderItem: function (aFolderURI, aItemURI, aAdditiveFlag) + { + var folder = document.getElementById(aFolderURI); + var kids = ContentUtils.childByLocalName(folder, "treechildren"); + if (!kids) return; + + var item = kids.firstChild; + while (item) { + if (item.id == aItemURI) break; + item = item.nextSibling; + } + if (!item) return; + + this.tree[aAdditiveFlag ? "addItemToSelection" : "selectItem"](item); + }, + + ///////////////////////////////////////////////////////////////////////////// + // Command handling & Updating. + controller: { + supportsCommand: function (aCommand) + { + switch(aCommand) { + case "cmd_bm_undo": + case "cmd_bm_redo": + return false; + case "cmd_bm_cut": + case "cmd_bm_copy": + case "cmd_bm_paste": + case "cmd_bm_delete": + case "cmd_bm_selectAll": + case "cmd_bm_open": + case "cmd_bm_openfolder": + case "cmd_bm_openinnewwindow": + case "cmd_bm_newbookmark": + case "cmd_bm_newfolder": + case "cmd_bm_newseparator": + case "cmd_bm_find": + case "cmd_bm_properties": + case "cmd_bm_rename": + case "cmd_bm_setnewbookmarkfolder": + case "cmd_bm_setpersonaltoolbarfolder": + case "cmd_bm_setnewsearchfolder": + case "cmd_bm_import": + case "cmd_bm_export": + case "cmd_bm_fileBookmark": + return true; + default: + return false; + } + }, + + isCommandEnabled: function (aCommand) + { + switch(aCommand) { + case "cmd_bm_undo": + case "cmd_bm_redo": + return false; + case "cmd_bm_paste": + var cp = gBookmarksShell.canPaste(); + return cp; + case "cmd_bm_cut": + case "cmd_bm_copy": + case "cmd_bm_delete": + return document.popupNode && document.popupNode.id != "NC:PersonalToolbarFolder"; + case "cmd_bm_selectAll": + return false; + case "cmd_bm_open": + var seln = gBookmarksShell.getSelection(); + return document.popupNode != null && seln[0].getAttributeNS(RDF_NS, "type") == NC_NS + "Bookmark"; + case "cmd_bm_openfolder": + seln = gBookmarksShell.getSelection(); + return document.popupNode != null && seln[0].getAttributeNS(RDF_NS, "type") == NC_NS + "Folder"; + case "cmd_bm_openinnewwindow": + return true; + case "cmd_bm_find": + case "cmd_bm_newbookmark": + case "cmd_bm_newfolder": + case "cmd_bm_newseparator": + case "cmd_bm_import": + case "cmd_bm_export": + return true; + case "cmd_bm_properties": + case "cmd_bm_rename": + return document.popupNode != null; + case "cmd_bm_setnewbookmarkfolder": + seln = gBookmarksShell.getSelection(); + if (!seln.length) return false; + var folderType = seln[0].getAttributeNS(RDF_NS, "type") == (NC_NS + "Folder"); + return document.popupNode && seln[0].id != "NC:NewBookmarkFolder" && folderType; + case "cmd_bm_setpersonaltoolbarfolder": + seln = gBookmarksShell.getSelection(); + if (!seln.length) return false; + folderType = seln[0].getAttributeNS(RDF_NS, "type") == (NC_NS + "Folder"); + return document.popupNode && seln[0].id != "NC:PersonalToolbarFolder" && folderType; + case "cmd_bm_setnewsearchfolder": + seln = gBookmarksShell.getSelection(); + if (!seln.length) return false; + folderType = seln[0].getAttributeNS(RDF_NS, "type") == (NC_NS + "Folder"); + return document.popupNode && seln[0].id != "NC:NewSearchFolder" && folderType; + case "cmd_bm_fileBookmark": + seln = gBookmarksShell.getSelection(); + return seln.length > 0; + default: + return false; + } + }, + + doCommand: function (aCommand) + { + switch(aCommand) { + case "cmd_bm_undo": + case "cmd_bm_redo": + break; + case "cmd_bm_paste": + case "cmd_bm_copy": + case "cmd_bm_cut": + case "cmd_bm_delete": + case "cmd_bm_newbookmark": + case "cmd_bm_newfolder": + case "cmd_bm_newseparator": + case "cmd_bm_properties": + case "cmd_bm_rename": + case "cmd_bm_open": + case "cmd_bm_openfolder": + case "cmd_bm_openinnewwindow": + case "cmd_bm_setnewbookmarkfolder": + case "cmd_bm_setpersonaltoolbarfolder": + case "cmd_bm_setnewsearchfolder": + case "cmd_bm_find": + case "cmd_bm_import": + case "cmd_bm_export": + case "cmd_bm_fileBookmark": + gBookmarksShell.execCommand(aCommand.substring("cmd_".length)); + break; + case "cmd_bm_selectAll": + break; + } + }, + + onEvent: function (aEvent) + { + }, + + onCommandUpdate: function () + { } } +}; + +function BM_navigatorLoad(aEvent) +{ + if (!gBookmarksShell) { + gBookmarksShell = new BookmarksToolbar("NC:PersonalToolbarFolder"); + controllers.appendController(gBookmarksShell.controller); + removeEventListener("load", BM_navigatorLoad, false); + } } + + +// An interim workaround for 101131 - Bookmarks Toolbar button nonfunctional. +// This simply checks to see if the bookmark menu is empty (aside from static +// items) when it is opened and if it is, prompts a rebuild. +// The best fix for this is more time consuming, and relies on document +//