/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* ***** BEGIN LICENSE BLOCK ***** * Version: MPL 1.1/GPL 2.0/LGPL 2.1 * * The contents of this file are subject to the Mozilla Public License Version * 1.1 (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS IS" basis, * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License * for the specific language governing rights and limitations under the * License. * * The Original Code is mozilla.org code. * * The Initial Developer of the Original Code is * Netscape Communications Corporation. * Portions created by the Initial Developer are Copyright (C) 1998 * the Initial Developer. All Rights Reserved. * * Contributor(s): * Blake Ross * Peter Annema * Dean Tessman * * Alternatively, the contents of this file may be used under the terms of * either of the GNU General Public License Version 2 or later (the "GPL"), * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), * in which case the provisions of the GPL or the LGPL are applicable instead * of those above. If you wish to allow use of your version of this file only * under the terms of either the GPL or the LGPL, and not to allow others to * use your version of this file under the terms of the MPL, indicate your * decision by deleting the provisions above and replace them with the notice * and other provisions required by the GPL or the LGPL. If you do not delete * the provisions above, a recipient may use your version of this file under * the terms of any one of the MPL, the GPL or the LGPL. * * ***** END LICENSE BLOCK ***** */ const REMOTESERVICE_CONTRACTID = "@mozilla.org/toolkit/remote-service;1"; const XUL_NAMESPACE = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"; var gURLBar = null; var gProxyButton = null; var gProxyFavIcon = null; var gProxyDeck = null; var gBookmarksService = null; var gSearchService = null; var gNavigatorBundle; var gBrandBundle; var gNavigatorRegionBundle; var gLastValidURLStr = ""; var gLastValidURL = null; var gClickSelectsAll = false; var gClickAtEndSelects = false; var gIgnoreFocus = false; var gIgnoreClick = false; var gURIFixup = null; var pref = null; var appCore = null; //cached elements var gBrowser = null; // focused frame URL var gFocusedURL = null; var gFocusedDocument = null; // Pref listener constants const gButtonPrefListener = { domain: "browser.toolbars.showbutton", init: function() { var array = pref.getChildList(this.domain, {}); for (var i in array) this.updateButton(array[i]); this.updateSeparator(); }, observe: function(subject, topic, prefName) { // verify that we're changing a button pref if (topic != "nsPref:changed") return; this.updateButton(prefName); this.updateSeparator(); }, updateButton: function(prefName) { var buttonName = prefName.substr(this.domain.length+1); var buttonId = buttonName + "-button"; var button = document.getElementById(buttonId); if (button) button.hidden = !pref.getBoolPref(prefName); }, updateSeparator: function() { // If all buttons before the separator are hidden, also hide the separator var separator = document.getElementById("home-bm-separator"); separator.hidden = allLeftButtonsAreHidden(); } }; const gTabStripPrefListener = { domain: "browser.tabs.autoHide", observe: function(subject, topic, prefName) { // verify that we're changing the tab browser strip auto hide pref if (topic != "nsPref:changed") return; if (gBrowser.tabContainer.childNodes.length == 1 && window.toolbar.visible) { var stripVisibility = !pref.getBoolPref(prefName); gBrowser.setStripVisibilityTo(stripVisibility); pref.setBoolPref("browser.tabs.forceHide", false); } } }; const gHomepagePrefListener = { domain: "browser.startup.homepage", observe: function(subject, topic, prefName) { // verify that we're changing the home page pref if (topic != "nsPref:changed") return; updateHomeButtonTooltip(); } }; const gStatusBarPopupIconPrefListener = { domain: "privacy.popups.statusbar_icon_enabled", observe: function(subject, topic, prefName) { if (topic != "nsPref:changed" || prefName != this.domain) return; var popupIcon = document.getElementById("popupIcon"); if (!pref.getBoolPref(prefName)) popupIcon.hidden = true; else if (gBrowser.getNotificationBox().popupCount) popupIcon.hidden = false; } }; // popup window permission change listener const gPopupPermListener = { observe: function(subject, topic, data) { if (topic == "popup-perm-close") { // close the window if we're a popup and our opener's URI matches // the URI in the notification var popupOpenerURI = maybeInitPopupContext(); if (popupOpenerURI) { const IOS = Components.classes["@mozilla.org/network/io-service;1"] .getService(Components.interfaces.nsIIOService); closeURI = IOS.newURI(data, null, null); if (closeURI.host == popupOpenerURI.host) window.close(); } } } }; /** * Pref listener handler functions. * Both functions assume that observer.domain is set to * the pref domain we want to start/stop listening to. */ function addPrefListener(observer) { try { var pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranch2); pbi.addObserver(observer.domain, observer, false); } catch(ex) { dump("Failed to observe prefs: " + ex + "\n"); } } function removePrefListener(observer) { try { var pbi = pref.QueryInterface(Components.interfaces.nsIPrefBranch2); pbi.removeObserver(observer.domain, observer); } catch(ex) { dump("Failed to remove pref observer: " + ex + "\n"); } } function addPopupPermListener(observer) { const OS = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); OS.addObserver(observer, "popup-perm-close", false); } function removePopupPermListener(observer) { const OS = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); OS.removeObserver(observer, "popup-perm-close"); } /** * We can avoid adding multiple load event listeners and save some time by adding * one listener that calls all real handlers. */ function pageShowEventHandlers(event) { // Filter out events that are not about the document load we are interested in if (event.originalTarget == content.document) { UpdateBookmarksLastVisitedDate(event); UpdateInternetSearchResults(event); checkForDirectoryListing(); postURLToNativeWidget(); } } /** * Determine whether or not the content area is displaying a page with frames, * and if so, toggle the display of the 'save frame as' menu item. **/ function getContentAreaFrameCount() { var saveFrameItem = document.getElementById("saveframe"); if (!content || !content.frames.length || !isContentFrame(document.commandDispatcher.focusedWindow)) saveFrameItem.setAttribute("hidden", "true"); else { var autoDownload = pref.getBoolPref("browser.download.autoDownload"); goSetMenuValue("saveframe", autoDownload ? "valueSave" : "valueSaveAs"); saveFrameItem.removeAttribute("hidden"); } } // When a content area frame is focused, update the focused frame URL function contentAreaFrameFocus() { const focusedWindow = document.commandDispatcher.focusedWindow; if (focusedWindow && focusedWindow.top == window.content) { gFocusedURL = focusedWindow.location.href; gFocusedDocument = focusedWindow.document; } } function updateHomeButtonTooltip() { var homePage = getHomePage(); var tooltip = document.getElementById("home-button-tooltip-inner"); while (tooltip.firstChild) tooltip.removeChild(tooltip.firstChild); for (var i in homePage) { var label = document.createElementNS(XUL_NAMESPACE, "label"); label.setAttribute("value", homePage[i]); tooltip.appendChild(label); } } //////////////////////////////// BOOKMARKS //////////////////////////////////// function UpdateBookmarksLastVisitedDate(event) { var url = getWebNavigation().currentURI.spec; if (url) { // if the URL is bookmarked, update its "Last Visited" date if (!gBookmarksService) gBookmarksService = Components.classes["@mozilla.org/browser/bookmarks-service;1"] .getService(Components.interfaces.nsIBookmarksService); gBookmarksService.updateLastVisitedDate(url, content.document.characterSet); } } function HandleBookmarkIcon(iconURL, addFlag) { var url = content.document.documentURI; if (url) { // update URL with new icon reference if (!gBookmarksService) gBookmarksService = Components.classes["@mozilla.org/browser/bookmarks-service;1"] .getService(Components.interfaces.nsIBookmarksService); if (addFlag) gBookmarksService.updateBookmarkIcon(url, iconURL); else gBookmarksService.removeBookmarkIcon(url, iconURL); } } function UpdateInternetSearchResults(event) { var url = getWebNavigation().currentURI.spec; if (url && isSearchPanelOpen()) { if (!gSearchService) gSearchService = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"] .getService(Components.interfaces.nsIInternetSearchService); gSearchService.FindInternetSearchResults(url); } } function getBrowser() { if (!gBrowser) gBrowser = document.getElementById("content"); return gBrowser; } function getHomePage() { var URIs = []; try { URIs[0] = pref.getComplexValue("browser.startup.homepage", Components.interfaces.nsIPrefLocalizedString).data; var count = pref.getIntPref("browser.startup.homepage.count"); for (var i = 1; i < count; ++i) { URIs[i] = pref.getComplexValue("browser.startup.homepage."+i, Components.interfaces.nsIPrefLocalizedString).data; } } catch(e) { } return URIs; } function UpdateBackForwardButtons() { var backBroadcaster = document.getElementById("canGoBack"); var forwardBroadcaster = document.getElementById("canGoForward"); var upBroadcaster = document.getElementById("canGoUp"); var browser = getBrowser(); // Avoid setting attributes on broadcasters if the value hasn't changed! // Remember, guys, setting attributes on elements is expensive! They // get inherited into anonymous content, broadcast to other widgets, etc.! // Don't do it if the value hasn't changed! - dwh var backDisabled = backBroadcaster.hasAttribute("disabled"); var forwardDisabled = forwardBroadcaster.hasAttribute("disabled"); var upDisabled = upBroadcaster.hasAttribute("disabled"); if (backDisabled == browser.canGoBack) { if (backDisabled) backBroadcaster.removeAttribute("disabled"); else backBroadcaster.setAttribute("disabled", true); } if (forwardDisabled == browser.canGoForward) { if (forwardDisabled) forwardBroadcaster.removeAttribute("disabled"); else forwardBroadcaster.setAttribute("disabled", true); } if (upDisabled != !browser.currentURI.spec.replace(/[#?].*$/, "").match(/\/[^\/]+\/./)) { if (upDisabled) upBroadcaster.removeAttribute("disabled"); else upBroadcaster.setAttribute("disabled", true); } } // 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("home-bm-separator").previousSibling; while (buttonNode) { if (buttonNode.localName != "tooltip" && !buttonNode.hidden) return false; buttonNode = buttonNode.previousSibling; } return true; } const gTabOpenObserver = { observe: function(subject, topic, data) { if (topic != "open-new-tab-request" || subject != window) return; delayedOpenTab(data); } }; const nsIBrowserDOMWindow = Components.interfaces.nsIBrowserDOMWindow; const nsIInterfaceRequestor = Components.interfaces.nsIInterfaceRequestor; function nsBrowserAccess() { } nsBrowserAccess.prototype = { openURI: function openURI(aURI, aOpener, aWhere, aContext) { var loadflags = aContext == nsIBrowserDOMWindow.OPEN_EXTERNAL ? nsIWebNavigation.LOAD_FLAGS_FROM_EXTERNAL : nsIWebNavigation.LOAD_FLAGS_NONE; if (aWhere == nsIBrowserDOMWindow.OPEN_DEFAULTWINDOW) if (aContext == nsIBrowserDOMWindow.OPEN_EXTERNAL) aWhere = pref.getIntPref("browser.link.open_external"); else aWhere = pref.getIntPref("browser.link.open_newwindow"); var referrer = aOpener ? aOpener.QueryInterface(nsIInterfaceRequestor) .getInterface(nsIWebNavigation) .currentURI : null; switch (aWhere) { case nsIBrowserDOMWindow.OPEN_NEWWINDOW: var uri = aURI ? aURI.spec : "about:blank"; return window.openDialog(getBrowserURL(), "_blank", "all,dialog=no", uri, null, referrer); case nsIBrowserDOMWindow.OPEN_NEWTAB: var newTab = gBrowser.addTab("about:blank", null, null, !pref.getBoolPref("browser.tabs.loadDivertedInBackground")); var browser = gBrowser.getBrowserForTab(newTab); if (aURI) { try { browser.loadURIWithFlags(aURI.spec, loadflags, referrer); } catch (e) {} } return browser.contentWindow; default: if (!aOpener) { if (aURI) gBrowser.loadURIWithFlags(aURI.spec, loadflags); return content; } aOpener = aOpener.top; if (aURI) { try { aOpener.QueryInterface(nsIInterfaceRequestor) .getInterface(nsIWebNavigation) .loadURI(uri, loadflags, referrer, null, null); } catch (e) {} } return aOpener; } }, isTabContentWindow: function isTabContentWindow(aWindow) { var browsers = gBrowser.browsers; for (var i = 0; browsers.item(i); i++) if (browsers[i].contentWindow == aWindow) return true; return false; } } function HandleAppCommandEvent(aEvent) { aEvent.stopPropagation(); switch (aEvent.command) { case "Back": BrowserBack(); break; case "Forward": BrowserForward(); break; case "Reload": BrowserReloadSkipCache(); break; case "Stop": BrowserStop(); break; case "Search": BrowserSearchInternet(); break; case "Bookmarks": BrowserEditBookmarks(); break; case "Home": BrowserHome(null); break; default: break; } } function Startup() { // init globals gNavigatorBundle = document.getElementById("bundle_navigator"); gBrandBundle = document.getElementById("bundle_brand"); gNavigatorRegionBundle = document.getElementById("bundle_navigator_region"); gBrowser = document.getElementById("content"); gURLBar = document.getElementById("urlbar"); SetPageProxyState("invalid", null); var webNavigation; try { // Create the browser instance component. appCore = Components.classes["@mozilla.org/appshell/component/browser/instance;1"] .createInstance(Components.interfaces.nsIBrowserInstance); if (!appCore) throw "couldn't create a browser instance"; // Get the preferences service var prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); pref = prefService.getBranch(null); window.tryToClose = WindowIsClosing; webNavigation = getWebNavigation(); if (!webNavigation) throw "no XBL binding for browser"; } catch (e) { alert("Error launching browser window:" + e); window.close(); // Give up. return; } // Do all UI building here: // Ensure button visibility matches prefs gButtonPrefListener.init(); // set home button tooltip text updateHomeButtonTooltip(); // initialize observers and listeners window.XULBrowserWindow = new nsBrowserStatusHandler(); window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIXULWindow) .XULBrowserWindow = window.XULBrowserWindow; addPrefListener(gButtonPrefListener); addPrefListener(gTabStripPrefListener); addPrefListener(gHomepagePrefListener); addPrefListener(gStatusBarPopupIconPrefListener); addPopupPermListener(gPopupPermListener); window.browserContentListener = new nsBrowserContentListener(window, getBrowser()); // Initialize browser instance.. 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("appcontent"); contentArea.addEventListener("pageshow", pageShowEventHandlers, true); contentArea.addEventListener("focus", contentAreaFrameFocus, true); // set default character set if provided if ("arguments" in window && window.arguments.length > 1 && window.arguments[1]) { if (window.arguments[1].indexOf("charset=") != -1) { var arrayArgComponents = window.arguments[1].split("="); if (arrayArgComponents) { //we should "inherit" the charset menu setting in a new window getMarkupDocumentViewer().defaultCharacterSet = arrayArgComponents[1]; } } } //initConsoleListener(); // hook up UI through progress listener getBrowser().addProgressListener(window.XULBrowserWindow, Components.interfaces.nsIWebProgress.NOTIFY_ALL); // load appropriate initial page from commandline var isPageCycling = false; // page cycling for tinderbox tests if (!appCore.cmdLineURLUsed) isPageCycling = appCore.startPageCycler(); // only load url passed in when we're not page cycling if (!isPageCycling) { var uriToLoad = ""; // Check window.arguments[0]. If not null then use it for uriArray // otherwise the new window is being called when another browser // window already exists so use the New Window pref for uriArray if ("arguments" in window && window.arguments.length >= 1) { var uriArray; if (window.arguments[0]) { uriArray = window.arguments[0].toString().split('\n'); // stringify and split } else { try { switch (pref.getIntPref("browser.windows.loadOnNewWindow")) { default: uriArray = ["about:blank"]; break; case 1: uriArray = getHomePage(); break; case 2: var history = Components.classes["@mozilla.org/browser/global-history;2"] .getService(Components.interfaces.nsIBrowserHistory); uriArray = [history.lastPageVisited]; break; } } catch(e) { uriArray = ["about:blank"]; } } uriToLoad = uriArray.splice(0, 1)[0]; if (uriArray.length > 0) window.setTimeout(function(arg) { for (var i in arg) gBrowser.addTab(arg[i]); }, 0, uriArray); } if (/^\s*$/.test(uriToLoad)) uriToLoad = "about:blank"; var browser = getBrowser(); if (uriToLoad != "about:blank") { gURLBar.value = uriToLoad; browser.userTypedValue = uriToLoad; if ("arguments" in window && window.arguments.length >= 4) { loadURI(uriToLoad, window.arguments[2], window.arguments[3]); } else if ("arguments" in window && window.arguments.length == 3) { loadURI(uriToLoad, window.arguments[2]); } else { loadURI(uriToLoad); } } // Focus the content area unless we're loading a blank page, or if // we weren't passed any arguments. This "breaks" the // javascript:window.open(); case where we don't get any arguments // either, but we're loading about:blank, but focusing the content // are is arguably correct in that case as well since the opener // is very likely to put some content in the new window, and then // the focus should be in the content area. var navBar = document.getElementById("nav-bar"); if ("arguments" in window && 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 ); // hook up browser access support window.browserDOMWindow = new nsBrowserAccess(); // hook up remote support if (REMOTESERVICE_CONTRACTID in Components.classes) { var remoteService = Components.classes[REMOTESERVICE_CONTRACTID] .getService(Components.interfaces.nsIRemoteService); remoteService.registerWindow(window); var observerService = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); observerService.addObserver(gTabOpenObserver, "open-new-tab-request", false); } } // called when we go into full screen, even if it is // initiated by a web page script addEventListener("fullscreen", onFullScreen, true); addEventListener("PopupCountChanged", UpdateStatusBarPopupIcon, true); addEventListener("AppCommand", HandleAppCommandEvent, true); // does clicking on the urlbar select its contents? gClickSelectsAll = pref.getBoolPref("browser.urlbar.clickSelectsAll"); gClickAtEndSelects = pref.getBoolPref("browser.urlbar.clickAtEndSelects"); // BiDi UI gShowBiDi = isBidiEnabled(); if (gShowBiDi) { document.getElementById("documentDirection-swap").hidden = false; document.getElementById("textfieldDirection-separator").hidden = false; document.getElementById("textfieldDirection-swap").hidden = false; } // now load bookmarks after a delay setTimeout(LoadBookmarksCallback, 0); } function LoadBookmarksCallback() { // loads the services initServices(); initBMService(); BMSVC.readBookmarks(); var bt = document.getElementById("bookmarks-ptf"); if (bt) { bt.database.AddObserver(BookmarksToolbarRDFObserver); } window.addEventListener("resize", BookmarksToolbar.resizeFunc, false); controllers.appendController(BookmarksMenuController); } function WindowFocusTimerCallback(element) { // This fuction is a redo of the fix for jag bug 91884 var ww = Components.classes["@mozilla.org/embedcomp/window-watcher;1"] .getService(Components.interfaces.nsIWindowWatcher); if (window == ww.activeWindow) { element.focus(); } else { // set the element in command dispatcher so focus will restore properly // when the window does become active if (element instanceof Components.interfaces.nsIDOMWindow) { document.commandDispatcher.focusedWindow = element; document.commandDispatcher.focusedElement = null; } else if (element instanceof Components.interfaces.nsIDOMElement) { document.commandDispatcher.focusedWindow = element.ownerDocument.defaultView; document.commandDispatcher.focusedElement = element; } } } function BrowserFlushBookmarksAndHistory() { // Flush bookmarks and history (used when window closes or is cached). try { // If bookmarks are dirty, flush 'em to disk var bmks = Components.classes["@mozilla.org/browser/bookmarks-service;1"] .getService(Components.interfaces.nsIRDFRemoteDataSource); bmks.Flush(); // give history a chance at flushing to disk also var history = Components.classes["@mozilla.org/browser/global-history;2"] .getService(Components.interfaces.nsIRDFRemoteDataSource); history.Flush(); } catch(ex) { } } function Shutdown() { // remove remote support if (REMOTESERVICE_CONTRACTID in Components.classes) { var observerService = Components.classes["@mozilla.org/observer-service;1"] .getService(Components.interfaces.nsIObserverService); observerService.removeObserver(gTabOpenObserver, "open-new-tab-request", false); } // shut down browser access support window.browserDOMWindow = null; try { getBrowser().removeProgressListener(window.XULBrowserWindow); } catch (ex) { } var bt = document.getElementById("bookmarks-ptf"); if (bt) { bt.database.RemoveObserver(BookmarksToolbarRDFObserver); } controllers.removeController(BookmarksMenuController); window.XULBrowserWindow.destroy(); window.XULBrowserWindow = null; window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIWebNavigation) .QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner .QueryInterface(Components.interfaces.nsIInterfaceRequestor) .getInterface(Components.interfaces.nsIXULWindow) .XULBrowserWindow = null; BrowserFlushBookmarksAndHistory(); // unregister us as a pref listener removePrefListener(gButtonPrefListener); removePrefListener(gTabStripPrefListener); removePrefListener(gHomepagePrefListener); removePrefListener(gStatusBarPopupIconPrefListener); removePopupPermListener(gPopupPermListener); window.browserContentListener.close(); // Close the app core. if (appCore) appCore.close(); } function Translate() { var service = pref.getComplexValue("browser.translation.service", Components.interfaces.nsIPrefLocalizedString).data; var serviceDomain = pref.getComplexValue("browser.translation.serviceDomain", Components.interfaces.nsIPrefLocalizedString).data; var targetURI = getWebNavigation().currentURI.spec; // if we're already viewing a translated page, then just reload if (targetURI.indexOf(serviceDomain) >= 0) BrowserReload(); else { loadURI(encodeURI(service + targetURI)); } } function gotoHistoryIndex(aEvent) { var index = aEvent.target.getAttribute("index"); if (!index) return false; if (index == "back") gBrowser.goBackGroup(); else if (index == "forward") gBrowser.goForwardGroup(); else { try { getWebNavigation().gotoIndex(index); } catch(ex) { return false; } } return true; } function BrowserBack() { try { getBrowser().goBack(); } catch(ex) { } } function BrowserHandleBackspace() { // The order of seeing keystrokes is this: // 1) Chrome, 2) Typeahead, 3) [platform]HTMLBindings.xml // Rather than have typeaheadfind responsible for making VK_BACK // go back in history, we handle backspace it here as follows: // When backspace is pressed, it might mean back // in typeaheadfind if that's active, or it might mean back in history var typeAhead = null; const TYPE_AHEAD_FIND_CONTRACTID = "@mozilla.org/suitetypeaheadfind;1"; if (TYPE_AHEAD_FIND_CONTRACTID in Components.classes) { typeAhead = Components.classes[TYPE_AHEAD_FIND_CONTRACTID] .getService(Components.interfaces.nsISuiteTypeAheadFind); } if (!typeAhead || !typeAhead.backOneChar()) { switch (pref.getIntPref("browser.backspace_action")) { case 0: BrowserBack(); break; case 1: goDoCommand("cmd_scrollPageUp"); break; } } } function BrowserForward() { try { getBrowser().goForward(); } catch(ex) { } } function BrowserUp() { loadURI(getBrowser().currentURI.spec.replace(/[#?].*$/, "").replace(/\/[^\/]*.$/, "/")); } function BrowserHandleShiftBackspace() { switch (pref.getIntPref("browser.backspace_action")) { case 0: BrowserForward(); break; case 1: goDoCommand("cmd_scrollPageDown"); break; } } function SetGroupHistory(popupMenu, direction) { while (popupMenu.firstChild) popupMenu.removeChild(popupMenu.firstChild); var menuItem = document.createElementNS(XUL_NAMESPACE, "menuitem"); var label = gNavigatorBundle.getString("tabs.historyItem"); menuItem.setAttribute("label", label); menuItem.setAttribute("index", direction); popupMenu.appendChild(menuItem); } function BrowserBackMenu(event) { if (gBrowser.backBrowserGroup.length != 0) { SetGroupHistory(event.target, "back"); return true; } return FillHistoryMenu(event.target, "back"); } function BrowserForwardMenu(event) { if (gBrowser.forwardBrowserGroup.length != 0) { SetGroupHistory(event.target, "forward"); return true; } return FillHistoryMenu(event.target, "forward"); } function BrowserStop() { try { const stopFlags = nsIWebNavigation.STOP_ALL; getWebNavigation().stop(stopFlags); } catch(ex) { } } function BrowserReload() { const reloadFlags = nsIWebNavigation.LOAD_FLAGS_NONE; return BrowserReloadWithFlags(reloadFlags); } function BrowserReloadSkipCache() { // Bypass proxy and cache. const reloadFlags = nsIWebNavigation.LOAD_FLAGS_BYPASS_PROXY | nsIWebNavigation.LOAD_FLAGS_BYPASS_CACHE; return BrowserReloadWithFlags(reloadFlags); } function BrowserHome(aEvent) { var tab; var homePage = getHomePage(); var target = !gBrowser ? "window": !aEvent ? "current" : BookmarksUtils.getBrowserTargetFromEvent(aEvent); if (homePage.length == 1) { switch (target) { case "current": loadURI(homePage[0]); break; case "tab": tab = gBrowser.addTab(homePage[0]); if (!BookmarksUtils.shouldLoadTabInBackground(aEvent)) gBrowser.selectedTab = tab; break; case "window": openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", homePage[0]); } } else { if (target == "window") openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", homePage.join("\n")); else { var URIs = []; for (var i in homePage) URIs.push({URI: homePage[i]}); tab = gBrowser.loadGroup(URIs); if (!BookmarksUtils.shouldLoadTabInBackground(aEvent)) gBrowser.selectedTab = tab; } } } 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 updateGroupmarkCommand() { const disabled = (!gBrowser || gBrowser.browsers.length == 1); document.getElementById("Browser:AddGroupmarkAs") .setAttribute("disabled", disabled); } function readRDFString(aDS,aRes,aProp) { var n = aDS.GetTarget(aRes, aProp, true); return n ? n.QueryInterface(Components.interfaces.nsIRDFLiteral).Value : ""; } function ensureDefaultEnginePrefs(aRDF,aDS) { var mPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); var defaultName = mPrefs.getComplexValue("browser.search.defaultenginename", Components.interfaces.nsIPrefLocalizedString).data; var kNC_Root = aRDF.GetResource("NC:SearchEngineRoot"); var kNC_child = aRDF.GetResource("http://home.netscape.com/NC-rdf#child"); var kNC_Name = aRDF.GetResource("http://home.netscape.com/NC-rdf#Name"); var arcs = aDS.GetTargets(kNC_Root, kNC_child, true); while (arcs.hasMoreElements()) { var engineRes = arcs.getNext().QueryInterface(Components.interfaces.nsIRDFResource); var name = readRDFString(aDS, engineRes, kNC_Name); if (name == defaultName) mPrefs.setCharPref("browser.search.defaultengine", engineRes.Value); } } 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); var kNC_Name = rdf.GetResource("http://home.netscape.com/NC-rdf#Name"); var defaultEngine; try { defaultEngine = mPrefs.getCharPref("browser.search.defaultengine"); } catch(ex) { ensureDefaultEnginePrefs(rdf, ds); defaultEngine = mPrefs.getCharPref("browser.search.defaultengine"); } } function getSearchUrl(attr) { var rdf = Components.classes["@mozilla.org/rdf/rdf-service;1"].getService(Components.interfaces.nsIRDFService); var ds = rdf.GetDataSource("rdf:internetsearch"); var kNC_Root = rdf.GetResource("NC:SearchEngineRoot"); var mPrefs = Components.classes["@mozilla.org/preferences-service;1"].getService(Components.interfaces.nsIPrefBranch); var defaultEngine = mPrefs.getCharPref("browser.search.defaultengine"); var engineRes = rdf.GetResource(defaultEngine); var prop = "http://home.netscape.com/NC-rdf#" + attr; var kNC_attr = rdf.GetResource(prop); var searchURL = readRDFString(ds, engineRes, kNC_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 (gBrowser.userTypedValue !== null) return document.getElementById("urlbar").value; return ""; } function OpenSearch(tabName, searchStr, newWindowOrTabFlag, reverseBackgroundPref) { //This function needs to be split up someday. var autoOpenSearchPanel = false; var defaultSearchURL = null; var fallbackDefaultSearchURL = gNavigatorRegionBundle.getString("fallbackDefaultSearchURL"); ensureSearchPref() //Check to see if search string contains "://" or "ftp." or white space. //If it does treat as url and match for pattern var urlmatch= /(:\/\/|^ftp\.)[^ \S]+$/ var forceAsURL = urlmatch.test(searchStr); try { autoOpenSearchPanel = pref.getBoolPref("browser.search.opensidebarsearchpanel"); defaultSearchURL = pref.getComplexValue("browser.search.defaulturl", Components.interfaces.nsIPrefLocalizedString).data; } catch (ex) { } // Fallback to a default url (one that we can get sidebar search results for) if (!defaultSearchURL) defaultSearchURL = fallbackDefaultSearchURL; if (!searchStr) { BrowserSearchInternet(); } else { //Check to see if location bar field is a url //If it is a url go to URL. A Url is "://" or "." as commented above //Otherwise search on entry if (forceAsURL) { BrowserLoadURL() } else { if (searchStr) { var escapedSearchStr = encodeURIComponent(searchStr); defaultSearchURL += escapedSearchStr; var searchDS = Components.classes["@mozilla.org/rdf/datasource;1?name=internetsearch"] .getService(Components.interfaces.nsIInternetSearchService); searchDS.RememberLastSearchText(escapedSearchStr); try { var searchEngineURI = pref.getCharPref("browser.search.defaultengine"); if (searchEngineURI) { var searchURL = getSearchUrl("actionButton"); if (searchURL) { defaultSearchURL = searchURL + escapedSearchStr; } else { searchURL = searchDS.GetInternetSearchURL(searchEngineURI, escapedSearchStr, 0, 0, {value:0}); if (searchURL) defaultSearchURL = searchURL; } } } catch (ex) { } if (!newWindowOrTabFlag) loadURI(defaultSearchURL); else if (!pref.getBoolPref("browser.search.opentabforcontextsearch")) window.open(defaultSearchURL, "_blank"); else { var newTab = gBrowser.addTab(defaultSearchURL); var loadInBackground = pref.getBoolPref("browser.tabs.loadInBackground"); if (reverseBackgroundPref) loadInBackground = !loadInBackground; if (!loadInBackground) gBrowser.selectedTab = newTab; } } } } // should we try and open up the sidebar to show the "Search Results" panel? if (autoOpenSearchPanel) RevealSearchPanel(); } function RevealSearchPanel() { // first lets check if the search panel will be shown at all // by checking the sidebar datasource to see if there is an entry // for the search panel, and if it is excluded for navigator or not var searchPanelExists = false; if (document.getElementById("urn:sidebar:panel:search")) { var myPanel = document.getElementById("urn:sidebar:panel:search"); var panel = sidebarObj.panels.get_panel_from_header_node(myPanel); searchPanelExists = !panel.is_excluded(); } else if (sidebarObj.never_built) { try{ var datasource = RDF.GetDataSourceBlocking(sidebarObj.datasource_uri); var aboutValue = RDF.GetResource("urn:sidebar:panel:search"); // check if the panel is even in the list by checking for its content var contentProp = RDF.GetResource("http://home.netscape.com/NC-rdf#content"); var content = datasource.GetTarget(aboutValue, contentProp, true); if (content instanceof Components.interfaces.nsIRDFLiteral){ // the search panel entry exists, now check if it is excluded // for navigator var excludeProp = RDF.GetResource("http://home.netscape.com/NC-rdf#exclude"); var exclude = datasource.GetTarget(aboutValue, excludeProp, true); if (exclude instanceof Components.interfaces.nsIRDFLiteral) { searchPanelExists = (exclude.Value.indexOf("navigator:browser") < 0); } else { // panel exists and no exclude set searchPanelExists = true; } } } catch(e){ searchPanelExists = false; } } if (searchPanelExists) { // make sure the sidebar is open, else SidebarSelectPanel() will fail if (sidebar_is_hidden()) SidebarShowHide(); if (sidebar_is_collapsed()) SidebarExpandCollapse(); 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) { openTopWin(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); var searchURL = searchDS.GetInternetSearchURL(searchEngineURI, "ABC", 0, 0, {value:0}); if (searchURL) { searchRoot = searchURL.match(/^[^:]+:\/\/[^?/]+/i); if (searchRoot) { openTopWin(searchRoot + "/"); return; } } } } } catch (ex) { } // Fallback if the stuff above fails: use the hard-coded search engine openTopWin(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 var params = { browser: window, action: null, url: "" }; openDialog("chrome://communicator/content/openLocation.xul", "_blank", "chrome,modal,titlebar", params); var url = getShortcutOrURI(params.url); switch (params.action) { case "0": // current window loadURI(url, null, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); break; case "1": // new window openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); break; case "2": // edit editPage(url); break; case "3": // new tab gBrowser.selectedTab = gBrowser.addTab(url, null, null, false, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); break; } } function BrowserOpenTab() { if (!gInPrintPreviewMode) { var uriToLoad; try { switch ( pref.getIntPref("browser.tabs.loadOnNewTab") ) { default: uriToLoad = "about:blank"; break; case 1: uriToLoad = pref.getComplexValue("browser.startup.homepage", Components.interfaces.nsIPrefLocalizedString).data; break; case 2: uriToLoad = gBrowser ? getWebNavigation().currentURI.spec : Components.classes["@mozilla.org/browser/global-history;2"] .getService(Components.interfaces.nsIBrowserHistory) .lastPageVisited; break; } } catch(e) { uriToLoad = "about:blank"; } // Open a new window if someone requests a new tab when no browser window is open if (!gBrowser) { openDialog(getBrowserURL(), "_blank", "chrome,all,dialog=no", uriToLoad); return; } gBrowser.selectedTab = gBrowser.addTab(uriToLoad); var navBar = document.getElementById("nav-bar"); if (uriToLoad == "about:blank" && !navBar.hidden && window.locationbar.visible) setTimeout("gURLBar.focus();", 0); else setTimeout("content.focus();", 0); } } /* Show file picker dialog configured for opening a file, and return * the selected nsIFileURL instance. */ function selectFileToOpen(label, prefRoot) { var fileURL = null; // Get filepicker component. const nsIFilePicker = Components.interfaces.nsIFilePicker; var fp = Components.classes["@mozilla.org/filepicker;1"].createInstance(nsIFilePicker); fp.init(window, gNavigatorBundle.getString(label), nsIFilePicker.modeOpen); fp.appendFilters(nsIFilePicker.filterAll | nsIFilePicker.filterText | nsIFilePicker.filterImages | nsIFilePicker.filterXML | nsIFilePicker.filterHTML); const filterIndexPref = prefRoot + "filterIndex"; const lastDirPref = prefRoot + "dir"; // use a pref to remember the filterIndex selected by the user. var index = 0; try { index = pref.getIntPref(filterIndexPref); } catch (ex) { } fp.filterIndex = index; // use a pref to remember the displayDirectory selected by the user. try { fp.displayDirectory = pref.getComplexValue(lastDirPref, Components.interfaces.nsILocalFile); } catch (ex) { } if (fp.show() == nsIFilePicker.returnOK) { pref.setIntPref(filterIndexPref, fp.filterIndex); pref.setComplexValue(lastDirPref, Components.interfaces.nsILocalFile, fp.file.parent); fileURL = fp.fileURL; } return fileURL; } function BrowserOpenFileWindow() { try { openTopWin(selectFileToOpen("openFile", "browser.open.").spec); } catch (e) {} } function BrowserEditBookmarks() { toOpenWindowByType("bookmarks:manager", "chrome://communicator/content/bookmarks/bookmarksManager.xul"); } function updateCloseItems() { var browser = getBrowser(); if (browser && browser.getStripVisibility()) { document.getElementById('menu_closeOtherTabs').hidden = false; if (browser.tabContainer.childNodes.length > 1) { document.getElementById('menu_close').setAttribute('label', gNavigatorBundle.getString('tabs.closeTab.label')); document.getElementById('menu_close').setAttribute('accesskey', gNavigatorBundle.getString('tabs.closeTab.accesskey')); document.getElementById('cmd_closeOtherTabs').removeAttribute('disabled'); document.getElementById('menu_closeWindow').hidden = false; } else { document.getElementById('menu_close').setAttribute('label', gNavigatorBundle.getString('tabs.close.label')); document.getElementById('menu_close').setAttribute('accesskey', gNavigatorBundle.getString('tabs.close.accesskey')); document.getElementById('cmd_closeOtherTabs').setAttribute('disabled', 'true'); document.getElementById('menu_closeWindow').hidden = true; } } else { document.getElementById('menu_close').setAttribute('label', gNavigatorBundle.getString('tabs.close.label')); document.getElementById('menu_close').setAttribute('accesskey', gNavigatorBundle.getString('tabs.close.accesskey')); document.getElementById('menu_closeWindow').hidden = true; document.getElementById('menu_closeOtherTabs').hidden = true; } var recentTabsItem = document.getElementById("menu_recentTabs"); recentTabsItem.setAttribute("disabled", !browser || browser.getUndoList().length == 0); } function updateRecentTabs(menupopup) { var browser = getBrowser(); while (menupopup.hasChildNodes()) menupopup.removeChild(menupopup.lastChild); var list = browser.getUndoList(); for (var i = 0; i < list.length; i++) { var menuitem = document.createElement("menuitem"); var label = list[i]; if (i < 9) { label = gNavigatorBundle.getFormattedString("tabs.recentlyClosed.format", [i + 1, label]); menuitem.setAttribute("accesskey", i + 1); } if (i == 0) menuitem.setAttribute("key", "key_restoreTab"); menuitem.setAttribute("label", label); menuitem.setAttribute("value", i); menupopup.appendChild(menuitem); } } function BrowserCloseOtherTabs() { var browser = getBrowser(); browser.removeAllTabsBut(browser.mCurrentTab); } function BrowserCloseTabOrWindow() { var browser = getBrowser(); if (browser.tabContainer.childNodes.length > 1) { // Just close up a tab. browser.removeCurrentTab(); return; } BrowserCloseWindow(); } function BrowserTryToCloseWindow() { //give tryToClose a chance to veto if it is defined if (typeof(window.tryToClose) != "function" || window.tryToClose()) BrowserCloseWindow(); } function BrowserCloseWindow() { // This code replicates stuff in Shutdown(). It is here because // window.screenX and window.screenY have real values. We need // to fix this eventually but by replicating the code here, we // provide a means of saving position (it just requires that the // user close the window via File->Close (vs. close box). // Get the current window position/size. var x = window.screenX; var y = window.screenY; var h = window.outerHeight; var w = window.outerWidth; // Store these into the window attributes (for persistence). var win = document.getElementById( "main-window" ); win.setAttribute( "x", x ); win.setAttribute( "y", y ); win.setAttribute( "height", h ); win.setAttribute( "width", w ); window.close(); } function loadURI(uri, referrer, flags) { try { getBrowser().loadURIWithFlags(uri, flags, referrer); } catch (e) { } } function BrowserLoadURL(aTriggeringEvent) { var url = gURLBar.value; // Remove leading and trailing spaces first url = url.replace(/^\s+/, '').replace(/\s+$/, ''); if (url.match(/^view-source:/)) { BrowserViewSourceOfURL(url.replace(/^view-source:/, ""), null, null); } else { // Check the pressed modifiers: (also see bug 97123) // Modifier Mac | Modifier PC | Action // -------------+-------------+----------- // Command | Control | New Window/Tab // Shift+Cmd | Shift+Ctrl | New Window/Tab behind current one // Option | Shift | Save URL (show Filepicker) // If false, the save modifier is Alt, which is Option on Mac. var modifierIsShift = true; try { modifierIsShift = pref.getBoolPref("ui.key.saveLink.shift"); } catch (ex) {} var shiftPressed = false; var saveModifier = false; // if the save modifier was pressed if (aTriggeringEvent && 'shiftKey' in aTriggeringEvent && 'altKey' in aTriggeringEvent) { saveModifier = modifierIsShift ? aTriggeringEvent.shiftKey : aTriggeringEvent.altKey; shiftPressed = aTriggeringEvent.shiftKey; } var browser = getBrowser(); url = getShortcutOrURI(url); // Accept both Control and Meta (=Command) as New-Window-Modifiers if (aTriggeringEvent && (('ctrlKey' in aTriggeringEvent && aTriggeringEvent.ctrlKey) || ('metaKey' in aTriggeringEvent && aTriggeringEvent.metaKey))) { // Check if user requests Tabs instead of windows var openTab = false; try { openTab = pref.getBoolPref("browser.tabs.opentabfor.urlbar"); } catch (ex) {} if (openTab) { // Open link in new tab var t = browser.addTab(url, null, null, false, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); // Focus new tab unless shift is pressed if (!shiftPressed) { browser.userTypedValue = null; browser.selectedTab = t; } } else { // Open a new window with the URL var newWin = openDialog(getBrowserURL(), "_blank", "all,dialog=no", url, null, null, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); // Reset url in the urlbar, copied from handleURLBarRevert() var oldURL = browser.currentURI.spec; if (oldURL != "about:blank" || content.opener) { gURLBar.value = oldURL; SetPageProxyState("valid", null); } else gURLBar.value = ""; browser.userTypedValue = null; // Focus old window if shift was pressed, as there's no // way to open a new window in the background // XXX this doesn't seem to work if (shiftPressed) { //newWin.blur(); content.focus(); } } } else if (saveModifier) { try { // Firstly, fixup the url so that (e.g.) "www.foo.com" works const nsIURIFixup = Components.interfaces.nsIURIFixup; if (!gURIFixup) gURIFixup = Components.classes["@mozilla.org/docshell/urifixup;1"] .getService(nsIURIFixup); url = gURIFixup.createFixupURI(url, nsIURIFixup.FIXUP_FLAGS_MAKE_ALTERNATE_URI).spec; // Open filepicker to save the url saveURL(url, ""); } catch(ex) { // XXX Do nothing for now. // Do we want to put up an alert in the future? Mmm, l10n... } } else { // No modifier was pressed, load the URL normally and // focus the content area loadURI(url, null, nsIWebNavigation.LOAD_FLAGS_ALLOW_THIRD_PARTY_FIXUP); content.focus(); } } } function getShortcutOrURI(url) { // rjc: added support for URL shortcuts (3/30/1999) try { if (!gBookmarksService) gBookmarksService = Components.classes["@mozilla.org/browser/bookmarks-service;1"] .getService(Components.interfaces.nsIBookmarksService); var shortcutURL = gBookmarksService.resolveKeyword(url); if (!shortcutURL) { // rjc: add support for string substitution with shortcuts (4/4/2000) // (see bug # 29871 for details) var aOffset = url.indexOf(" "); if (aOffset > 0) { var cmd = url.substr(0, aOffset); var text = url.substr(aOffset+1); shortcutURL = gBookmarksService.resolveKeyword(cmd); // Bug 123006 : %s replace and URI escape, %S replace with raw value if (shortcutURL && text) { var encodedText = null; var charset = ""; const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/; var matches = shortcutURL.match(re); if (matches) { shortcutURL = matches[1]; charset = matches[2]; } else if (/%s/.test(shortcutURL)) { try { charset = BMSVC.getLastCharset(shortcutURL); } catch (ex) { } } if (charset) encodedText = escape(convertFromUnicode(charset, text)); else // default case: charset=UTF-8 encodedText = encodeURIComponent(text); if (encodedText && /%[sS]/.test(shortcutURL)) shortcutURL = shortcutURL.replace(/%s/g, encodedText) .replace(/%S/g, text); else shortcutURL = null; } } } if (shortcutURL) url = shortcutURL; } catch (ex) { } return url; } function readFromClipboard() { var url; try { // Get clipboard. var clipboard = Components.classes["@mozilla.org/widget/clipboard;1"] .getService(Components.interfaces.nsIClipboard); // Create tranferable that will transfer the text. var trans = Components.classes["@mozilla.org/widget/transferable;1"] .createInstance(Components.interfaces.nsITransferable); trans.addDataFlavor("text/unicode"); // If available, use selection clipboard, otherwise global one if (clipboard.supportsSelectionClipboard()) clipboard.getData(trans, clipboard.kSelectionClipboard); else clipboard.getData(trans, clipboard.kGlobalClipboard); var data = {}; var dataLen = {}; trans.getTransferData("text/unicode", data, dataLen); if (data) { data = data.value.QueryInterface(Components.interfaces.nsISupportsString); url = data.data.substring(0, dataLen.value / 2); } } catch (ex) { } return url; } function BrowserViewSourceOfDocument(aDocument) { var docCharset; var pageCookie; var webNav; // Get the document charset docCharset = "charset=" + aDocument.characterSet; // Get the nsIWebNavigation associated with the document try { var win; var ifRequestor; // Get the DOMWindow for the requested document. If the DOMWindow // cannot be found, then just use the content window... // // XXX: This is a bit of a hack... win = aDocument.defaultView; if (win == window) { win = content; } ifRequestor = win.QueryInterface(Components.interfaces.nsIInterfaceRequestor); webNav = ifRequestor.getInterface(Components.interfaces.nsIWebNavigation); } catch(err) { // If nsIWebNavigation cannot be found, just get the one for the whole // window... webNav = getWebNavigation(); } // // Get the 'PageDescriptor' for the current document. This allows the // view-source to access the cached copy of the content rather than // refetching it from the network... // try{ var PageLoader = webNav.QueryInterface(Components.interfaces.nsIWebPageDescriptor); pageCookie = PageLoader.currentDescriptor; } catch(err) { // If no page descriptor is available, just use the view-source URL... } BrowserViewSourceOfURL(webNav.currentURI.spec, docCharset, pageCookie); } function BrowserViewSourceOfURL(url, charset, pageCookie) { // try to open a view-source window while inheriting the charset (if any) openDialog("chrome://navigator/content/viewSource.xul", "_blank", "all,dialog=no", url, charset, pageCookie); } // doc=null for regular page info, doc=owner document for frame info. function BrowserPageInfo(doc, initialTab) { window.openDialog("chrome://navigator/content/pageinfo/pageInfo.xul", "_blank", "chrome,dialog=no", {doc: doc, initialTab: initialTab}); } function hiddenWindowStartup() { // focus the hidden window window.focus(); // Disable menus which are not appropriate var disabledItems = ['cmd_close', 'Browser:SendPage', 'Browser:EditPage', 'Browser:SavePage', 'cmd_printSetup', 'Browser:Print', 'canGoBack', 'canGoForward', 'Browser:AddBookmark', 'Browser:AddBookmarkAs', 'cmd_undo', 'cmd_redo', 'cmd_cut', 'cmd_copy', 'cmd_paste', 'cmd_delete', 'cmd_selectAll', 'cmd_findTypeText', 'cmd_findTypeLinks', 'Browser:Find', 'Browser:FindAgain', 'Browser:FindPrev', 'menu_Toolbars', 'menuitem_reload', 'menu_UseStyleSheet', 'charsetMenu', 'View:PageSource', 'View:PageInfo', 'menu_translate', 'BlockCookies', 'UseCookiesDefault', 'AllowSessionCookies', 'AllowCookies', 'BlockImages', 'UseImagesDefault', 'AllowImages', 'AllowPopups', 'menu_zoom', 'cmd_minimizeWindow', 'cmd_zoomWindow']; var broadcaster; for (var id in disabledItems) { broadcaster = document.getElementById(disabledItems[id]); if (broadcaster) broadcaster.setAttribute("disabled", "true"); } // also hide the window list separator var separator = document.getElementById("sep-window-list"); if (separator) separator.setAttribute("hidden", "true"); // Get the preferences service var prefService = Components.classes["@mozilla.org/preferences-service;1"] .getService(Components.interfaces.nsIPrefService); pref = prefService.getBranch(null); // init string bundles gNavigatorBundle = document.getElementById("bundle_navigator"); gNavigatorRegionBundle = document.getElementById("bundle_navigator_region"); gBrandBundle = document.getElementById("bundle_brand"); // now load bookmarks after a delay setTimeout(hiddenWindowLoadBookmarksCallback, 0); } function hiddenWindowLoadBookmarksCallback() { // loads the services initServices(); initBMService(); BMSVC.readBookmarks(); } var consoleListener = { observe: function (aMsgObject) { const nsIScriptError = Components.interfaces.nsIScriptError; var scriptError = aMsgObject.QueryInterface(nsIScriptError); var isWarning = scriptError.flags & nsIScriptError.warningFlag != 0; if (!isWarning) { var statusbarDisplay = document.getElementById("statusbar-display"); statusbarDisplay.setAttribute("error", "true"); statusbarDisplay.addEventListener("click", loadErrorConsole, true); statusbarDisplay.label = gNavigatorBundle.getString("jserror"); this.isShowingError = true; } }, // whether or not an error alert is being displayed isShowingError: false }; function initConsoleListener() { /** * XXX - console launch hookup requires some work that I'm not sure * how to do. * * 1) ideally, the notification would disappear when the * document that had the error was flushed. how do I know when * this happens? All the nsIScriptError object I get tells me * is the URL. Where is it located in the content area? * 2) the notification service should not display chrome * script errors. web developers and users are not interested * in the failings of our shitty, exception unsafe js. One * could argue that this should also extend to the console by * default (although toggle-able via setting for chrome * authors) At any rate, no status indication should be given * for chrome script errors. * * As a result I am commenting out this for the moment. * var consoleService = Components.classes["@mozilla.org/consoleservice;1"] .getService(Components.interfaces.nsIConsoleService); if (consoleService) consoleService.registerListener(consoleListener); */ } function loadErrorConsole(aEvent) { if (aEvent.detail == 2) toJavaScriptConsole(); } function clearErrorNotification() { var statusbarDisplay = document.getElementById("statusbar-display"); statusbarDisplay.removeAttribute("error"); statusbarDisplay.removeEventListener("click", loadErrorConsole, true); consoleListener.isShowingError = false; } const NS_URLWIDGET_CONTRACTID = "@mozilla.org/urlwidget;1"; var urlWidgetService = null; if (NS_URLWIDGET_CONTRACTID in Components.classes) { urlWidgetService = Components.classes[NS_URLWIDGET_CONTRACTID] .getService(Components.interfaces.nsIUrlWidget); } //Posts the currently displayed url to a native widget so third-party apps can observe it. function postURLToNativeWidget() { if (urlWidgetService) { var url = getWebNavigation().currentURI.spec; try { urlWidgetService.SetURLToHiddenControl(url, window); } catch(ex) { } } } function checkForDirectoryListing() { if ( "HTTPIndex" in content && content.HTTPIndex instanceof Components.interfaces.nsIHTTPIndex ) { content.defaultCharacterset = getMarkupDocumentViewer().defaultCharacterSet; } } /** * Use Stylesheet functions. * Written by Tim Hill (bug 6782) * Frameset handling by Neil Rashbrook **/ /** * Adds this frame's stylesheet sets to the View > Use Style submenu * * If the frame has no preferred stylesheet set then the "Default style" * menuitem should be shown. Note that it defaults to checked, hidden. * * If this frame has a selected stylesheet set then its menuitem should * be checked (unless the "None" style is currently selected), and the * "Default style" menuitem should to be unchecked. * * The stylesheet sets may match those of other frames. In that case, the * checkmark should be removed from sets that are not selected in this frame. * * @param menuPopup The submenu's popup child * @param frame The frame whose sets are to be added * @param styleDisabled True if the "None" style is currently selected * @param itemPersistentOnly The "Default style" menuitem element */ function stylesheetFillFrame(menuPopup, frame, styleDisabled, itemPersistentOnly) { if (!frame.document.preferredStyleSheetSet) itemPersistentOnly.hidden = false; var title = frame.document.selectedStyleSheetSet; if (title) itemPersistentOnly.removeAttribute("checked"); var styleSheetSets = frame.document.styleSheetSets; for (var i = 0; i < styleSheetSets.length; i++) { var styleSheetSet = styleSheetSets[i]; var menuitem = menuPopup.getElementsByAttribute("data", styleSheetSet).item(0); if (menuitem) { if (styleSheetSet != title) menuitem.removeAttribute("checked"); } else { var menuItem = document.createElement("menuitem"); menuItem.setAttribute("type", "radio"); menuItem.setAttribute("label", styleSheetSet); menuItem.setAttribute("data", styleSheetSet); menuItem.setAttribute("checked", styleSheetSet == title && !styleDisabled); menuPopup.appendChild(menuItem); } } } /** * Adds all available stylesheet sets to the View > Use Style submenu * * If all frames have preferred stylesheet sets then the "Default style" * menuitem should remain hidden, otherwise it should be shown, and * if some frames have a selected stylesheet then the "Default style" * menuitem should be unchecked, otherwise it should remain checked. * * A stylesheet set's menuitem should not be checked if the "None" style * is currently selected. Otherwise a stylesheet set may be available in * more than one frame. In such a case the menuitem should only be checked * if it is selected in all frames in which it is available. * * @param menuPopup The submenu's popup child * @param frameset The frameset whose sets are to be added * @param styleDisabled True if the "None" style is currently selected * @param itemPersistentOnly The "Default style" menuitem element */ function stylesheetFillAll(menuPopup, frameset, styleDisabled, itemPersistentOnly) { stylesheetFillFrame(menuPopup, frameset, styleDisabled, itemPersistentOnly); for (var i = 0; i < frameset.frames.length; i++) { stylesheetFillAll(menuPopup, frameset.frames[i], styleDisabled, itemPersistentOnly); } } /** * Populates the View > Use Style submenu with all available stylesheet sets * @param menuPopup The submenu's popup child */ function stylesheetFillPopup(menuPopup) { /* Clear menu */ var itemPersistentOnly = menuPopup.firstChild.nextSibling; while (itemPersistentOnly.nextSibling) menuPopup.removeChild(itemPersistentOnly.nextSibling); /* Reset permanent items */ var styleDisabled = getMarkupDocumentViewer().authorStyleDisabled; menuPopup.firstChild.setAttribute("checked", styleDisabled); itemPersistentOnly.setAttribute("checked", !styleDisabled); itemPersistentOnly.hidden = true; stylesheetFillAll(menuPopup, window.content, styleDisabled, itemPersistentOnly); } /** * Switches all frames in a frameset to the same stylesheet set * * Only frames that support the given title will be switched * * @param frameset The frameset whose frames are to be switched * @param title The name of the stylesheet set to switch to */ function stylesheetSwitchAll(frameset, title) { if (!title || frameset.document.styleSheetSets.contains(title)) { frameset.document.selectedStyleSheetSet = title; } for (var i = 0; i < frameset.frames.length; i++) { stylesheetSwitchAll(frameset.frames[i], title); } } function setStyleDisabled(disabled) { getMarkupDocumentViewer().authorStyleDisabled = disabled; } function applyTheme(themeName) { var name = themeName.getAttribute("internalName"); if (!name) return; var str = Components.classes["@mozilla.org/supports-string;1"].createInstance(Components.interfaces.nsISupportsString); str.data = name; if (pref.getBoolPref("extensions.dss.enabled")) { pref.setComplexValue("general.skins.selectedSkin", Components.interfaces.nsISupportsString, str); return; } pref.setComplexValue("extensions.lastSelectedSkin", Components.interfaces.nsISupportsString, str); var switchPending = str != pref.getComplexValue("general.skins.selectedSkin", Components.interfaces.nsISupportsString); pref.setBoolPref("extensions.dss.switchPending", switchPending); if (switchPending) { var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"].getService(Components.interfaces.nsIPromptService); var dialogTitle = gNavigatorBundle.getString("switchskinstitle"); var brandName = gBrandBundle.getString("brandShortName"); var msg = gNavigatorBundle.getFormattedString("switchskins", [brandName]); promptService.alert(window, dialogTitle, msg); } } function getNewThemes() { // get URL for more themes from prefs try { var formatter = Components.classes["@mozilla.org/toolkit/URLFormatterService;1"] .getService(Components.interfaces.nsIURLFormatter); openTopWin(formatter.formatURLPref("extensions.getMoreThemesURL")); } catch (ex) { dump(ex); } } function URLBarFocusHandler(aEvent) { if (gIgnoreFocus) gIgnoreFocus = false; else if (gClickSelectsAll) gURLBar.select(); } function URLBarMouseDownHandler(aEvent) { if (gURLBar.hasAttribute("focused")) { gIgnoreClick = true; } else { gIgnoreFocus = true; gIgnoreClick = false; gURLBar.setSelectionRange(0, 0); } } function URLBarClickHandler(aEvent) { if (!gIgnoreClick && gClickSelectsAll && gURLBar.selectionStart == gURLBar.selectionEnd) if (gClickAtEndSelects || gURLBar.selectionStart < gURLBar.value.length) gURLBar.select(); } // This function gets the "windows hooks" service and has it check its setting // This will do nothing on platforms other than Windows. function checkForDefaultBrowser() { const NS_WINHOOKS_CONTRACTID = "@mozilla.org/winhooks;1"; var dialogShown = false; if (NS_WINHOOKS_CONTRACTID in Components.classes) { try { dialogShown = Components.classes[NS_WINHOOKS_CONTRACTID] .getService(Components.interfaces.nsIWindowsHooks) .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("nav-bar"); // If it's hidden, show it. if (navBar.getAttribute("hidden") == "true") goToggleToolbar('nav-bar','cmd_viewnavbar'); if (gURLBar.value) gURLBar.select(); else gURLBar.focus(); } // If "ESC" is pressed in the url bar, we replace the urlbar's value with the url of the page // and highlight it, unless it is about:blank, where we reset it to "". function handleURLBarRevert() { var url = getWebNavigation().currentURI.spec; var throbberElement = document.getElementById("navigator-throbber"); var isScrolling = gURLBar.userAction == "scrolling"; // don't revert to last valid url unless page is NOT loading // and user is NOT key-scrolling through autocomplete list if (!throbberElement.hasAttribute("busy") && !isScrolling) { if (url != "about:blank" || content.opener) { gURLBar.value = url; gURLBar.select(); SetPageProxyState("valid", null); // XXX Build a URI and pass it in here. } else { //if about:blank, urlbar becomes "" gURLBar.value = ""; } gBrowser.userTypedValue = null; } // tell widget to revert to last typed text only if the user // was scrolling when they hit escape return isScrolling; } function handleURLBarCommand(aUserAction, aTriggeringEvent) { try { addToUrlbarHistory(gURLBar.value); } catch (ex) { // Things may go wrong when adding url to session history, // but don't let that interfere with the loading of the url. } BrowserLoadURL(aTriggeringEvent); } function UpdatePageProxyState() { if (gURLBar.value != gLastValidURLStr) SetPageProxyState("invalid", null); } function SetPageProxyState(aState, aURI) { if (!gProxyButton) gProxyButton = document.getElementById("page-proxy-button"); if (!gProxyFavIcon) gProxyFavIcon = document.getElementById("page-proxy-favicon"); if (!gProxyDeck) gProxyDeck = document.getElementById("page-proxy-deck"); gProxyButton.setAttribute("pageproxystate", aState); if (aState == "valid") { gLastValidURLStr = gURLBar.value; gURLBar.addEventListener("input", UpdatePageProxyState, false); if (gBrowser.shouldLoadFavIcon(aURI)) { var favStr = gBrowser.buildFavIconString(aURI); if (favStr != gProxyFavIcon.src) { gBrowser.loadFavIcon(aURI, "src", gProxyFavIcon); gProxyDeck.selectedIndex = 0; } else gProxyDeck.selectedIndex = 1; } else { gProxyDeck.selectedIndex = 0; gProxyFavIcon.removeAttribute("src"); } } else if (aState == "invalid") { gURLBar.removeEventListener("input", UpdatePageProxyState, false); gProxyDeck.selectedIndex = 0; } } function PageProxyDragGesture(aEvent) { if (gProxyButton.getAttribute("pageproxystate") == "valid") { nsDragAndDrop.startDrag(aEvent, proxyIconDNDObserver); return true; } return false; } function handlePageProxyClick(aEvent) { switch (aEvent.button) { case 0: // bug 52784 - select location field contents gURLBar.select(); break; case 1: // bug 111337 - load url/keyword from clipboard return middleMousePaste(aEvent); break; } return true; } 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) { 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); } function BrowserFullScreen() { window.fullScreen = !window.fullScreen; } function onFullScreen() { FullScreen.toggle(); } function UpdateStatusBarPopupIcon(aEvent) { if (aEvent && aEvent.originalTarget != gBrowser.getNotificationBox()) return; var showIcon = pref.getBoolPref("privacy.popups.statusbar_icon_enabled"); if (showIcon) { var popupIcon = document.getElementById("popupIcon"); popupIcon.hidden = !gBrowser.getNotificationBox().popupCount; } } function StatusbarViewPopupManager() { var hostPort = ""; try { hostPort = getBrowser().selectedBrowser.currentURI.hostPort; } catch(ex) { } // open whitelist with site prefilled to unblock viewPopups(hostPort); } function popupBlockerMenuShowing(event) { var separator = document.getElementById("popupMenuSeparator"); if (separator) separator.hidden = !createShowPopupsMenu(event.target, gBrowser.selectedBrowser); } function toHistory() { toOpenWindowByType("history:manager", "chrome://communicator/content/history/history.xul"); } function checkTheme(popup) { var prefName = pref.getBoolPref("extensions.dss.switchPending") ? "extensions.lastSelectedSkin" : "general.skins.selectedSkin"; var currentTheme = pref.getComplexValue(prefName, Components.interfaces.nsISupportsString); var menuitem = popup.getElementsByAttribute("internalName", currentTheme)[0]; if (menuitem) menuitem.setAttribute("checked", true); } // opener may not have been initialized by load time (chrome windows only) // so call this function some time later. function maybeInitPopupContext() { // it's not a popup with no opener if (!window.content.opener) return null; try { // are we a popup window? const CI = Components.interfaces; var xulwin = window .QueryInterface(CI.nsIInterfaceRequestor) .getInterface(CI.nsIWebNavigation) .QueryInterface(CI.nsIDocShellTreeItem).treeOwner .QueryInterface(CI.nsIInterfaceRequestor) .getInterface(CI.nsIXULWindow); if (xulwin.contextFlags & CI.nsIWindowCreator2.PARENT_IS_LOADING_OR_RUNNING_TIMEOUT) { // return our opener's URI const IOS = Components.classes["@mozilla.org/network/io-service;1"] .getService(CI.nsIIOService); return IOS.newURI(window.content.opener.location.href, null, null); } } catch(e) { } return null; } function WindowIsClosing() { var browser = getBrowser(); var cn = browser.tabContainer.childNodes; var numtabs = cn.length; var reallyClose = true; if (numtabs > 1) { var shouldPrompt = pref.getBoolPref("browser.tabs.warnOnClose"); if (shouldPrompt) { var promptService = Components.classes["@mozilla.org/embedcomp/prompt-service;1"] .getService(Components.interfaces.nsIPromptService); //default to true: if it were false, we wouldn't get this far var warnOnClose = {value:true}; var buttonPressed = promptService.confirmEx(window, gNavigatorBundle.getString('tabs.closeWarningTitle'), gNavigatorBundle.getFormattedString("tabs.closeWarning", [numtabs]), (promptService.BUTTON_TITLE_IS_STRING * promptService.BUTTON_POS_0) + (promptService.BUTTON_TITLE_CANCEL * promptService.BUTTON_POS_1), gNavigatorBundle.getString('tabs.closeButton'), null, null, gNavigatorBundle.getString('tabs.closeWarningPromptMe'), warnOnClose); reallyClose = (buttonPressed == 0); //don't set the pref unless they press OK and it's false if (reallyClose && !warnOnClose.value) { pref.setBoolPref("browser.tabs.warnOnClose", false); } } //if the warn-me pref was true } //if multiple tabs are open for (var i = 0; reallyClose && i < numtabs; ++i) { var ds = browser.getBrowserForTab(cn[i]).docShell; if (ds.contentViewer && !ds.contentViewer.permitUnload()) reallyClose = false; } return reallyClose; } /** * file upload support */ /* This function returns the URI of the currently focused content frame * or frameset. */ function getCurrentURI() { const CI = Components.interfaces; var focusedWindow = document.commandDispatcher.focusedWindow; var contentFrame = isContentFrame(focusedWindow) ? focusedWindow : window.content; var nav = contentFrame.QueryInterface(CI.nsIInterfaceRequestor) .getInterface(CI.nsIWebNavigation); return nav.currentURI; } function uploadFile(fileURL) { const CI = Components.interfaces; var targetBaseURI = getCurrentURI(); // generate the target URI. we use fileURL.file.leafName to get the // unicode value of the target filename w/o any URI-escaped chars. // this gives the protocol handler the best chance of generating a // properly formatted URI spec. we pass null for the origin charset // parameter since we want the URI to inherit the origin charset // property from targetBaseURI. var leafName = fileURL.file.leafName; const IOS = Components.classes["@mozilla.org/network/io-service;1"] .getService(CI.nsIIOService); var targetURI = IOS.newURI(leafName, null, targetBaseURI); // ok, start uploading... var dialog = Components.classes["@mozilla.org/progressdialog;1"] .createInstance(CI.nsIProgressDialog); var persist = Components.classes["@mozilla.org/embedding/browser/nsWebBrowserPersist;1"] .createInstance(CI.nsIWebBrowserPersist); dialog.init(fileURL, targetURI, leafName, null, Date.now()*1000, null, persist); dialog.open(window); persist.progressListener = dialog; persist.saveURI(fileURL, null, null, null, null, targetURI); } function BrowserUploadFile() { try { uploadFile(selectFileToOpen("uploadFile", "browser.upload.")); } catch (e) {} } /* This function is called whenever the file menu is about to be displayed. * Enable the upload menu item if appropriate. */ function updateFileUploadItem() { var canUpload = false; try { canUpload = getCurrentURI().schemeIs('ftp'); } catch (e) {} var item = document.getElementById('Browser:UploadFile'); if (canUpload) item.removeAttribute('disabled'); else item.setAttribute('disabled', 'true'); } function isBidiEnabled() { var rv = false; var systemLocale; try { var localeService = Components.classes["@mozilla.org/intl/nslocaleservice;1"] .getService(Components.interfaces.nsILocaleService); systemLocale = localeService.getSystemLocale().getCategory("NSILOCALE_CTYPE"); rv = /^(he|ar|syr|fa|ur)-/.test(systemLocale); } catch (e) {} if (!rv) { // check the overriding pref rv = pref.getBoolPref("bidi.browser.ui"); } return rv; } function SwitchDocumentDirection(aWindow) { aWindow.document.dir = (aWindow.document.dir == "ltr" ? "rtl" : "ltr"); for (var run = 0; run < aWindow.frames.length; run++) SwitchDocumentDirection(aWindow.frames[run]); } function updateSavePageItems() { var autoDownload = pref.getBoolPref("browser.download.autoDownload"); goSetMenuValue("savepage", autoDownload ? "valueSave" : "valueSaveAs"); } function convertFromUnicode(charset, str) { try { var unicodeConverter = Components .classes["@mozilla.org/intl/scriptableunicodeconverter"] .createInstance(Components.interfaces.nsIScriptableUnicodeConverter); unicodeConverter.charset = charset; str = unicodeConverter.ConvertFromUnicode(str); return str + unicodeConverter.Finish(); } catch(ex) { return null; } }