michael@0: /* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: Components.utils.import("resource://gre/modules/XPCOMUtils.jsm"); michael@0: XPCOMUtils.defineLazyModuleGetter(this, "DownloadsCommon", michael@0: "resource:///modules/DownloadsCommon.jsm"); michael@0: michael@0: var gMainPane = { michael@0: _pane: null, michael@0: michael@0: /** michael@0: * Initialization of this. michael@0: */ michael@0: init: function () michael@0: { michael@0: this._pane = document.getElementById("paneMain"); michael@0: michael@0: // set up the "use current page" label-changing listener michael@0: this._updateUseCurrentButton(); michael@0: window.addEventListener("focus", this._updateUseCurrentButton.bind(this), false); michael@0: michael@0: this.updateBrowserStartupLastSession(); michael@0: michael@0: // Notify observers that the UI is now ready michael@0: Components.classes["@mozilla.org/observer-service;1"] michael@0: .getService(Components.interfaces.nsIObserverService) michael@0: .notifyObservers(window, "main-pane-loaded", null); michael@0: }, michael@0: michael@0: // HOME PAGE michael@0: michael@0: /* michael@0: * Preferences: michael@0: * michael@0: * browser.startup.homepage michael@0: * - the user's home page, as a string; if the home page is a set of tabs, michael@0: * this will be those URLs separated by the pipe character "|" michael@0: * browser.startup.page michael@0: * - what page(s) to show when the user starts the application, as an integer: michael@0: * michael@0: * 0: a blank page michael@0: * 1: the home page (as set by the browser.startup.homepage pref) michael@0: * 2: the last page the user visited (DEPRECATED) michael@0: * 3: windows and tabs from the last session (a.k.a. session restore) michael@0: * michael@0: * The deprecated option is not exposed in UI; however, if the user has it michael@0: * selected and doesn't change the UI for this preference, the deprecated michael@0: * option is preserved. michael@0: */ michael@0: michael@0: syncFromHomePref: function () michael@0: { michael@0: let homePref = document.getElementById("browser.startup.homepage"); michael@0: michael@0: // If the pref is set to about:home, set the value to "" to show the michael@0: // placeholder text (about:home title). michael@0: if (homePref.value.toLowerCase() == "about:home") michael@0: return ""; michael@0: michael@0: // If the pref is actually "", show about:blank. The actual home page michael@0: // loading code treats them the same, and we don't want the placeholder text michael@0: // to be shown. michael@0: if (homePref.value == "") michael@0: return "about:blank"; michael@0: michael@0: // Otherwise, show the actual pref value. michael@0: return undefined; michael@0: }, michael@0: michael@0: syncToHomePref: function (value) michael@0: { michael@0: // If the value is "", use about:home. michael@0: if (value == "") michael@0: return "about:home"; michael@0: michael@0: // Otherwise, use the actual textbox value. michael@0: return undefined; michael@0: }, michael@0: michael@0: /** michael@0: * Sets the home page to the current displayed page (or frontmost tab, if the michael@0: * most recent browser window contains multiple tabs), updating preference michael@0: * window UI to reflect this. michael@0: */ michael@0: setHomePageToCurrent: function () michael@0: { michael@0: let homePage = document.getElementById("browser.startup.homepage"); michael@0: let tabs = this._getTabsForHomePage(); michael@0: function getTabURI(t) t.linkedBrowser.currentURI.spec; michael@0: michael@0: // FIXME Bug 244192: using dangerous "|" joiner! michael@0: if (tabs.length) michael@0: homePage.value = tabs.map(getTabURI).join("|"); michael@0: }, michael@0: michael@0: /** michael@0: * Displays a dialog in which the user can select a bookmark to use as home michael@0: * page. If the user selects a bookmark, that bookmark's name is displayed in michael@0: * UI and the bookmark's address is stored to the home page preference. michael@0: */ michael@0: setHomePageToBookmark: function () michael@0: { michael@0: var rv = { urls: null, names: null }; michael@0: document.documentElement.openSubDialog("chrome://browser/content/preferences/selectBookmark.xul", michael@0: "resizable", rv); michael@0: if (rv.urls && rv.names) { michael@0: var homePage = document.getElementById("browser.startup.homepage"); michael@0: michael@0: // XXX still using dangerous "|" joiner! michael@0: homePage.value = rv.urls.join("|"); michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Switches the "Use Current Page" button between its singular and plural michael@0: * forms. michael@0: */ michael@0: _updateUseCurrentButton: function () { michael@0: let useCurrent = document.getElementById("useCurrent"); michael@0: michael@0: let tabs = this._getTabsForHomePage(); michael@0: if (tabs.length > 1) michael@0: useCurrent.label = useCurrent.getAttribute("label2"); michael@0: else michael@0: useCurrent.label = useCurrent.getAttribute("label1"); michael@0: michael@0: // In this case, the button's disabled state is set by preferences.xml. michael@0: if (document.getElementById michael@0: ("pref.browser.homepage.disable_button.current_page").locked) michael@0: return; michael@0: michael@0: useCurrent.disabled = !tabs.length michael@0: }, michael@0: michael@0: _getTabsForHomePage: function () michael@0: { michael@0: var win; michael@0: var tabs = []; michael@0: if (document.documentElement.instantApply) { michael@0: const Cc = Components.classes, Ci = Components.interfaces; michael@0: // If we're in instant-apply mode, use the most recent browser window michael@0: var wm = Cc["@mozilla.org/appshell/window-mediator;1"] michael@0: .getService(Ci.nsIWindowMediator); michael@0: win = wm.getMostRecentWindow("navigator:browser"); michael@0: } michael@0: else { michael@0: win = window.opener; michael@0: } michael@0: michael@0: if (win && win.document.documentElement michael@0: .getAttribute("windowtype") == "navigator:browser") { michael@0: // We should only include visible & non-pinned tabs michael@0: tabs = win.gBrowser.visibleTabs.slice(win.gBrowser._numPinnedTabs); michael@0: } michael@0: michael@0: return tabs; michael@0: }, michael@0: michael@0: /** michael@0: * Restores the default home page as the user's home page. michael@0: */ michael@0: restoreDefaultHomePage: function () michael@0: { michael@0: var homePage = document.getElementById("browser.startup.homepage"); michael@0: homePage.value = homePage.defaultValue; michael@0: }, michael@0: michael@0: // DOWNLOADS michael@0: michael@0: /* michael@0: * Preferences: michael@0: * michael@0: * browser.download.useDownloadDir - bool michael@0: * True - Save files directly to the folder configured via the michael@0: * browser.download.folderList preference. michael@0: * False - Always ask the user where to save a file and default to michael@0: * browser.download.lastDir when displaying a folder picker dialog. michael@0: * browser.download.dir - local file handle michael@0: * A local folder the user may have selected for downloaded files to be michael@0: * saved. Migration of other browser settings may also set this path. michael@0: * This folder is enabled when folderList equals 2. michael@0: * browser.download.lastDir - local file handle michael@0: * May contain the last folder path accessed when the user browsed michael@0: * via the file save-as dialog. (see contentAreaUtils.js) michael@0: * browser.download.folderList - int michael@0: * Indicates the location users wish to save downloaded files too. michael@0: * It is also used to display special file labels when the default michael@0: * download location is either the Desktop or the Downloads folder. michael@0: * Values: michael@0: * 0 - The desktop is the default download location. michael@0: * 1 - The system's downloads folder is the default download location. michael@0: * 2 - The default download location is elsewhere as specified in michael@0: * browser.download.dir. michael@0: * browser.download.downloadDir michael@0: * deprecated. michael@0: * browser.download.defaultFolder michael@0: * deprecated. michael@0: */ michael@0: michael@0: /** michael@0: * Enables/disables the folder field and Browse button based on whether a michael@0: * default download directory is being used. michael@0: */ michael@0: readUseDownloadDir: function () michael@0: { michael@0: var downloadFolder = document.getElementById("downloadFolder"); michael@0: var chooseFolder = document.getElementById("chooseFolder"); michael@0: var preference = document.getElementById("browser.download.useDownloadDir"); michael@0: downloadFolder.disabled = !preference.value; michael@0: chooseFolder.disabled = !preference.value; michael@0: michael@0: // don't override the preference's value in UI michael@0: return undefined; michael@0: }, michael@0: michael@0: /** michael@0: * Displays a file picker in which the user can choose the location where michael@0: * downloads are automatically saved, updating preferences and UI in michael@0: * response to the choice, if one is made. michael@0: */ michael@0: chooseFolder: function () michael@0: { michael@0: const nsIFilePicker = Components.interfaces.nsIFilePicker; michael@0: const nsILocalFile = Components.interfaces.nsILocalFile; michael@0: michael@0: let bundlePreferences = document.getElementById("bundlePreferences"); michael@0: let title = bundlePreferences.getString("chooseDownloadFolderTitle"); michael@0: let folderListPref = document.getElementById("browser.download.folderList"); michael@0: let currentDirPref = this._indexToFolder(folderListPref.value); // file michael@0: let defDownloads = this._indexToFolder(1); // file michael@0: let fp = Components.classes["@mozilla.org/filepicker;1"]. michael@0: createInstance(nsIFilePicker); michael@0: let fpCallback = function fpCallback_done(aResult) { michael@0: if (aResult == nsIFilePicker.returnOK) { michael@0: let file = fp.file.QueryInterface(nsILocalFile); michael@0: let downloadDirPref = document.getElementById("browser.download.dir"); michael@0: michael@0: downloadDirPref.value = file; michael@0: folderListPref.value = this._folderToIndex(file); michael@0: // Note, the real prefs will not be updated yet, so dnld manager's michael@0: // userDownloadsDirectory may not return the right folder after michael@0: // this code executes. displayDownloadDirPref will be called on michael@0: // the assignment above to update the UI. michael@0: } michael@0: }.bind(this); michael@0: michael@0: fp.init(window, title, nsIFilePicker.modeGetFolder); michael@0: fp.appendFilters(nsIFilePicker.filterAll); michael@0: // First try to open what's currently configured michael@0: if (currentDirPref && currentDirPref.exists()) { michael@0: fp.displayDirectory = currentDirPref; michael@0: } // Try the system's download dir michael@0: else if (defDownloads && defDownloads.exists()) { michael@0: fp.displayDirectory = defDownloads; michael@0: } // Fall back to Desktop michael@0: else { michael@0: fp.displayDirectory = this._indexToFolder(0); michael@0: } michael@0: fp.open(fpCallback); michael@0: }, michael@0: michael@0: /** michael@0: * Initializes the download folder display settings based on the user's michael@0: * preferences. michael@0: */ michael@0: displayDownloadDirPref: function () michael@0: { michael@0: var folderListPref = document.getElementById("browser.download.folderList"); michael@0: var bundlePreferences = document.getElementById("bundlePreferences"); michael@0: var downloadFolder = document.getElementById("downloadFolder"); michael@0: var currentDirPref = document.getElementById("browser.download.dir"); michael@0: michael@0: // Used in defining the correct path to the folder icon. michael@0: var ios = Components.classes["@mozilla.org/network/io-service;1"] michael@0: .getService(Components.interfaces.nsIIOService); michael@0: var fph = ios.getProtocolHandler("file") michael@0: .QueryInterface(Components.interfaces.nsIFileProtocolHandler); michael@0: var iconUrlSpec; michael@0: michael@0: // Display a 'pretty' label or the path in the UI. michael@0: if (folderListPref.value == 2) { michael@0: // Custom path selected and is configured michael@0: downloadFolder.label = this._getDisplayNameOfFile(currentDirPref.value); michael@0: iconUrlSpec = fph.getURLSpecFromFile(currentDirPref.value); michael@0: } else if (folderListPref.value == 1) { michael@0: // 'Downloads' michael@0: // In 1.5, this pointed to a folder we created called 'My Downloads' michael@0: // and was available as an option in the 1.5 drop down. On XP this michael@0: // was in My Documents, on OSX it was in User Docs. In 2.0, we did michael@0: // away with the drop down option, although the special label was michael@0: // still supported for the folder if it existed. Because it was michael@0: // not exposed it was rarely used. michael@0: // With 3.0, a new desktop folder - 'Downloads' was introduced for michael@0: // platforms and versions that don't support a default system downloads michael@0: // folder. See nsDownloadManager for details. michael@0: downloadFolder.label = bundlePreferences.getString("downloadsFolderName"); michael@0: iconUrlSpec = fph.getURLSpecFromFile(this._indexToFolder(1)); michael@0: } else { michael@0: // 'Desktop' michael@0: downloadFolder.label = bundlePreferences.getString("desktopFolderName"); michael@0: iconUrlSpec = fph.getURLSpecFromFile(this._getDownloadsFolder("Desktop")); michael@0: } michael@0: downloadFolder.image = "moz-icon://" + iconUrlSpec + "?size=16"; michael@0: michael@0: // don't override the preference's value in UI michael@0: return undefined; michael@0: }, michael@0: michael@0: /** michael@0: * Returns the textual path of a folder in readable form. michael@0: */ michael@0: _getDisplayNameOfFile: function (aFolder) michael@0: { michael@0: // TODO: would like to add support for 'Downloads on Macintosh HD' michael@0: // for OS X users. michael@0: return aFolder ? aFolder.path : ""; michael@0: }, michael@0: michael@0: /** michael@0: * Returns the Downloads folder. If aFolder is "Desktop", then the Downloads michael@0: * folder returned is the desktop folder; otherwise, it is a folder whose name michael@0: * indicates that it is a download folder and whose path is as determined by michael@0: * the XPCOM directory service via the download manager's attribute michael@0: * defaultDownloadsDirectory. michael@0: * michael@0: * @throws if aFolder is not "Desktop" or "Downloads" michael@0: */ michael@0: _getDownloadsFolder: function (aFolder) michael@0: { michael@0: switch (aFolder) { michael@0: case "Desktop": michael@0: var fileLoc = Components.classes["@mozilla.org/file/directory_service;1"] michael@0: .getService(Components.interfaces.nsIProperties); michael@0: return fileLoc.get("Desk", Components.interfaces.nsILocalFile); michael@0: break; michael@0: case "Downloads": michael@0: var dnldMgr = Components.classes["@mozilla.org/download-manager;1"] michael@0: .getService(Components.interfaces.nsIDownloadManager); michael@0: return dnldMgr.defaultDownloadsDirectory; michael@0: break; michael@0: } michael@0: throw "ASSERTION FAILED: folder type should be 'Desktop' or 'Downloads'"; michael@0: }, michael@0: michael@0: /** michael@0: * Determines the type of the given folder. michael@0: * michael@0: * @param aFolder michael@0: * the folder whose type is to be determined michael@0: * @returns integer michael@0: * 0 if aFolder is the Desktop or is unspecified, michael@0: * 1 if aFolder is the Downloads folder, michael@0: * 2 otherwise michael@0: */ michael@0: _folderToIndex: function (aFolder) michael@0: { michael@0: if (!aFolder || aFolder.equals(this._getDownloadsFolder("Desktop"))) michael@0: return 0; michael@0: else if (aFolder.equals(this._getDownloadsFolder("Downloads"))) michael@0: return 1; michael@0: return 2; michael@0: }, michael@0: michael@0: /** michael@0: * Converts an integer into the corresponding folder. michael@0: * michael@0: * @param aIndex michael@0: * an integer michael@0: * @returns the Desktop folder if aIndex == 0, michael@0: * the Downloads folder if aIndex == 1, michael@0: * the folder stored in browser.download.dir michael@0: */ michael@0: _indexToFolder: function (aIndex) michael@0: { michael@0: switch (aIndex) { michael@0: case 0: michael@0: return this._getDownloadsFolder("Desktop"); michael@0: case 1: michael@0: return this._getDownloadsFolder("Downloads"); michael@0: } michael@0: var currentDirPref = document.getElementById("browser.download.dir"); michael@0: return currentDirPref.value; michael@0: }, michael@0: michael@0: /** michael@0: * Returns the value for the browser.download.folderList preference. michael@0: */ michael@0: getFolderListPref: function () michael@0: { michael@0: var folderListPref = document.getElementById("browser.download.folderList"); michael@0: switch (folderListPref.value) { michael@0: case 0: // Desktop michael@0: case 1: // Downloads michael@0: return folderListPref.value; michael@0: break; michael@0: case 2: // Custom michael@0: var currentDirPref = document.getElementById("browser.download.dir"); michael@0: if (currentDirPref.value) { michael@0: // Resolve to a known location if possible. We are writing out michael@0: // to prefs on this call, so now would be a good time to do it. michael@0: return this._folderToIndex(currentDirPref.value); michael@0: } michael@0: return 0; michael@0: break; michael@0: } michael@0: }, michael@0: michael@0: /** michael@0: * Hide/show the "Show my windows and tabs from last time" option based michael@0: * on the value of the browser.privatebrowsing.autostart pref. michael@0: */ michael@0: updateBrowserStartupLastSession: function() michael@0: { michael@0: let pbAutoStartPref = document.getElementById("browser.privatebrowsing.autostart"); michael@0: let startupPref = document.getElementById("browser.startup.page"); michael@0: let menu = document.getElementById("browserStartupPage"); michael@0: let option = document.getElementById("browserStartupLastSession"); michael@0: if (pbAutoStartPref.value) { michael@0: option.setAttribute("disabled", "true"); michael@0: if (option.selected) { michael@0: menu.selectedItem = document.getElementById("browserStartupHomePage"); michael@0: } michael@0: } else { michael@0: option.removeAttribute("disabled"); michael@0: startupPref.updateElements(); // select the correct index in the startup menulist michael@0: } michael@0: } michael@0: };