2007-10-02 19:08:00 +00:00
# - * - Mode : javascript ; tab - width : 2 ; indent - tabs - mode : nil ; c - basic - offset : 2 - * -
2012-05-21 11:12:37 +00:00
# This Source Code Form is subject to the terms of the Mozilla Public
# License , v . 2.0 . If a copy of the MPL was not distributed with this
# file , You can obtain one at http : //mozilla.org/MPL/2.0/.
2002-08-04 02:53:09 +00:00
2008-01-27 05:08:46 +00:00
let Ci = Components . interfaces ;
let Cu = Components . utils ;
2010-01-28 18:31:45 +00:00
2008-01-27 05:08:46 +00:00
Cu . import ( "resource://gre/modules/XPCOMUtils.jsm" ) ;
2013-10-03 01:27:53 +00:00
Cu . import ( "resource://gre/modules/NotificationDB.jsm" ) ;
2013-03-18 15:46:17 +00:00
Cu . import ( "resource:///modules/RecentWindow.jsm" ) ;
2013-11-19 20:54:03 +00:00
Cu . import ( "resource://gre/modules/WindowsPrefSync.jsm" ) ;
2008-01-27 05:08:46 +00:00
2014-03-14 18:47:46 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "BrowserUtils" ,
"resource://gre/modules/BrowserUtils.jsm" ) ;
2013-06-25 01:26:22 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "Task" ,
"resource://gre/modules/Task.jsm" ) ;
2013-11-26 07:31:52 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "CharsetMenu" ,
2014-01-06 08:44:19 +00:00
"resource://gre/modules/CharsetMenu.jsm" ) ;
2014-01-31 00:16:05 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "ShortcutUtils" ,
"resource://gre/modules/ShortcutUtils.jsm" ) ;
2013-06-25 01:26:22 +00:00
2009-07-13 17:34:13 +00:00
const nsIWebNavigation = Ci . nsIWebNavigation ;
2007-05-20 21:09:42 +00:00
2002-10-13 16:39:47 +00:00
var gLastBrowserCharset = null ;
2002-10-13 22:22:38 +00:00
var gPrevCharset = null ;
2010-09-08 11:39:35 +00:00
var gProxyFavIcon = null ;
2002-08-04 02:53:09 +00:00
var gLastValidURLStr = "" ;
2007-11-09 10:19:12 +00:00
var gInPrintPreviewMode = false ;
2009-10-06 15:58:00 +00:00
var gContextMenu = null ; // nsContextMenu instance
2013-04-23 02:47:34 +00:00
var gMultiProcessBrowser = false ;
2004-05-05 23:24:45 +00:00
2008-01-26 05:48:51 +00:00
# ifndef XP _MACOSX
var gEditUIVisible = true ;
# endif
2008-08-02 22:41:32 +00:00
[
[ "gBrowser" , "content" ] ,
[ "gNavToolbox" , "navigator-toolbox" ] ,
[ "gURLBar" , "urlbar" ] ,
2010-05-19 16:57:16 +00:00
[ "gNavigatorBundle" , "bundle_browser" ]
2008-08-02 22:41:32 +00:00
] . forEach ( function ( elementGlobal ) {
var [ name , id ] = elementGlobal ;
window . _ _defineGetter _ _ ( name , function ( ) {
var element = document . getElementById ( id ) ;
if ( ! element )
return null ;
delete window [ name ] ;
2008-08-03 10:27:30 +00:00
return window [ name ] = element ;
} ) ;
window . _ _defineSetter _ _ ( name , function ( val ) {
delete window [ name ] ;
return window [ name ] = val ;
2008-08-02 22:41:32 +00:00
} ) ;
2008-07-30 20:28:29 +00:00
} ) ;
2010-05-19 16:57:16 +00:00
// Smart getter for the findbar. If you don't wish to force the creation of
// the findbar, check gFindBarInitialized first.
2013-07-06 00:56:36 +00:00
this . _ _defineGetter _ _ ( "gFindBar" , function ( ) {
return window . gBrowser . getFindBar ( ) ;
} ) ;
this . _ _defineGetter _ _ ( "gFindBarInitialized" , function ( ) {
return window . gBrowser . isFindBarInitialized ( ) ;
2010-05-19 16:57:16 +00:00
} ) ;
2012-11-22 01:38:56 +00:00
XPCOMUtils . defineLazyGetter ( this , "gPrefService" , function ( ) {
return Services . prefs ;
2008-07-30 20:28:29 +00:00
} ) ;
2012-09-25 18:44:40 +00:00
this . _ _defineGetter _ _ ( "AddonManager" , function ( ) {
2012-02-05 20:22:57 +00:00
let tmp = { } ;
Cu . import ( "resource://gre/modules/AddonManager.jsm" , tmp ) ;
return this . AddonManager = tmp . AddonManager ;
2010-07-01 16:23:11 +00:00
} ) ;
2012-09-25 18:44:40 +00:00
this . _ _defineSetter _ _ ( "AddonManager" , function ( val ) {
2010-07-01 16:23:11 +00:00
delete this . AddonManager ;
return this . AddonManager = val ;
} ) ;
2012-09-25 18:44:40 +00:00
this . _ _defineGetter _ _ ( "PluralForm" , function ( ) {
2009-04-24 08:20:15 +00:00
Cu . import ( "resource://gre/modules/PluralForm.jsm" ) ;
return this . PluralForm ;
2009-04-23 06:50:30 +00:00
} ) ;
2012-09-25 18:44:40 +00:00
this . _ _defineSetter _ _ ( "PluralForm" , function ( val ) {
2009-04-23 18:51:01 +00:00
delete this . PluralForm ;
return this . PluralForm = val ;
} ) ;
2009-04-23 06:50:30 +00:00
2012-03-20 15:20:56 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "TelemetryStopwatch" ,
2012-11-22 01:38:56 +00:00
"resource://gre/modules/TelemetryStopwatch.jsm" ) ;
2012-03-20 15:20:56 +00:00
2013-03-26 21:23:23 +00:00
XPCOMUtils . defineLazyGetter ( this , "gCustomizeMode" , function ( ) {
let scope = { } ;
Cu . import ( "resource:///modules/CustomizeMode.jsm" , scope ) ;
return new scope . CustomizeMode ( window ) ;
} ) ;
2010-08-02 23:37:56 +00:00
# ifdef MOZ _SERVICES _SYNC
2012-11-22 01:38:56 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "Weave" ,
"resource://services-sync/main.js" ) ;
2010-08-02 23:37:56 +00:00
# endif
2010-04-09 17:45:25 +00:00
XPCOMUtils . defineLazyGetter ( this , "PopupNotifications" , function ( ) {
let tmp = { } ;
Cu . import ( "resource://gre/modules/PopupNotifications.jsm" , tmp ) ;
2010-06-23 16:53:09 +00:00
try {
return new tmp . PopupNotifications ( gBrowser ,
document . getElementById ( "notification-popup" ) ,
document . getElementById ( "notification-popup-box" ) ) ;
} catch ( ex ) {
Cu . reportError ( ex ) ;
2012-11-26 16:18:25 +00:00
return null ;
2010-06-23 16:53:09 +00:00
}
2010-04-09 17:45:25 +00:00
} ) ;
2012-05-10 17:33:54 +00:00
XPCOMUtils . defineLazyGetter ( this , "DeveloperToolbar" , function ( ) {
let tmp = { } ;
Cu . import ( "resource:///modules/devtools/DeveloperToolbar.jsm" , tmp ) ;
return new tmp . DeveloperToolbar ( window , document . getElementById ( "developer-toolbar" ) ) ;
} ) ;
2013-12-02 08:28:01 +00:00
XPCOMUtils . defineLazyGetter ( this , "BrowserToolboxProcess" , function ( ) {
2012-11-27 10:39:10 +00:00
let tmp = { } ;
2013-12-02 08:28:01 +00:00
Cu . import ( "resource:///modules/devtools/ToolboxProcess.jsm" , tmp ) ;
return tmp . BrowserToolboxProcess ;
2012-11-27 10:39:10 +00:00
} ) ;
2012-11-22 01:38:56 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "Social" ,
"resource:///modules/Social.jsm" ) ;
2012-07-12 01:31:19 +00:00
2012-08-09 06:46:17 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "PageThumbs" ,
2013-02-17 04:15:41 +00:00
"resource://gre/modules/PageThumbs.jsm" ) ;
2012-08-09 06:46:17 +00:00
2012-07-28 06:25:11 +00:00
# ifdef MOZ _SAFE _BROWSING
2012-11-22 01:38:56 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "SafeBrowsing" ,
"resource://gre/modules/SafeBrowsing.jsm" ) ;
2012-07-28 06:25:11 +00:00
# endif
2012-09-19 14:20:44 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "gBrowserNewTabPreloader" ,
2012-09-21 16:10:17 +00:00
"resource:///modules/BrowserNewTabPreloader.jsm" , "BrowserNewTabPreloader" ) ;
2012-08-13 16:34:10 +00:00
2014-02-25 17:51:41 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "gCustomizationTabPreloader" ,
"resource:///modules/CustomizationTabPreloader.jsm" , "CustomizationTabPreloader" ) ;
2012-10-05 23:25:52 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "PrivateBrowsingUtils" ,
"resource://gre/modules/PrivateBrowsingUtils.jsm" ) ;
2013-07-02 00:42:48 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "SitePermissions" ,
"resource:///modules/SitePermissions.jsm" ) ;
2013-07-27 05:40:07 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "SessionStore" ,
"resource:///modules/sessionstore/SessionStore.jsm" ) ;
2014-01-25 15:36:04 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "fxAccounts" ,
"resource://gre/modules/FxAccounts.jsm" ) ;
2013-09-12 19:24:10 +00:00
# ifdef MOZ _CRASHREPORTER
XPCOMUtils . defineLazyModuleGetter ( this , "TabCrashReporter" ,
"resource:///modules/TabCrashReporter.jsm" ) ;
# endif
2009-03-03 08:20:14 +00:00
let gInitialPages = [
"about:blank" ,
2012-01-25 22:43:27 +00:00
"about:newtab" ,
2012-06-08 21:31:44 +00:00
"about:home" ,
2009-03-03 08:20:14 +00:00
"about:privatebrowsing" ,
2013-06-28 21:44:29 +00:00
"about:welcomeback" ,
2009-03-03 08:20:14 +00:00
"about:sessionrestore"
] ;
2012-06-01 06:26:00 +00:00
# include browser - addons . js
2013-03-26 21:23:23 +00:00
# include browser - customization . js
2012-06-01 06:26:00 +00:00
# include browser - feeds . js
2012-06-01 06:26:00 +00:00
# include browser - fullScreen . js
2009-09-01 08:26:26 +00:00
# include browser - fullZoom . js
# include browser - places . js
2012-06-01 06:26:00 +00:00
# include browser - plugins . js
2012-07-28 06:25:11 +00:00
# include browser - safebrowsing . js
2012-07-12 01:31:19 +00:00
# include browser - social . js
2009-09-01 08:26:26 +00:00
# include browser - tabPreviews . js
2010-07-29 19:37:25 +00:00
# include browser - tabview . js
2012-01-19 15:01:43 +00:00
# include browser - thumbnails . js
2012-12-28 09:25:59 +00:00
# include browser - webrtcUI . js
2013-04-09 19:44:01 +00:00
# include browser - gestureSupport . js
2009-09-01 08:26:26 +00:00
2013-01-12 03:05:35 +00:00
# ifdef MOZ _DATA _REPORTING
# include browser - data - submission - info - bar . js
# endif
2010-08-02 23:37:56 +00:00
# ifdef MOZ _SERVICES _SYNC
# include browser - syncui . js
# endif
2014-01-25 15:19:07 +00:00
# include browser - fxaccounts . js
2009-10-12 06:13:25 +00:00
XPCOMUtils . defineLazyGetter ( this , "Win7Features" , function ( ) {
2009-10-06 04:26:15 +00:00
# ifdef XP _WIN
2013-09-12 06:50:46 +00:00
// Bug 666808 - AeroPeek support for e10s
if ( gMultiProcessBrowser )
return null ;
2009-10-06 04:26:15 +00:00
const WINTASKBAR _CONTRACTID = "@mozilla.org/windows-taskbar;1" ;
2009-10-08 01:09:09 +00:00
if ( WINTASKBAR _CONTRACTID in Cc &&
2009-10-08 06:58:22 +00:00
Cc [ WINTASKBAR _CONTRACTID ] . getService ( Ci . nsIWinTaskbar ) . available ) {
2013-01-30 22:44:40 +00:00
let AeroPeek = Cu . import ( "resource:///modules/WindowsPreviewPerTab.jsm" , { } ) . AeroPeek ;
2009-10-06 04:26:15 +00:00
return {
onOpenWindow : function ( ) {
AeroPeek . onOpenWindow ( window ) ;
} ,
onCloseWindow : function ( ) {
AeroPeek . onCloseWindow ( window ) ;
}
} ;
}
# endif
2009-10-12 06:13:25 +00:00
return null ;
} ) ;
2009-10-06 04:26:15 +00:00
2014-01-31 01:35:36 +00:00
# ifdef MOZ _CRASHREPORTER
XPCOMUtils . defineLazyServiceGetter ( this , "gCrashReporter" ,
"@mozilla.org/xre/app-info;1" ,
"nsICrashReporter" ) ;
# endif
2011-08-08 17:31:32 +00:00
XPCOMUtils . defineLazyGetter ( this , "PageMenu" , function ( ) {
let tmp = { } ;
Cu . import ( "resource://gre/modules/PageMenu.jsm" , tmp ) ;
return new tmp . PageMenu ( ) ;
} ) ;
2002-08-04 02:53:09 +00:00
/ * *
* We can avoid adding multiple load event listeners and save some time by adding
* one listener that calls all real handlers .
* /
2013-03-09 11:34:29 +00:00
function pageShowEventHandlers ( persisted ) {
2012-09-12 09:27:29 +00:00
charsetLoadListener ( ) ;
XULBrowserWindow . asyncUpdateUI ( ) ;
// The PluginClickToPlay events are not fired when navigating using the
2013-03-09 11:34:29 +00:00
// BF cache. |persisted| is true when the page is loaded from the
2012-09-12 09:27:29 +00:00
// BF cache, so this code reshows the notification if necessary.
2013-03-09 11:34:29 +00:00
if ( persisted )
2012-09-12 09:27:29 +00:00
gPluginHandler . reshowClickToPlayNotification ( ) ;
2002-08-04 02:53:09 +00:00
}
2008-09-01 20:19:24 +00:00
function UpdateBackForwardCommands ( aWebNavigation ) {
2002-08-09 01:41:39 +00:00
var backBroadcaster = document . getElementById ( "Browser:Back" ) ;
var forwardBroadcaster = document . getElementById ( "Browser:Forward" ) ;
2005-06-14 10:15:58 +00:00
2002-08-04 02:53:09 +00:00
// 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
2002-11-09 01:21:19 +00:00
var backDisabled = backBroadcaster . hasAttribute ( "disabled" ) ;
var forwardDisabled = forwardBroadcaster . hasAttribute ( "disabled" ) ;
2007-01-31 18:10:02 +00:00
if ( backDisabled == aWebNavigation . canGoBack ) {
2002-11-09 01:21:19 +00:00
if ( backDisabled )
backBroadcaster . removeAttribute ( "disabled" ) ;
else
backBroadcaster . setAttribute ( "disabled" , true ) ;
2002-08-04 02:53:09 +00:00
}
2005-06-14 10:15:58 +00:00
2013-12-17 18:43:50 +00:00
let canGoForward = aWebNavigation . canGoForward ;
if ( forwardDisabled ) {
// Force the button to either be hidden (if we are already disabled,
// and should be), or to show if we're about to un-disable it:
// otherwise no transition will occur and it'll never show:
CombinedBackForward . setForwardButtonOcclusion ( ! canGoForward ) ;
}
if ( forwardDisabled == canGoForward ) {
2002-11-09 01:21:19 +00:00
if ( forwardDisabled )
forwardBroadcaster . removeAttribute ( "disabled" ) ;
else
forwardBroadcaster . setAttribute ( "disabled" , true ) ;
2002-08-04 02:53:09 +00:00
}
}
2006-04-20 22:35:06 +00:00
/ * *
* Click - and - Hold implementation for the Back and Forward buttons
* XXXmano : should this live in toolbarbutton . xml ?
* /
2009-09-29 19:19:21 +00:00
function SetClickAndHoldHandlers ( ) {
var timer ;
2006-04-20 22:35:06 +00:00
2011-05-24 06:34:14 +00:00
function openMenu ( aButton ) {
cancelHold ( aButton ) ;
2009-09-29 19:19:21 +00:00
aButton . firstChild . hidden = false ;
aButton . open = true ;
}
2006-09-18 19:51:24 +00:00
2009-09-29 19:19:21 +00:00
function mousedownHandler ( aEvent ) {
if ( aEvent . button != 0 ||
aEvent . currentTarget . open ||
aEvent . currentTarget . disabled )
return ;
2006-04-20 22:35:06 +00:00
2009-09-29 19:19:21 +00:00
// Prevent the menupopup from opening immediately
aEvent . currentTarget . firstChild . hidden = true ;
2006-04-20 22:35:06 +00:00
2011-05-24 06:34:14 +00:00
aEvent . currentTarget . addEventListener ( "mouseout" , mouseoutHandler , false ) ;
aEvent . currentTarget . addEventListener ( "mouseup" , mouseupHandler , false ) ;
timer = setTimeout ( openMenu , 500 , aEvent . currentTarget ) ;
}
function mouseoutHandler ( aEvent ) {
let buttonRect = aEvent . currentTarget . getBoundingClientRect ( ) ;
if ( aEvent . clientX >= buttonRect . left &&
aEvent . clientX <= buttonRect . right &&
aEvent . clientY >= buttonRect . bottom )
openMenu ( aEvent . currentTarget ) ;
else
cancelHold ( aEvent . currentTarget ) ;
}
function mouseupHandler ( aEvent ) {
cancelHold ( aEvent . currentTarget ) ;
}
function cancelHold ( aButton ) {
clearTimeout ( timer ) ;
aButton . removeEventListener ( "mouseout" , mouseoutHandler , false ) ;
aButton . removeEventListener ( "mouseup" , mouseupHandler , false ) ;
2009-09-29 19:19:21 +00:00
}
2006-05-30 14:10:32 +00:00
2009-09-29 19:19:21 +00:00
function clickHandler ( aEvent ) {
if ( aEvent . button == 0 &&
aEvent . target == aEvent . currentTarget &&
! aEvent . currentTarget . open &&
2009-10-15 15:48:54 +00:00
! aEvent . currentTarget . disabled ) {
let cmdEvent = document . createEvent ( "xulcommandevent" ) ;
cmdEvent . initCommandEvent ( "command" , true , true , window , 0 ,
aEvent . ctrlKey , aEvent . altKey , aEvent . shiftKey ,
aEvent . metaKey , null ) ;
aEvent . currentTarget . dispatchEvent ( cmdEvent ) ;
}
2009-09-29 19:19:21 +00:00
}
function _addClickAndHoldListenersOnElement ( aElm ) {
aElm . addEventListener ( "mousedown" , mousedownHandler , true ) ;
aElm . addEventListener ( "click" , clickHandler , true ) ;
2006-04-20 22:35:06 +00:00
}
2013-07-18 16:46:28 +00:00
// Bug 414797: Clone the back/forward buttons' context menu into both buttons.
let popup = document . getElementById ( "backForwardMenu" ) . cloneNode ( true ) ;
popup . removeAttribute ( "id" ) ;
// Prevent the back/forward buttons' context attributes from being inherited.
popup . setAttribute ( "context" , "" ) ;
let backButton = document . getElementById ( "back-button" ) ;
backButton . setAttribute ( "type" , "menu" ) ;
backButton . appendChild ( popup ) ;
_addClickAndHoldListenersOnElement ( backButton ) ;
let forwardButton = document . getElementById ( "forward-button" ) ;
popup = popup . cloneNode ( true ) ;
forwardButton . setAttribute ( "type" , "menu" ) ;
forwardButton . appendChild ( popup ) ;
_addClickAndHoldListenersOnElement ( forwardButton ) ;
2006-04-20 22:35:06 +00:00
}
2004-11-30 08:23:02 +00:00
const gSessionHistoryObserver = {
observe : function ( subject , topic , data )
{
if ( topic != "browser:purge-session-history" )
return ;
2002-10-08 23:14:45 +00:00
2004-11-30 08:23:02 +00:00
var backCommand = document . getElementById ( "Browser:Back" ) ;
backCommand . setAttribute ( "disabled" , "true" ) ;
var fwdCommand = document . getElementById ( "Browser:Forward" ) ;
fwdCommand . setAttribute ( "disabled" , "true" ) ;
2006-02-01 15:22:15 +00:00
2011-07-28 20:20:52 +00:00
// Hide session restore button on about:home
2012-08-27 14:13:02 +00:00
window . messageManager . broadcastAsyncMessage ( "Browser:HideSessionRestoreButton" ) ;
2011-07-28 20:20:52 +00:00
2007-03-01 06:30:53 +00:00
if ( gURLBar ) {
// Clear undo history of the URL bar
gURLBar . editor . transactionManager . clear ( )
2006-02-01 15:22:15 +00:00
}
2004-11-30 08:23:02 +00:00
}
} ;
2002-10-09 01:41:08 +00:00
2005-08-12 00:34:19 +00:00
/ * *
* Given a starting docshell and a URI to look up , find the docshell the URI
2010-03-24 21:22:04 +00:00
* is loaded in .
2005-08-12 00:34:19 +00:00
* @ param aDocument
2010-03-24 21:22:04 +00:00
* A document to find instead of using just a URI - this is more specific .
2005-08-12 00:34:19 +00:00
* @ param aDocShell
* The doc shell to start at
* @ param aSoughtURI
* The URI that we ' re looking for
2010-03-24 21:22:04 +00:00
* @ returns The doc shell that the sought URI is loaded in . Can be in
2005-08-12 00:34:19 +00:00
* subframes .
* /
function findChildShell ( aDocument , aDocShell , aSoughtURI ) {
aDocShell . QueryInterface ( Components . interfaces . nsIWebNavigation ) ;
aDocShell . QueryInterface ( Components . interfaces . nsIInterfaceRequestor ) ;
var doc = aDocShell . getInterface ( Components . interfaces . nsIDOMDocument ) ;
2010-03-24 21:22:04 +00:00
if ( ( aDocument && doc == aDocument ) ||
2005-08-25 16:40:42 +00:00
( aSoughtURI && aSoughtURI . spec == aDocShell . currentURI . spec ) )
2005-08-12 00:34:19 +00:00
return aDocShell ;
2014-01-06 22:34:15 +00:00
var node = aDocShell . QueryInterface ( Components . interfaces . nsIDocShellTreeItem ) ;
2005-08-12 00:34:19 +00:00
for ( var i = 0 ; i < node . childCount ; ++ i ) {
var docShell = node . getChildAt ( i ) ;
docShell = findChildShell ( aDocument , docShell , aSoughtURI ) ;
if ( docShell )
return docShell ;
}
return null ;
}
2010-12-16 17:53:27 +00:00
var gPopupBlockerObserver = {
_reportButton : null ,
2012-05-08 21:47:19 +00:00
2010-12-16 17:53:27 +00:00
onReportButtonClick : function ( aEvent )
{
if ( aEvent . button != 0 || aEvent . target != this . _reportButton )
return ;
2009-09-18 18:18:26 +00:00
2010-12-16 17:53:27 +00:00
document . getElementById ( "blockedPopupOptions" )
. openPopup ( this . _reportButton , "after_end" , 0 , 2 , false , false , aEvent ) ;
} ,
handleEvent : function ( aEvent )
2004-11-30 08:23:02 +00:00
{
2007-12-19 11:26:36 +00:00
if ( aEvent . originalTarget != gBrowser . selectedBrowser )
return ;
2010-12-16 17:53:27 +00:00
if ( ! this . _reportButton && gURLBar )
this . _reportButton = document . getElementById ( "page-report-button" ) ;
if ( ! gBrowser . pageReport ) {
// Hide the icon in the location bar (if the location bar exists)
if ( gURLBar )
this . _reportButton . hidden = true ;
2006-11-06 23:41:31 +00:00
return ;
2010-12-16 17:53:27 +00:00
}
if ( gURLBar )
this . _reportButton . hidden = false ;
2006-11-06 23:41:31 +00:00
// Only show the notification again if we've not already shown it. Since
// notifications are per-browser, we don't need to worry about re-adding
// it.
if ( ! gBrowser . pageReport . reported ) {
2005-08-27 17:19:08 +00:00
if ( gPrefService . getBoolPref ( "privacy.popups.showBrowserMessage" ) ) {
2004-11-30 08:23:02 +00:00
var brandBundle = document . getElementById ( "bundle_brand" ) ;
var brandShortName = brandBundle . getString ( "brandShortName" ) ;
2006-11-06 23:41:31 +00:00
var popupCount = gBrowser . pageReport . length ;
2005-06-07 20:16:29 +00:00
# ifdef XP _WIN
2009-07-13 22:10:04 +00:00
var popupButtonText = gNavigatorBundle . getString ( "popupWarningButton" ) ;
var popupButtonAccesskey = gNavigatorBundle . getString ( "popupWarningButton.accesskey" ) ;
2005-06-07 20:16:29 +00:00
# else
2009-07-13 22:10:04 +00:00
var popupButtonText = gNavigatorBundle . getString ( "popupWarningButtonUnix" ) ;
var popupButtonAccesskey = gNavigatorBundle . getString ( "popupWarningButtonUnix.accesskey" ) ;
2005-06-07 20:16:29 +00:00
# endif
2013-03-22 22:27:25 +00:00
var messageBase = gNavigatorBundle . getString ( "popupWarning.message" ) ;
var message = PluralForm . get ( popupCount , messageBase )
. replace ( "#1" , brandShortName )
. replace ( "#2" , popupCount ) ;
2005-04-28 17:28:00 +00:00
2006-04-19 20:50:25 +00:00
var notificationBox = gBrowser . getNotificationBox ( ) ;
var notification = notificationBox . getNotificationWithValue ( "popup-blocked" ) ;
if ( notification ) {
notification . label = message ;
}
else {
var buttons = [ {
label : popupButtonText ,
accessKey : popupButtonAccesskey ,
popup : "blockedPopupOptions" ,
callback : null
} ] ;
const priority = notificationBox . PRIORITY _WARNING _MEDIUM ;
notificationBox . appendNotification ( message , "popup-blocked" ,
"chrome://browser/skin/Info.png" ,
priority , buttons ) ;
}
2004-11-30 08:23:02 +00:00
}
2006-11-06 23:41:31 +00:00
// Record the fact that we've reported this blocked popup, so we don't
// show it again.
gBrowser . pageReport . reported = true ;
2002-10-09 01:26:47 +00:00
}
2004-11-30 08:23:02 +00:00
} ,
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
toggleAllowPopupsForSite : function ( aEvent )
{
2010-02-25 22:13:00 +00:00
var pm = Services . perms ;
2004-11-30 08:23:02 +00:00
var shouldBlock = aEvent . target . getAttribute ( "block" ) == "true" ;
2009-09-18 18:18:26 +00:00
var perm = shouldBlock ? pm . DENY _ACTION : pm . ALLOW _ACTION ;
pm . add ( gBrowser . currentURI , "popup" , perm ) ;
2005-06-14 10:15:58 +00:00
2006-04-19 20:50:25 +00:00
gBrowser . getNotificationBox ( ) . removeCurrentNotification ( ) ;
2004-11-30 08:23:02 +00:00
} ,
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
fillPopupList : function ( aEvent )
{
// XXXben - rather than using |currentURI| here, which breaks down on multi-framed sites
// we should really walk the pageReport and create a list of "allow for <host>"
// menuitems for the common subset of hosts present in the report, this will
// make us frame-safe.
2006-07-29 16:59:20 +00:00
//
// XXXjst - Note that when this is fixed to work with multi-framed sites,
// also back out the fix for bug 343772 where
// nsGlobalWindow::CheckOpenAllow() was changed to also
// check if the top window's location is whitelisted.
2009-09-18 18:18:26 +00:00
var uri = gBrowser . currentURI ;
2004-11-30 08:23:02 +00:00
var blockedPopupAllowSite = document . getElementById ( "blockedPopupAllowSite" ) ;
try {
blockedPopupAllowSite . removeAttribute ( "hidden" ) ;
2005-06-14 10:15:58 +00:00
2010-02-25 22:13:00 +00:00
var pm = Services . perms ;
2009-09-18 18:18:26 +00:00
if ( pm . testPermission ( uri , "popup" ) == pm . ALLOW _ACTION ) {
2004-11-30 08:23:02 +00:00
// Offer an item to block popups for this site, if a whitelist entry exists
// already for it.
2012-11-28 15:48:35 +00:00
let blockString = gNavigatorBundle . getFormattedString ( "popupBlock" , [ uri . host || uri . spec ] ) ;
2004-11-30 08:23:02 +00:00
blockedPopupAllowSite . setAttribute ( "label" , blockString ) ;
blockedPopupAllowSite . setAttribute ( "block" , "true" ) ;
}
else {
// Offer an item to allow popups for this site
2012-11-28 15:48:35 +00:00
let allowString = gNavigatorBundle . getFormattedString ( "popupAllow" , [ uri . host || uri . spec ] ) ;
2004-11-30 08:23:02 +00:00
blockedPopupAllowSite . setAttribute ( "label" , allowString ) ;
blockedPopupAllowSite . removeAttribute ( "block" ) ;
}
}
catch ( e ) {
blockedPopupAllowSite . setAttribute ( "hidden" , "true" ) ;
}
2005-06-14 10:15:58 +00:00
2012-10-07 21:47:10 +00:00
if ( PrivateBrowsingUtils . isWindowPrivate ( window ) )
2008-11-03 23:22:22 +00:00
blockedPopupAllowSite . setAttribute ( "disabled" , "true" ) ;
2009-12-17 21:11:48 +00:00
else
2009-12-17 23:37:48 +00:00
blockedPopupAllowSite . removeAttribute ( "disabled" ) ;
2008-11-03 23:22:22 +00:00
2006-03-28 02:16:06 +00:00
var foundUsablePopupURI = false ;
2012-08-21 16:56:07 +00:00
var pageReports = gBrowser . pageReport ;
if ( pageReports ) {
for ( let pageReport of pageReports ) {
2010-08-27 15:49:08 +00:00
// popupWindowURI will be null if the file picker popup is blocked.
2012-05-08 21:47:19 +00:00
// xxxdz this should make the option say "Show file picker" and do it (Bug 590306)
2012-08-21 16:56:07 +00:00
if ( ! pageReport . popupWindowURI )
2010-08-27 15:49:08 +00:00
continue ;
2012-08-21 16:56:07 +00:00
var popupURIspec = pageReport . popupWindowURI . spec ;
2006-03-28 02:16:06 +00:00
// Sometimes the popup URI that we get back from the pageReport
// isn't useful (for instance, netscape.com's popup URI ends up
// being "http://www.netscape.com", which isn't really the URI of
// the popup they're trying to show). This isn't going to be
// useful to the user, so we won't create a menu item for it.
2004-11-30 08:23:02 +00:00
if ( popupURIspec == "" || popupURIspec == "about:blank" ||
popupURIspec == uri . spec )
continue ;
2006-03-28 02:16:06 +00:00
// Because of the short-circuit above, we may end up in a situation
// in which we don't have any usable popup addresses to show in
// the menu, and therefore we shouldn't show the separator. However,
// since we got past the short-circuit, we must've found at least
// one usable popup URI and thus we'll turn on the separator later.
foundUsablePopupURI = true ;
2004-11-30 08:23:02 +00:00
var menuitem = document . createElement ( "menuitem" ) ;
2009-07-13 22:10:04 +00:00
var label = gNavigatorBundle . getFormattedString ( "popupShowPopupPrefix" ,
[ popupURIspec ] ) ;
2004-11-30 08:23:02 +00:00
menuitem . setAttribute ( "label" , label ) ;
menuitem . setAttribute ( "popupWindowURI" , popupURIspec ) ;
2012-08-21 16:56:07 +00:00
menuitem . setAttribute ( "popupWindowFeatures" , pageReport . popupWindowFeatures ) ;
menuitem . setAttribute ( "popupWindowName" , pageReport . popupWindowName ) ;
2004-11-30 08:23:02 +00:00
menuitem . setAttribute ( "oncommand" , "gPopupBlockerObserver.showBlockedPopup(event);" ) ;
2012-08-21 16:56:07 +00:00
menuitem . requestingWindow = pageReport . requestingWindow ;
menuitem . requestingDocument = pageReport . requestingDocument ;
2004-11-30 08:23:02 +00:00
aEvent . target . appendChild ( menuitem ) ;
}
}
2006-03-28 02:16:06 +00:00
// Show or hide the separator, depending on whether we added any
// showable popup addresses to the menu.
var blockedPopupsSeparator =
document . getElementById ( "blockedPopupsSeparator" ) ;
if ( foundUsablePopupURI )
blockedPopupsSeparator . removeAttribute ( "hidden" ) ;
else
blockedPopupsSeparator . setAttribute ( "hidden" , true ) ;
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
var blockedPopupDontShowMessage = document . getElementById ( "blockedPopupDontShowMessage" ) ;
var showMessage = gPrefService . getBoolPref ( "privacy.popups.showBrowserMessage" ) ;
blockedPopupDontShowMessage . setAttribute ( "checked" , ! showMessage ) ;
2010-12-16 17:53:27 +00:00
if ( aEvent . target . anchorNode . id == "page-report-button" ) {
aEvent . target . anchorNode . setAttribute ( "open" , "true" ) ;
blockedPopupDontShowMessage . setAttribute ( "label" , gNavigatorBundle . getString ( "popupWarningDontShowFromLocationbar" ) ) ;
} else
blockedPopupDontShowMessage . setAttribute ( "label" , gNavigatorBundle . getString ( "popupWarningDontShowFromMessage" ) ) ;
} ,
onPopupHiding : function ( aEvent ) {
if ( aEvent . target . anchorNode . id == "page-report-button" )
aEvent . target . anchorNode . removeAttribute ( "open" ) ;
2011-07-02 14:00:06 +00:00
let item = aEvent . target . lastChild ;
while ( item && item . getAttribute ( "observes" ) != "blockedPopupsSeparator" ) {
let next = item . previousSibling ;
item . parentNode . removeChild ( item ) ;
item = next ;
}
2004-11-30 08:23:02 +00:00
} ,
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
showBlockedPopup : function ( aEvent )
2004-01-17 22:41:38 +00:00
{
2007-01-13 01:08:43 +00:00
var target = aEvent . target ;
var popupWindowURI = target . getAttribute ( "popupWindowURI" ) ;
var features = target . getAttribute ( "popupWindowFeatures" ) ;
var name = target . getAttribute ( "popupWindowName" ) ;
2005-06-14 10:15:58 +00:00
2007-01-13 01:08:43 +00:00
var dwi = target . requestingWindow ;
// If we have a requesting window and the requesting document is
// still the current document, open the popup.
if ( dwi && dwi . document == target . requestingDocument ) {
2005-12-28 00:39:10 +00:00
dwi . open ( popupWindowURI , name , features ) ;
2004-11-30 08:23:02 +00:00
}
} ,
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
editPopupSettings : function ( )
{
var host = "" ;
try {
2009-09-18 18:18:26 +00:00
host = gBrowser . currentURI . host ;
2004-11-30 08:23:02 +00:00
}
2005-06-14 10:15:58 +00:00
catch ( e ) { }
2004-11-30 08:23:02 +00:00
2005-02-25 09:07:58 +00:00
var bundlePreferences = document . getElementById ( "bundle_preferences" ) ;
2005-06-14 10:15:58 +00:00
var params = { blockVisible : false ,
sessionVisible : false ,
allowVisible : true ,
prefilledHost : host ,
2005-02-25 09:07:58 +00:00
permissionType : "popup" ,
windowTitle : bundlePreferences . getString ( "popuppermissionstitle" ) ,
introText : bundlePreferences . getString ( "popuppermissionstext" ) } ;
2010-01-28 18:31:45 +00:00
var existingWindow = Services . wm . getMostRecentWindow ( "Browser:Permissions" ) ;
2004-11-30 08:23:02 +00:00
if ( existingWindow ) {
2005-02-25 09:07:58 +00:00
existingWindow . initWithParams ( params ) ;
2004-11-30 08:23:02 +00:00
existingWindow . focus ( ) ;
}
2005-02-25 09:07:58 +00:00
else
window . openDialog ( "chrome://browser/content/preferences/permissions.xul" ,
"_blank" , "resizable,dialog=no,centerscreen" , params ) ;
2004-11-30 08:23:02 +00:00
} ,
2005-06-14 10:15:58 +00:00
2004-11-30 08:23:02 +00:00
dontShowMessage : function ( )
{
var showMessage = gPrefService . getBoolPref ( "privacy.popups.showBrowserMessage" ) ;
gPrefService . setBoolPref ( "privacy.popups.showBrowserMessage" , ! showMessage ) ;
2006-04-19 20:50:25 +00:00
gBrowser . getNotificationBox ( ) . removeCurrentNotification ( ) ;
2004-01-17 22:41:38 +00:00
}
} ;
2010-09-11 04:10:31 +00:00
const gFormSubmitObserver = {
QueryInterface : XPCOMUtils . generateQI ( [ Ci . nsIFormSubmitObserver ] ) ,
panel : null ,
init : function ( )
{
this . panel = document . getElementById ( 'invalid-form-popup' ) ;
} ,
notifyInvalidSubmit : function ( aFormElement , aInvalidElements )
{
// We are going to handle invalid form submission attempt by focusing the
// first invalid element and show the corresponding validation message in a
// panel attached to the element.
if ( ! aInvalidElements . length ) {
return ;
}
// Don't show the popup if the current tab doesn't contain the invalid form.
2010-09-20 20:27:47 +00:00
if ( gBrowser . contentDocument !=
aFormElement . ownerDocument . defaultView . top . document ) {
2010-09-11 04:10:31 +00:00
return ;
}
let element = aInvalidElements . queryElementAt ( 0 , Ci . nsISupports ) ;
if ( ! ( element instanceof HTMLInputElement ||
element instanceof HTMLTextAreaElement ||
element instanceof HTMLSelectElement ||
element instanceof HTMLButtonElement ) ) {
return ;
}
2010-10-25 22:02:24 +00:00
this . panel . firstChild . textContent = element . validationMessage ;
2010-09-11 04:10:31 +00:00
element . focus ( ) ;
2010-12-18 02:05:14 +00:00
// If the user interacts with the element and makes it valid or leaves it,
// we want to remove the popup.
2010-09-11 04:10:31 +00:00
// We could check for clicks but a click is already removing the popup.
2010-12-18 02:05:14 +00:00
function blurHandler ( ) {
2010-09-11 04:10:31 +00:00
gFormSubmitObserver . panel . hidePopup ( ) ;
} ;
2010-12-18 02:05:14 +00:00
function inputHandler ( e ) {
if ( e . originalTarget . validity . valid ) {
gFormSubmitObserver . panel . hidePopup ( ) ;
2011-02-03 23:07:33 +00:00
} else {
// If the element is now invalid for a new reason, we should update the
// error message.
if ( gFormSubmitObserver . panel . firstChild . textContent !=
e . originalTarget . validationMessage ) {
gFormSubmitObserver . panel . firstChild . textContent =
e . originalTarget . validationMessage ;
}
2010-12-18 02:05:14 +00:00
}
} ;
element . addEventListener ( "input" , inputHandler , false ) ;
element . addEventListener ( "blur" , blurHandler , false ) ;
2010-09-11 04:10:31 +00:00
2010-12-18 02:05:14 +00:00
// One event to bring them all and in the darkness bind them.
2012-04-16 22:35:34 +00:00
this . panel . addEventListener ( "popuphiding" , function onPopupHiding ( aEvent ) {
aEvent . target . removeEventListener ( "popuphiding" , onPopupHiding , false ) ;
2010-12-18 02:05:14 +00:00
element . removeEventListener ( "input" , inputHandler , false ) ;
element . removeEventListener ( "blur" , blurHandler , false ) ;
2010-09-11 04:10:31 +00:00
} , false ) ;
this . panel . hidden = false ;
2011-01-18 11:07:15 +00:00
// We want to show the popup at the middle of checkbox and radio buttons
// and where the content begin for the other elements.
let offset = 0 ;
let position = "" ;
if ( element . tagName == 'INPUT' &&
( element . type == 'radio' || element . type == 'checkbox' ) ) {
position = "bottomcenter topleft" ;
} else {
2011-02-03 23:06:16 +00:00
let win = element . ownerDocument . defaultView ;
let style = win . getComputedStyle ( element , null ) ;
let utils = win . QueryInterface ( Components . interfaces . nsIInterfaceRequestor )
. getInterface ( Components . interfaces . nsIDOMWindowUtils ) ;
2011-01-18 11:07:15 +00:00
if ( style . direction == 'rtl' ) {
offset = parseInt ( style . paddingRight ) + parseInt ( style . borderRightWidth ) ;
} else {
offset = parseInt ( style . paddingLeft ) + parseInt ( style . borderLeftWidth ) ;
}
2012-09-29 11:35:19 +00:00
offset = Math . round ( offset * utils . fullZoom ) ;
2011-02-03 23:06:16 +00:00
2011-01-18 11:07:15 +00:00
position = "after_start" ;
}
this . panel . openPopup ( element , position , offset , 0 ) ;
2010-09-11 04:10:31 +00:00
}
} ;
2012-06-15 19:09:47 +00:00
var gBrowserInit = {
2013-10-22 11:07:30 +00:00
delayedStartupFinished : false ,
2012-06-15 19:09:48 +00:00
onLoad : function ( ) {
2014-02-11 17:01:08 +00:00
gMultiProcessBrowser =
window . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsILoadContext )
. useRemoteTabs ;
2013-04-23 02:47:34 +00:00
2012-06-15 19:09:47 +00:00
var mustLoadSidebar = false ;
2013-08-09 00:16:47 +00:00
if ( ! gMultiProcessBrowser ) {
// There is a Content:Click message manually sent from content.
Cc [ "@mozilla.org/eventlistenerservice;1" ]
. getService ( Ci . nsIEventListenerService )
. addSystemEventListener ( gBrowser , "click" , contentAreaClick , true ) ;
}
2013-03-20 14:07:28 +00:00
2012-06-15 19:09:48 +00:00
gBrowser . addEventListener ( "DOMUpdatePageReport" , gPopupBlockerObserver , false ) ;
2012-11-07 21:59:20 +00:00
// Note that the XBL binding is untrusted
gBrowser . addEventListener ( "PluginBindingAttached" , gPluginHandler , true , true ) ;
gBrowser . addEventListener ( "PluginCrashed" , gPluginHandler , true ) ;
gBrowser . addEventListener ( "PluginOutdated" , gPluginHandler , true ) ;
2013-06-24 12:51:07 +00:00
gBrowser . addEventListener ( "PluginInstantiated" , gPluginHandler , true ) ;
2013-11-02 15:53:26 +00:00
gBrowser . addEventListener ( "PluginRemoved" , gPluginHandler , true ) ;
2012-11-07 21:59:20 +00:00
2012-06-15 19:09:48 +00:00
gBrowser . addEventListener ( "NewPluginInstalled" , gPluginHandler . newPluginInstalled , true ) ;
2003-01-29 07:42:59 +00:00
2012-06-15 19:09:48 +00:00
Services . obs . addObserver ( gPluginHandler . pluginCrashed , "plugin-crashed" , false ) ;
window . addEventListener ( "AppCommand" , HandleAppCommandEvent , true ) ;
messageManager . loadFrameScript ( "chrome://browser/content/content.js" , true ) ;
// initialize observers and listeners
// and give C++ access to gBrowser
XULBrowserWindow . init ( ) ;
window . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShellTreeItem ) . treeOwner
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIXULWindow )
. XULBrowserWindow = window . XULBrowserWindow ;
window . QueryInterface ( Ci . nsIDOMChromeWindow ) . browserDOMWindow =
new nsBrowserAccess ( ) ;
2013-04-25 05:29:31 +00:00
// hook up UI through progress listener
gBrowser . addProgressListener ( window . XULBrowserWindow ) ;
gBrowser . addTabsProgressListener ( window . TabsProgressListener ) ;
2010-06-13 08:20:58 +00:00
2012-06-15 19:09:48 +00:00
// setup our common DOMLinkAdded listener
2014-02-09 01:41:34 +00:00
DOMLinkHandler . init ( ) ;
2010-01-05 07:28:46 +00:00
2012-06-15 19:09:48 +00:00
// setup simple gestures support
gGestureSupport . init ( true ) ;
2010-06-15 21:51:29 +00:00
2013-04-09 19:44:01 +00:00
// setup history swipe animation
gHistorySwipeAnimation . init ( ) ;
2013-07-09 20:21:23 +00:00
if ( window . opener && ! window . opener . closed &&
PrivateBrowsingUtils . isWindowPrivate ( window ) == PrivateBrowsingUtils . isWindowPrivate ( window . opener ) ) {
2012-06-15 19:09:47 +00:00
let openerSidebarBox = window . opener . document . getElementById ( "sidebar-box" ) ;
// If the opener had a sidebar, open the same sidebar in our window.
// The opener can be the hidden window too, if we're coming from the state
// where no windows are open, and the hidden window has no sidebar box.
if ( openerSidebarBox && ! openerSidebarBox . hidden ) {
let sidebarCmd = openerSidebarBox . getAttribute ( "sidebarcommand" ) ;
let sidebarCmdElem = document . getElementById ( sidebarCmd ) ;
// dynamically generated sidebars will fail this check.
if ( sidebarCmdElem ) {
let sidebarBox = document . getElementById ( "sidebar-box" ) ;
let sidebarTitle = document . getElementById ( "sidebar-title" ) ;
sidebarTitle . setAttribute (
"value" , window . opener . document . getElementById ( "sidebar-title" ) . getAttribute ( "value" ) ) ;
sidebarBox . setAttribute ( "width" , openerSidebarBox . boxObject . width ) ;
sidebarBox . setAttribute ( "sidebarcommand" , sidebarCmd ) ;
// Note: we're setting 'src' on sidebarBox, which is a <vbox>, not on
// the <browser id="sidebar">. This lets us delay the actual load until
// delayedStartup().
sidebarBox . setAttribute (
"src" , window . opener . document . getElementById ( "sidebar" ) . getAttribute ( "src" ) ) ;
2008-09-03 07:40:33 +00:00
mustLoadSidebar = true ;
2006-12-01 11:16:07 +00:00
2012-06-15 19:09:47 +00:00
sidebarBox . hidden = false ;
2008-09-03 07:40:33 +00:00
document . getElementById ( "sidebar-splitter" ) . hidden = false ;
2012-06-15 19:09:47 +00:00
sidebarCmdElem . setAttribute ( "checked" , "true" ) ;
2005-08-02 18:34:13 +00:00
}
2012-06-15 19:09:47 +00:00
}
}
else {
let box = document . getElementById ( "sidebar-box" ) ;
if ( box . hasAttribute ( "sidebarcommand" ) ) {
let commandID = box . getAttribute ( "sidebarcommand" ) ;
if ( commandID ) {
let command = document . getElementById ( commandID ) ;
if ( command ) {
mustLoadSidebar = true ;
box . hidden = false ;
document . getElementById ( "sidebar-splitter" ) . hidden = false ;
command . setAttribute ( "checked" , "true" ) ;
}
else {
// Remove the |sidebarcommand| attribute, because the element it
// refers to no longer exists, so we should assume this sidebar
// panel has been uninstalled. (249883)
box . removeAttribute ( "sidebarcommand" ) ;
}
2005-08-02 18:34:13 +00:00
}
2002-11-08 04:50:05 +00:00
}
}
2010-01-28 18:31:45 +00:00
2012-06-15 19:09:47 +00:00
// Certain kinds of automigration rely on this notification to complete their
// tasks BEFORE the browser window is shown.
Services . obs . notifyObservers ( null , "browser-window-before-show" , "" ) ;
// Set a sane starting width/height for all resolutions on new profiles.
if ( ! document . documentElement . hasAttribute ( "width" ) ) {
2013-03-21 13:30:16 +00:00
let defaultWidth ;
2012-06-15 19:09:47 +00:00
let defaultHeight ;
2013-03-21 13:30:16 +00:00
// Very small: maximize the window
// Portrait : use about full width and 3/4 height, to view entire pages
// at once (without being obnoxiously tall)
// Widescreen: use about half width, to suggest side-by-side page view
// Otherwise : use 3/4 height and width
2012-06-15 19:09:47 +00:00
if ( screen . availHeight <= 600 ) {
document . documentElement . setAttribute ( "sizemode" , "maximized" ) ;
defaultWidth = 610 ;
defaultHeight = 450 ;
}
else {
2013-03-21 13:30:16 +00:00
if ( screen . availWidth <= screen . availHeight ) {
defaultWidth = screen . availWidth * . 9 ;
defaultHeight = screen . availHeight * . 75 ;
}
else if ( screen . availWidth >= 2048 ) {
2012-06-15 19:09:47 +00:00
defaultWidth = ( screen . availWidth / 2 ) - 20 ;
2013-03-21 13:30:16 +00:00
defaultHeight = screen . availHeight - 10 ;
}
else {
defaultWidth = screen . availWidth * . 75 ;
defaultHeight = screen . availHeight * . 75 ;
}
2013-09-23 13:21:35 +00:00
# if MOZ _WIDGET _GTK == 2
2012-06-15 19:09:47 +00:00
// On X, we're not currently able to account for the size of the window
// border. Use 28px as a guess (titlebar + bottom window border)
defaultHeight -= 28 ;
2011-05-23 01:46:33 +00:00
# endif
2002-11-08 04:50:05 +00:00
}
2012-06-15 19:09:47 +00:00
document . documentElement . setAttribute ( "width" , defaultWidth ) ;
document . documentElement . setAttribute ( "height" , defaultHeight ) ;
2002-11-08 04:50:05 +00:00
}
2005-02-23 01:34:53 +00:00
2012-06-15 19:09:47 +00:00
if ( ! window . toolbar . visible ) {
// adjust browser UI for popups
if ( gURLBar ) {
gURLBar . setAttribute ( "readonly" , "true" ) ;
gURLBar . setAttribute ( "enablehistory" , "false" ) ;
}
goSetCommandEnabled ( "cmd_newNavigatorTab" , false ) ;
2010-04-22 07:24:39 +00:00
}
2002-11-08 04:50:05 +00:00
2012-06-15 19:09:48 +00:00
// Misc. inits.
2012-06-15 19:09:47 +00:00
CombinedStopReload . init ( ) ;
2013-12-17 18:43:50 +00:00
CombinedBackForward . init ( ) ;
2012-06-15 19:09:47 +00:00
gPrivateBrowsingUI . init ( ) ;
2013-01-11 12:39:39 +00:00
TabsInTitlebar . init ( ) ;
2011-02-04 08:09:04 +00:00
2012-10-23 23:16:08 +00:00
// Wait until chrome is painted before executing code not critical to making the window visible
2013-07-26 11:16:29 +00:00
this . _boundDelayedStartup = this . _delayedStartup . bind ( this , mustLoadSidebar ) ;
2012-10-23 23:16:08 +00:00
window . addEventListener ( "MozAfterPaint" , this . _boundDelayedStartup ) ;
2012-12-07 11:10:41 +00:00
this . _loadHandled = true ;
2012-06-15 19:09:47 +00:00
} ,
2009-02-22 19:09:10 +00:00
2012-10-23 23:16:08 +00:00
_cancelDelayedStartup : function ( ) {
window . removeEventListener ( "MozAfterPaint" , this . _boundDelayedStartup ) ;
this . _boundDelayedStartup = null ;
} ,
2013-07-26 11:16:29 +00:00
_delayedStartup : function ( mustLoadSidebar ) {
2012-06-15 19:09:47 +00:00
let tmp = { } ;
2013-02-09 18:28:38 +00:00
Cu . import ( "resource://gre/modules/TelemetryTimestamps.jsm" , tmp ) ;
2012-06-15 19:09:47 +00:00
let TelemetryTimestamps = tmp . TelemetryTimestamps ;
TelemetryTimestamps . add ( "delayedStartupStarted" ) ;
2012-10-23 23:16:08 +00:00
this . _cancelDelayedStartup ( ) ;
2012-06-15 19:09:47 +00:00
2013-07-02 00:33:19 +00:00
// We need to set the MozApplicationManifest event listeners up
// before we start loading the home pages in case a document has
// a "manifest" attribute, in which the MozApplicationManifest event
// will be fired.
gBrowser . addEventListener ( "MozApplicationManifest" ,
OfflineApps , false ) ;
// listen for offline apps on social
let socialBrowser = document . getElementById ( "social-sidebar-browser" ) ;
socialBrowser . addEventListener ( "MozApplicationManifest" ,
OfflineApps , false ) ;
2013-07-26 11:16:29 +00:00
let uriToLoad = this . _getUriToLoad ( ) ;
2012-11-02 02:46:56 +00:00
var isLoadingBlank = isBlankPageURL ( uriToLoad ) ;
2013-03-15 13:13:52 +00:00
// This pageshow listener needs to be registered before we may call
// swapBrowsersAndCloseOther() to receive pageshow events fired by that.
gBrowser . addEventListener ( "pageshow" , function ( event ) {
// Filter out events that are not about the document load we are interested in
if ( content && event . target == content . document )
2013-04-19 19:31:40 +00:00
setTimeout ( pageShowEventHandlers , 0 , event . persisted ) ;
2013-03-15 13:13:52 +00:00
} , true ) ;
2012-11-02 02:46:56 +00:00
if ( uriToLoad && uriToLoad != "about:blank" ) {
if ( uriToLoad instanceof Ci . nsISupportsArray ) {
let count = uriToLoad . Count ( ) ;
let specs = [ ] ;
for ( let i = 0 ; i < count ; i ++ ) {
let urisstring = uriToLoad . GetElementAt ( i ) . QueryInterface ( Ci . nsISupportsString ) ;
specs . push ( urisstring . data ) ;
}
// This function throws for certain malformed URIs, so use exception handling
// so that we don't disrupt startup
try {
gBrowser . loadTabs ( specs , false , true ) ;
} catch ( e ) { }
}
else if ( uriToLoad instanceof XULElement ) {
// swap the given tab with the default about:blank tab and then close
// the original tab in the other window.
// Stop the about:blank load
gBrowser . stop ( ) ;
// make sure it has a docshell
gBrowser . docShell ;
gBrowser . swapBrowsersAndCloseOther ( gBrowser . selectedTab , uriToLoad ) ;
}
2013-07-26 11:16:29 +00:00
// window.arguments[2]: referrer (nsIURI)
// [3]: postData (nsIInputStream)
// [4]: allowThirdPartyFixup (bool)
2012-11-02 02:46:56 +00:00
else if ( window . arguments . length >= 3 ) {
loadURI ( uriToLoad , window . arguments [ 2 ] , window . arguments [ 3 ] || null ,
window . arguments [ 4 ] || false ) ;
window . focus ( ) ;
}
// Note: loadOneOrMoreURIs *must not* be called if window.arguments.length >= 3.
// Such callers expect that window.arguments[0] is handled as a single URI.
2014-02-14 11:00:49 +00:00
else {
if ( uriToLoad == "about:newtab" &&
Services . prefs . getBoolPref ( "browser.newtabpage.enabled" ) ) {
Services . telemetry . getHistogramById ( "NEWTAB_PAGE_SHOWN" ) . add ( true ) ;
}
2012-11-02 02:46:56 +00:00
loadOneOrMoreURIs ( uriToLoad ) ;
2014-02-14 11:00:49 +00:00
}
2012-11-02 02:46:56 +00:00
}
2012-07-28 06:25:11 +00:00
# ifdef MOZ _SAFE _BROWSING
2012-07-31 05:54:56 +00:00
// Bug 778855 - Perf regression if we do this here. To be addressed in bug 779008.
setTimeout ( function ( ) { SafeBrowsing . init ( ) ; } , 2000 ) ;
2012-07-28 06:25:11 +00:00
# endif
2012-06-15 19:09:47 +00:00
Services . obs . addObserver ( gSessionHistoryObserver , "browser:purge-session-history" , false ) ;
Services . obs . addObserver ( gXPInstallObserver , "addon-install-disabled" , false ) ;
Services . obs . addObserver ( gXPInstallObserver , "addon-install-started" , false ) ;
Services . obs . addObserver ( gXPInstallObserver , "addon-install-blocked" , false ) ;
Services . obs . addObserver ( gXPInstallObserver , "addon-install-failed" , false ) ;
Services . obs . addObserver ( gXPInstallObserver , "addon-install-complete" , false ) ;
Services . obs . addObserver ( gFormSubmitObserver , "invalidformsubmit" , false ) ;
BrowserOffline . init ( ) ;
OfflineApps . init ( ) ;
IndexedDBPromptHelper . init ( ) ;
gFormSubmitObserver . init ( ) ;
2014-02-11 17:01:08 +00:00
gRemoteTabsUI . init ( ) ;
2014-03-12 03:13:45 +00:00
gPageStyleMenu . init ( ) ;
2013-07-28 09:50:05 +00:00
2013-05-14 16:55:21 +00:00
// Initialize the full zoom setting.
// We do this before the session restore service gets initialized so we can
// apply full zoom settings to tabs restored by the session restore service.
FullZoom . init ( ) ;
2013-09-26 09:59:12 +00:00
PanelUI . init ( ) ;
2013-07-10 22:00:03 +00:00
LightweightThemeListener . init ( ) ;
2012-12-28 09:25:59 +00:00
WebrtcIndicator . init ( ) ;
2012-06-15 19:09:47 +00:00
// Ensure login manager is up and running.
2012-12-20 20:34:06 +00:00
Services . logins ;
2012-06-15 19:09:47 +00:00
2013-09-12 19:24:10 +00:00
# ifdef MOZ _CRASHREPORTER
if ( gMultiProcessBrowser )
TabCrashReporter . init ( ) ;
# endif
2012-06-15 19:09:47 +00:00
if ( mustLoadSidebar ) {
let sidebar = document . getElementById ( "sidebar" ) ;
let sidebarBox = document . getElementById ( "sidebar-box" ) ;
sidebar . setAttribute ( "src" , sidebarBox . getAttribute ( "src" ) ) ;
}
2002-11-08 04:50:05 +00:00
2012-06-15 19:09:47 +00:00
UpdateUrlbarSearchSplitterState ( ) ;
2005-06-14 10:15:58 +00:00
2012-08-22 14:08:12 +00:00
if ( ! isLoadingBlank || ! focusAndSelectUrlBar ( ) )
2012-06-15 19:09:47 +00:00
gBrowser . selectedBrowser . focus ( ) ;
2010-03-24 21:22:04 +00:00
2012-06-15 19:09:47 +00:00
// Set up Sanitize Item
2012-06-15 19:09:48 +00:00
this . _initializeSanitizer ( ) ;
2002-11-16 17:14:12 +00:00
2012-06-15 19:09:47 +00:00
// Enable/Disable auto-hide tabbar
gBrowser . tabContainer . updateVisibility ( ) ;
2005-02-25 09:07:58 +00:00
2014-01-22 12:31:09 +00:00
BookmarkingUI . init ( ) ;
2012-06-15 19:09:47 +00:00
gPrefService . addObserver ( gHomeButton . prefDomain , gHomeButton , false ) ;
2005-02-14 19:26:50 +00:00
2012-06-15 19:09:47 +00:00
var homeButton = document . getElementById ( "home-button" ) ;
gHomeButton . updateTooltip ( homeButton ) ;
gHomeButton . updatePersonalToolbarStyle ( homeButton ) ;
2008-02-20 09:56:52 +00:00
2012-06-15 19:09:47 +00:00
// BiDi UI
gBidiUI = isBidiEnabled ( ) ;
if ( gBidiUI ) {
document . getElementById ( "documentDirection-separator" ) . hidden = false ;
document . getElementById ( "documentDirection-swap" ) . hidden = false ;
document . getElementById ( "textfieldDirection-separator" ) . hidden = false ;
document . getElementById ( "textfieldDirection-swap" ) . hidden = false ;
}
2005-06-14 10:15:58 +00:00
2012-06-15 19:09:47 +00:00
// Setup click-and-hold gestures access to the session history
// menus if global click-and-hold isn't turned on
if ( ! getBoolPref ( "ui.click_hold_context_menus" , false ) )
SetClickAndHoldHandlers ( ) ;
2006-04-20 22:35:06 +00:00
2014-03-12 03:13:48 +00:00
let NP = { } ;
Cu . import ( "resource:///modules/NetworkPrioritizer.jsm" , NP ) ;
NP . trackBrowserWindow ( window ) ;
2009-10-30 21:16:17 +00:00
2012-06-15 19:09:47 +00:00
PlacesToolbarHelper . init ( ) ;
2010-05-05 13:28:04 +00:00
2012-06-15 19:09:47 +00:00
ctrlTab . readPref ( ) ;
gPrefService . addObserver ( ctrlTab . prefName , ctrlTab , false ) ;
2008-07-15 16:11:00 +00:00
2012-06-15 19:09:47 +00:00
// Initialize the download manager some time after the app starts so that
// auto-resume downloads begin (such as after crashing or quitting with
// active downloads) and speeds up the first-load of the download manager UI.
// If the user manually opens the download manager before the timeout, the
2013-11-04 18:21:13 +00:00
// downloads will start right away, and initializing again won't hurt.
2012-06-15 19:09:47 +00:00
setTimeout ( function ( ) {
2013-09-18 13:16:00 +00:00
try {
2013-11-04 18:21:13 +00:00
Cu . import ( "resource:///modules/DownloadsCommon.jsm" , { } )
. DownloadsCommon . initializeAllDataLinks ( ) ;
Cu . import ( "resource:///modules/DownloadsTaskbar.jsm" , { } )
. DownloadsTaskbar . registerIndicator ( window ) ;
2013-09-18 13:16:00 +00:00
} catch ( ex ) {
Cu . reportError ( ex ) ;
2013-08-03 11:04:44 +00:00
}
2012-06-15 19:09:47 +00:00
} , 10000 ) ;
2008-01-26 05:48:51 +00:00
2012-06-15 19:09:47 +00:00
// The object handling the downloads indicator is also initialized here in the
// delayed startup function, but the actual indicator element is not loaded
// unless there are downloads to be displayed.
DownloadsButton . initializeIndicator ( ) ;
2012-04-17 11:35:09 +00:00
2008-01-26 05:48:51 +00:00
# ifndef XP _MACOSX
2012-06-15 19:09:47 +00:00
updateEditUIVisibility ( ) ;
let placesContext = document . getElementById ( "placesContext" ) ;
placesContext . addEventListener ( "popupshowing" , updateEditUIVisibility , false ) ;
placesContext . addEventListener ( "popuphiding" , updateEditUIVisibility , false ) ;
2008-01-26 05:48:51 +00:00
# endif
2008-09-03 22:05:15 +00:00
2012-06-15 19:09:47 +00:00
gBrowser . mPanelContainer . addEventListener ( "InstallBrowserTheme" , LightWeightThemeWebInstaller , false , true ) ;
gBrowser . mPanelContainer . addEventListener ( "PreviewBrowserTheme" , LightWeightThemeWebInstaller , false , true ) ;
gBrowser . mPanelContainer . addEventListener ( "ResetBrowserThemePreview" , LightWeightThemeWebInstaller , false , true ) ;
2009-10-06 04:26:15 +00:00
2013-09-12 06:50:46 +00:00
if ( Win7Features )
Win7Features . onOpenWindow ( ) ;
2010-04-06 06:34:27 +00:00
2012-06-15 19:09:48 +00:00
// called when we go into full screen, even if initiated by a web page script
2012-06-15 19:09:47 +00:00
window . addEventListener ( "fullscreen" , onFullScreen , true ) ;
2011-10-28 08:28:05 +00:00
2012-06-15 19:09:47 +00:00
// Called when we enter DOM full-screen mode. Note we can already be in browser
// full-screen mode when we enter DOM full-screen mode.
window . addEventListener ( "MozEnteredDomFullscreen" , onMozEnteredDomFullscreen , true ) ;
2011-10-28 08:28:05 +00:00
2012-06-15 19:09:47 +00:00
if ( window . fullScreen )
onFullScreen ( ) ;
if ( document . mozFullScreen )
onMozEnteredDomFullscreen ( ) ;
2010-08-27 04:44:01 +00:00
2010-08-02 23:37:56 +00:00
# ifdef MOZ _SERVICES _SYNC
2012-06-15 19:09:47 +00:00
// initialize the sync UI
gSyncUI . init ( ) ;
2014-01-25 15:19:07 +00:00
gFxAccounts . init ( ) ;
2010-08-02 23:37:56 +00:00
# endif
2013-01-12 03:05:35 +00:00
# ifdef MOZ _DATA _REPORTING
gDataNotificationInfoBar . init ( ) ;
# endif
2012-06-15 19:09:47 +00:00
gBrowserThumbnails . init ( ) ;
2010-08-07 22:32:17 +00:00
2012-11-30 08:07:59 +00:00
// Add Devtools menuitems and listeners
2012-12-13 13:03:55 +00:00
gDevToolsBrowser . registerBrowserWindow ( window ) ;
2012-11-30 08:07:59 +00:00
2012-06-15 19:09:47 +00:00
window . addEventListener ( "mousemove" , MousePosTracker , false ) ;
window . addEventListener ( "dragover" , MousePosTracker , false ) ;
2002-08-04 02:53:09 +00:00
2013-05-17 19:29:05 +00:00
gNavToolbox . addEventListener ( "customizationstarting" , CustomizationHandler ) ;
2014-01-22 09:42:51 +00:00
gNavToolbox . addEventListener ( "customizationchange" , CustomizationHandler ) ;
2013-05-17 19:29:05 +00:00
gNavToolbox . addEventListener ( "customizationending" , CustomizationHandler ) ;
2013-04-05 13:56:30 +00:00
2012-06-15 19:09:47 +00:00
// End startup crash tracking after a delay to catch crashes while restoring
// tabs and to postpone saving the pref to disk.
try {
const startupCrashEndDelay = 30 * 1000 ;
2012-12-20 20:34:06 +00:00
setTimeout ( Services . startup . trackStartupCrashEnd , startupCrashEndDelay ) ;
2012-06-15 19:09:47 +00:00
} catch ( ex ) {
Cu . reportError ( "Could not end startup crash tracking: " + ex ) ;
}
2009-10-12 06:13:25 +00:00
2013-11-19 20:54:03 +00:00
if ( typeof WindowsPrefSync !== 'undefined' ) {
// Pulls in Metro controlled prefs and pushes out Desktop controlled prefs
WindowsPrefSync . init ( ) ;
}
2013-06-12 14:31:09 +00:00
2013-07-27 05:40:07 +00:00
SessionStore . promiseInitialized . then ( ( ) => {
2014-03-12 02:25:45 +00:00
// Bail out if the window has been closed in the meantime.
if ( window . closed ) {
return ;
}
2013-07-25 19:50:15 +00:00
// Enable the Restore Last Session command if needed
2013-10-22 06:20:15 +00:00
RestoreLastSessionObserver . init ( ) ;
2013-07-25 19:50:15 +00:00
2014-03-12 02:25:45 +00:00
SocialUI . init ( ) ;
2013-07-25 19:50:15 +00:00
TabView . init ( ) ;
2013-08-02 20:02:22 +00:00
setTimeout ( function ( ) { BrowserChromeTest . markAsReady ( ) ; } , 0 ) ;
2013-07-25 19:50:15 +00:00
} ) ;
2013-10-22 11:07:30 +00:00
this . delayedStartupFinished = true ;
2013-07-25 19:50:15 +00:00
2013-06-12 14:31:09 +00:00
Services . obs . notifyObservers ( window , "browser-delayed-startup-finished" , "" ) ;
TelemetryTimestamps . add ( "delayedStartupFinished" ) ;
2012-06-15 19:09:47 +00:00
} ,
2011-09-26 17:11:22 +00:00
2013-07-26 11:16:29 +00:00
// Returns the URI(s) to load at startup.
_getUriToLoad : function ( ) {
// window.arguments[0]: URI to load (string), or an nsISupportsArray of
// nsISupportsStrings to load, or a xul:tab of
// a tabbrowser, which will be replaced by this
// window (for this case, all other arguments are
// ignored).
if ( ! window . arguments || ! window . arguments [ 0 ] )
return null ;
let uri = window . arguments [ 0 ] ;
let sessionStartup = Cc [ "@mozilla.org/browser/sessionstartup;1" ]
. getService ( Ci . nsISessionStartup ) ;
let defaultArgs = Cc [ "@mozilla.org/browser/clh;1" ]
. getService ( Ci . nsIBrowserHandler )
. defaultArgs ;
// If the given URI matches defaultArgs (the default homepage) we want
// to block its load if we're going to restore a session anyway.
if ( uri == defaultArgs && sessionStartup . willOverrideHomepage )
return null ;
return uri ;
} ,
2012-06-15 19:09:48 +00:00
onUnload : function ( ) {
2012-06-15 19:09:47 +00:00
// In certain scenarios it's possible for unload to be fired before onload,
// (e.g. if the window is being closed after browser.js loads but before the
// load completes). In that case, there's nothing to do here.
2012-12-07 11:10:41 +00:00
if ( ! this . _loadHandled )
2012-06-15 19:09:47 +00:00
return ;
2008-12-02 09:21:13 +00:00
2012-12-13 13:03:55 +00:00
gDevToolsBrowser . forgetBrowserWindow ( window ) ;
2010-01-05 07:28:46 +00:00
2013-01-04 20:31:38 +00:00
let desc = Object . getOwnPropertyDescriptor ( window , "DeveloperToolbar" ) ;
if ( desc && ! desc . get ) {
DeveloperToolbar . destroy ( ) ;
}
2012-06-15 19:09:48 +00:00
// First clean up services initialized in gBrowserInit.onLoad (or those whose
2012-06-15 19:09:47 +00:00
// uninit methods don't depend on the services having been initialized).
2008-10-23 20:15:22 +00:00
2012-06-15 19:09:47 +00:00
CombinedStopReload . uninit ( ) ;
2013-12-17 18:43:50 +00:00
CombinedBackForward . uninit ( ) ;
2009-10-06 12:33:55 +00:00
2012-06-15 19:09:47 +00:00
gGestureSupport . init ( false ) ;
2004-04-07 17:37:55 +00:00
2013-04-09 19:44:01 +00:00
gHistorySwipeAnimation . uninit ( ) ;
2012-06-15 19:09:47 +00:00
FullScreen . cleanup ( ) ;
2002-08-04 02:53:09 +00:00
2014-01-25 15:19:07 +00:00
# ifdef MOZ _SERVICES _SYNC
gFxAccounts . uninit ( ) ;
# endif
2012-06-15 19:09:47 +00:00
Services . obs . removeObserver ( gPluginHandler . pluginCrashed , "plugin-crashed" ) ;
2004-01-22 01:46:48 +00:00
2012-06-15 19:09:47 +00:00
try {
gBrowser . removeProgressListener ( window . XULBrowserWindow ) ;
gBrowser . removeTabsProgressListener ( window . TabsProgressListener ) ;
} catch ( ex ) {
}
2011-04-26 13:23:07 +00:00
2013-05-10 15:19:48 +00:00
BookmarkingUI . uninit ( ) ;
2012-01-10 09:13:26 +00:00
2012-06-15 19:09:47 +00:00
TabsInTitlebar . uninit ( ) ;
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
var enumerator = Services . wm . getEnumerator ( null ) ;
enumerator . getNext ( ) ;
if ( ! enumerator . hasMoreElements ( ) ) {
document . persist ( "sidebar-box" , "sidebarcommand" ) ;
document . persist ( "sidebar-box" , "width" ) ;
document . persist ( "sidebar-box" , "src" ) ;
document . persist ( "sidebar-title" , "value" ) ;
}
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
// Now either cancel delayedStartup, or clean up the services initialized from
// it.
2012-10-23 23:16:08 +00:00
if ( this . _boundDelayedStartup ) {
this . _cancelDelayedStartup ( ) ;
2012-06-15 19:09:47 +00:00
} else {
if ( Win7Features )
Win7Features . onCloseWindow ( ) ;
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
gPrefService . removeObserver ( ctrlTab . prefName , ctrlTab ) ;
ctrlTab . uninit ( ) ;
TabView . uninit ( ) ;
2014-03-12 02:25:45 +00:00
SocialUI . uninit ( ) ;
2012-06-15 19:09:47 +00:00
gBrowserThumbnails . uninit ( ) ;
2011-04-26 13:23:07 +00:00
FullZoom . destroy ( ) ;
2012-06-15 19:09:47 +00:00
Services . obs . removeObserver ( gSessionHistoryObserver , "browser:purge-session-history" ) ;
Services . obs . removeObserver ( gXPInstallObserver , "addon-install-disabled" ) ;
Services . obs . removeObserver ( gXPInstallObserver , "addon-install-started" ) ;
Services . obs . removeObserver ( gXPInstallObserver , "addon-install-blocked" ) ;
Services . obs . removeObserver ( gXPInstallObserver , "addon-install-failed" ) ;
Services . obs . removeObserver ( gXPInstallObserver , "addon-install-complete" ) ;
Services . obs . removeObserver ( gFormSubmitObserver , "invalidformsubmit" ) ;
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
try {
gPrefService . removeObserver ( gHomeButton . prefDomain , gHomeButton ) ;
} catch ( ex ) {
2012-06-15 19:09:48 +00:00
Cu . reportError ( ex ) ;
2012-06-15 19:09:47 +00:00
}
2011-04-26 13:23:07 +00:00
2013-11-19 20:54:03 +00:00
if ( typeof WindowsPrefSync !== 'undefined' ) {
WindowsPrefSync . uninit ( ) ;
}
2013-05-22 14:17:05 +00:00
2012-06-15 19:09:47 +00:00
BrowserOffline . uninit ( ) ;
OfflineApps . uninit ( ) ;
IndexedDBPromptHelper . uninit ( ) ;
2013-04-23 00:01:31 +00:00
LightweightThemeListener . uninit ( ) ;
2013-03-26 21:23:23 +00:00
PanelUI . uninit ( ) ;
2012-06-15 19:09:47 +00:00
}
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
// Final window teardown, do this last.
window . XULBrowserWindow = null ;
2012-06-15 19:09:48 +00:00
window . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShellTreeItem ) . treeOwner
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIXULWindow )
2012-06-15 19:09:47 +00:00
. XULBrowserWindow = null ;
window . QueryInterface ( Ci . nsIDOMChromeWindow ) . browserDOMWindow = null ;
} ,
2002-08-04 02:53:09 +00:00
2005-01-24 23:40:03 +00:00
# ifdef XP _MACOSX
2012-06-15 19:09:47 +00:00
// nonBrowserWindowStartup(), nonBrowserWindowDelayedStartup(), and
// nonBrowserWindowShutdown() are used for non-browser windows in
// macBrowserOverlay
nonBrowserWindowStartup : function ( ) {
// Disable inappropriate commands / submenus
var disabledItems = [ 'Browser:SavePage' ,
'Browser:SendLink' , 'cmd_pageSetup' , 'cmd_print' , 'cmd_find' , 'cmd_findAgain' ,
'viewToolbarsMenu' , 'viewSidebarMenuMenu' , 'Browser:Reload' ,
'viewFullZoomMenu' , 'pageStyleMenu' , 'charsetMenu' , 'View:PageSource' , 'View:FullScreen' ,
'viewHistorySidebar' , 'Browser:AddBookmarkAs' , 'Browser:BookmarkAllTabs' ,
2013-05-09 10:08:07 +00:00
'View:PageInfo' , 'Browser:ToggleTabView' ] ;
2012-06-15 19:09:47 +00:00
var element ;
2012-08-22 07:58:18 +00:00
for ( let disabledItem of disabledItems ) {
element = document . getElementById ( disabledItem ) ;
2005-04-19 15:32:38 +00:00
if ( element )
element . setAttribute ( "disabled" , "true" ) ;
}
2012-06-15 19:09:47 +00:00
// If no windows are active (i.e. we're the hidden window), disable the close, minimize
// and zoom menu commands as well
if ( window . location . href == "chrome://browser/content/hiddenWindow.xul" ) {
var hiddenWindowDisabledItems = [ 'cmd_close' , 'minimizeWindow' , 'zoomWindow' ] ;
2012-08-22 07:58:18 +00:00
for ( let hiddenWindowDisabledItem of hiddenWindowDisabledItems ) {
element = document . getElementById ( hiddenWindowDisabledItem ) ;
2012-06-15 19:09:47 +00:00
if ( element )
element . setAttribute ( "disabled" , "true" ) ;
}
2010-02-22 20:51:30 +00:00
2012-06-15 19:09:47 +00:00
// also hide the window-list separator
element = document . getElementById ( "sep-window-list" ) ;
element . setAttribute ( "hidden" , "true" ) ;
2010-02-22 20:51:30 +00:00
2012-06-15 19:09:47 +00:00
// Setup the dock menu.
let dockMenuElement = document . getElementById ( "menu_mac_dockmenu" ) ;
if ( dockMenuElement != null ) {
let nativeMenu = Cc [ "@mozilla.org/widget/standalonenativemenu;1" ]
. createInstance ( Ci . nsIStandaloneNativeMenu ) ;
2010-02-22 20:51:30 +00:00
2012-06-15 19:09:47 +00:00
try {
nativeMenu . init ( dockMenuElement ) ;
let dockSupport = Cc [ "@mozilla.org/widget/macdocksupport;1" ]
. getService ( Ci . nsIMacDockSupport ) ;
dockSupport . dockMenu = nativeMenu ;
}
catch ( e ) {
}
2010-02-22 20:51:30 +00:00
}
}
2005-01-24 23:40:03 +00:00
2013-04-08 15:30:50 +00:00
if ( PrivateBrowsingUtils . permanentPrivateBrowsing ) {
document . getElementById ( "macDockMenuNewWindow" ) . hidden = true ;
}
2012-10-23 23:16:08 +00:00
this . _delayedStartupTimeoutId = setTimeout ( this . nonBrowserWindowDelayedStartup . bind ( this ) , 0 ) ;
2012-06-15 19:09:47 +00:00
} ,
2005-01-24 23:40:03 +00:00
2012-06-15 19:09:47 +00:00
nonBrowserWindowDelayedStartup : function ( ) {
2012-10-23 23:16:08 +00:00
this . _delayedStartupTimeoutId = null ;
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
// initialise the offline listener
BrowserOffline . init ( ) ;
2010-03-24 21:22:04 +00:00
2012-06-15 19:09:47 +00:00
// Set up Sanitize Item
2012-06-15 19:09:48 +00:00
this . _initializeSanitizer ( ) ;
2009-01-09 11:24:17 +00:00
2012-06-15 19:09:47 +00:00
// initialize the private browsing UI
gPrivateBrowsingUI . init ( ) ;
2010-08-02 23:37:56 +00:00
# ifdef MOZ _SERVICES _SYNC
2012-06-15 19:09:47 +00:00
// initialize the sync UI
gSyncUI . init ( ) ;
2010-08-02 23:37:56 +00:00
# endif
2012-06-15 19:09:47 +00:00
} ,
2007-08-31 17:08:03 +00:00
2012-06-15 19:09:47 +00:00
nonBrowserWindowShutdown : function ( ) {
// If nonBrowserWindowDelayedStartup hasn't run yet, we have no work to do -
// just cancel the pending timeout and return;
2012-10-23 23:16:08 +00:00
if ( this . _delayedStartupTimeoutId ) {
clearTimeout ( this . _delayedStartupTimeoutId ) ;
2012-06-15 19:09:47 +00:00
return ;
}
2011-04-26 13:23:07 +00:00
2012-06-15 19:09:47 +00:00
BrowserOffline . uninit ( ) ;
} ,
2005-01-24 23:40:03 +00:00
# endif
2005-06-14 10:15:58 +00:00
2012-06-15 19:09:48 +00:00
_initializeSanitizer : function ( ) {
2012-06-15 19:09:47 +00:00
const kDidSanitizeDomain = "privacy.sanitize.didShutdownSanitize" ;
if ( gPrefService . prefHasUserValue ( kDidSanitizeDomain ) ) {
gPrefService . clearUserPref ( kDidSanitizeDomain ) ;
// We need to persist this preference change, since we want to
// check it at next app start even if the browser exits abruptly
gPrefService . savePrefFile ( null ) ;
2009-05-21 09:51:56 +00:00
}
2012-06-15 19:09:47 +00:00
/ * *
* Migrate Firefox 3.0 privacy . item prefs under one of these conditions :
*
* a ) User has customized any privacy . item prefs
* b ) privacy . sanitize . sanitizeOnShutdown is set
* /
if ( ! gPrefService . getBoolPref ( "privacy.sanitize.migrateFx3Prefs" ) ) {
let itemBranch = gPrefService . getBranch ( "privacy.item." ) ;
let itemArray = itemBranch . getChildList ( "" ) ;
// See if any privacy.item prefs are set
let doMigrate = itemArray . some ( function ( name ) itemBranch . prefHasUserValue ( name ) ) ;
// Or if sanitizeOnShutdown is set
if ( ! doMigrate )
doMigrate = gPrefService . getBoolPref ( "privacy.sanitize.sanitizeOnShutdown" ) ;
if ( doMigrate ) {
let cpdBranch = gPrefService . getBranch ( "privacy.cpd." ) ;
let clearOnShutdownBranch = gPrefService . getBranch ( "privacy.clearOnShutdown." ) ;
2012-08-21 16:56:07 +00:00
for ( let name of itemArray ) {
2012-06-15 19:09:47 +00:00
try {
// don't migrate password or offlineApps clearing in the CRH dialog since
// there's no UI for those anymore. They default to false. bug 497656
if ( name != "passwords" && name != "offlineApps" )
cpdBranch . setBoolPref ( name , itemBranch . getBoolPref ( name ) ) ;
clearOnShutdownBranch . setBoolPref ( name , itemBranch . getBoolPref ( name ) ) ;
}
catch ( e ) {
Cu . reportError ( "Exception thrown during privacy pref migration: " + e ) ;
}
2012-08-21 16:56:07 +00:00
}
2012-06-15 19:09:47 +00:00
}
gPrefService . setBoolPref ( "privacy.sanitize.migrateFx3Prefs" , true ) ;
2009-05-21 09:51:56 +00:00
}
2012-06-15 19:09:47 +00:00
} ,
2005-02-25 09:07:58 +00:00
}
2013-05-22 14:17:05 +00:00
2012-06-15 19:09:47 +00:00
/* Legacy global init functions */
2012-06-15 19:09:48 +00:00
var BrowserStartup = gBrowserInit . onLoad . bind ( gBrowserInit ) ;
var BrowserShutdown = gBrowserInit . onUnload . bind ( gBrowserInit ) ;
2012-06-15 19:09:47 +00:00
# ifdef XP _MACOSX
var nonBrowserWindowStartup = gBrowserInit . nonBrowserWindowStartup . bind ( gBrowserInit ) ;
var nonBrowserWindowDelayedStartup = gBrowserInit . nonBrowserWindowDelayedStartup . bind ( gBrowserInit ) ;
var nonBrowserWindowShutdown = gBrowserInit . nonBrowserWindowShutdown . bind ( gBrowserInit ) ;
# endif
2012-06-15 19:09:47 +00:00
function HandleAppCommandEvent ( evt ) {
switch ( evt . command ) {
case "Back" :
BrowserBack ( ) ;
break ;
case "Forward" :
BrowserForward ( ) ;
break ;
case "Reload" :
BrowserReloadSkipCache ( ) ;
break ;
case "Stop" :
2012-12-20 21:16:11 +00:00
if ( XULBrowserWindow . stopCommand . getAttribute ( "disabled" ) != "true" )
BrowserStop ( ) ;
2012-06-15 19:09:47 +00:00
break ;
case "Search" :
BrowserSearch . webSearch ( ) ;
break ;
case "Bookmarks" :
toggleSidebar ( 'viewBookmarksSidebar' ) ;
break ;
case "Home" :
BrowserHome ( ) ;
break ;
2012-12-31 00:33:49 +00:00
case "New" :
BrowserOpenTab ( ) ;
break ;
case "Close" :
BrowserCloseTabOrWindow ( ) ;
break ;
case "Find" :
gFindBar . onFindCommand ( ) ;
break ;
case "Help" :
openHelpLink ( 'firefox-help' ) ;
break ;
case "Open" :
BrowserOpenFileWindow ( ) ;
2012-06-15 19:09:47 +00:00
break ;
2012-12-31 00:33:49 +00:00
case "Print" :
PrintUtils . print ( ) ;
break ;
case "Save" :
saveDocument ( window . content . document ) ;
break ;
case "SendMail" :
MailIntegration . sendLinkForWindow ( window . content ) ;
break ;
default :
return ;
2009-07-15 07:22:37 +00:00
}
2012-12-31 00:33:49 +00:00
evt . stopPropagation ( ) ;
evt . preventDefault ( ) ;
2005-02-25 09:07:58 +00:00
}
2010-09-10 19:57:18 +00:00
function gotoHistoryIndex ( aEvent ) {
let index = aEvent . target . getAttribute ( "index" ) ;
2002-08-04 02:53:09 +00:00
if ( ! index )
return false ;
2004-06-23 22:54:12 +00:00
2010-09-10 19:57:18 +00:00
let where = whereToOpenLink ( aEvent ) ;
2004-06-23 22:54:12 +00:00
if ( where == "current" ) {
2010-09-10 19:57:18 +00:00
// Normal click. Go there in the current tab and update session history.
2004-06-23 22:54:12 +00:00
try {
2008-07-30 20:28:29 +00:00
gBrowser . gotoIndex ( index ) ;
2004-06-23 22:54:12 +00:00
}
catch ( ex ) {
return false ;
}
return true ;
2002-08-04 02:53:09 +00:00
}
2010-09-10 19:57:18 +00:00
// Modified click. Go there in a new tab/window.
2005-06-14 10:15:58 +00:00
2011-01-10 19:01:47 +00:00
duplicateTabIn ( gBrowser . selectedTab , where , index - gBrowser . sessionHistory . index ) ;
2010-09-10 19:57:18 +00:00
return true ;
2004-06-23 22:54:12 +00:00
}
2008-09-01 20:19:24 +00:00
function BrowserForward ( aEvent ) {
2010-09-10 19:57:18 +00:00
let where = whereToOpenLink ( aEvent , false , true ) ;
2002-08-04 02:53:09 +00:00
2004-06-23 22:54:12 +00:00
if ( where == "current" ) {
try {
2008-07-30 20:28:29 +00:00
gBrowser . goForward ( ) ;
2004-06-23 22:54:12 +00:00
}
catch ( ex ) {
}
}
else {
2011-01-10 19:01:47 +00:00
duplicateTabIn ( gBrowser . selectedTab , where , 1 ) ;
2004-06-23 22:54:12 +00:00
}
2002-08-04 02:53:09 +00:00
}
2008-09-01 20:19:24 +00:00
function BrowserBack ( aEvent ) {
2010-09-10 19:57:18 +00:00
let where = whereToOpenLink ( aEvent , false , true ) ;
2004-06-23 22:54:12 +00:00
if ( where == "current" ) {
try {
2008-07-30 20:28:29 +00:00
gBrowser . goBack ( ) ;
2004-06-23 22:54:12 +00:00
}
catch ( ex ) {
}
2002-08-04 02:53:09 +00:00
}
2004-06-23 22:54:12 +00:00
else {
2011-01-10 19:01:47 +00:00
duplicateTabIn ( gBrowser . selectedTab , where , - 1 ) ;
2002-08-04 02:53:09 +00:00
}
}
2003-05-31 18:43:50 +00:00
function BrowserHandleBackspace ( )
{
2005-10-20 15:16:27 +00:00
switch ( gPrefService . getIntPref ( "browser.backspace_action" ) ) {
case 0 :
BrowserBack ( ) ;
break ;
case 1 :
goDoCommand ( "cmd_scrollPageUp" ) ;
break ;
}
}
function BrowserHandleShiftBackspace ( )
{
switch ( gPrefService . getIntPref ( "browser.backspace_action" ) ) {
case 0 :
BrowserForward ( ) ;
break ;
case 1 :
goDoCommand ( "cmd_scrollPageDown" ) ;
break ;
}
2003-05-31 18:43:50 +00:00
}
2012-06-15 19:09:48 +00:00
function BrowserStop ( ) {
const stopFlags = nsIWebNavigation . STOP _ALL ;
gBrowser . webNavigation . stop ( stopFlags ) ;
2002-08-04 02:53:09 +00:00
}
2008-08-31 21:00:59 +00:00
function BrowserReloadOrDuplicate ( aEvent ) {
var backgroundTabModifier = aEvent . button == 1 ||
# ifdef XP _MACOSX
aEvent . metaKey ;
# else
aEvent . ctrlKey ;
# endif
if ( aEvent . shiftKey && ! backgroundTabModifier ) {
BrowserReloadSkipCache ( ) ;
return ;
}
2010-09-10 19:57:18 +00:00
let where = whereToOpenLink ( aEvent , false , true ) ;
2008-08-31 21:00:59 +00:00
if ( where == "current" )
BrowserReload ( ) ;
else
2010-09-10 19:57:18 +00:00
duplicateTabIn ( gBrowser . selectedTab , where ) ;
2008-08-31 21:00:59 +00:00
}
function BrowserReload ( ) {
2002-08-04 02:53:09 +00:00
const reloadFlags = nsIWebNavigation . LOAD _FLAGS _NONE ;
2008-08-31 21:00:59 +00:00
BrowserReloadWithFlags ( reloadFlags ) ;
2002-08-04 02:53:09 +00:00
}
2008-08-31 21:00:59 +00:00
function BrowserReloadSkipCache ( ) {
2002-08-04 02:53:09 +00:00
// Bypass proxy and cache.
const reloadFlags = nsIWebNavigation . LOAD _FLAGS _BYPASS _PROXY | nsIWebNavigation . LOAD _FLAGS _BYPASS _CACHE ;
2008-08-31 21:00:59 +00:00
BrowserReloadWithFlags ( reloadFlags ) ;
2002-08-04 02:53:09 +00:00
}
2010-11-07 14:06:37 +00:00
var BrowserHome = BrowserGoHome ;
2008-09-01 20:19:24 +00:00
function BrowserGoHome ( aEvent ) {
2008-01-09 04:04:31 +00:00
if ( aEvent && "button" in aEvent &&
aEvent . button == 2 ) // right-click: do nothing
2004-07-16 16:32:41 +00:00
return ;
var homePage = gHomeButton . getHomePage ( ) ;
2008-09-01 20:19:24 +00:00
var where = whereToOpenLink ( aEvent , false , true ) ;
2004-07-16 16:32:41 +00:00
var urls ;
2010-11-05 21:03:42 +00:00
// Home page should open in a new tab when current tab is an app tab
if ( where == "current" &&
2011-02-02 02:08:57 +00:00
gBrowser &&
2010-11-05 21:03:42 +00:00
gBrowser . selectedTab . pinned )
where = "tab" ;
2004-07-16 16:32:41 +00:00
// openUILinkIn in utilityOverlay.js doesn't handle loading multiple pages
switch ( where ) {
case "current" :
loadOneOrMoreURIs ( homePage ) ;
break ;
case "tabshifted" :
case "tab" :
urls = homePage . split ( "|" ) ;
2006-01-20 23:04:26 +00:00
var loadInBackground = getBoolPref ( "browser.tabs.loadBookmarksInBackground" , false ) ;
gBrowser . loadTabs ( urls , loadInBackground ) ;
2004-07-16 16:32:41 +00:00
break ;
case "window" :
OpenBrowserWindow ( ) ;
break ;
2002-11-16 17:14:12 +00:00
}
2004-07-16 16:32:41 +00:00
}
function loadOneOrMoreURIs ( aURIString )
{
2005-01-24 23:40:03 +00:00
# ifdef XP _MACOSX
// we're not a browser window, pass the URI string to a new browser window
if ( window . location . href != getBrowserURL ( ) )
{
2007-09-24 20:53:57 +00:00
window . openDialog ( getBrowserURL ( ) , "_blank" , "all,dialog=no" , aURIString ) ;
2005-01-24 23:40:03 +00:00
return ;
}
# endif
2006-01-20 23:04:26 +00:00
// This function throws for certain malformed URIs, so use exception handling
// so that we don't disrupt startup
try {
gBrowser . loadTabs ( aURIString . split ( "|" ) , false , true ) ;
2010-03-24 21:22:04 +00:00
}
2006-01-20 23:04:26 +00:00
catch ( e ) {
2005-01-20 23:04:06 +00:00
}
2002-08-04 02:53:09 +00:00
}
2009-10-05 13:41:24 +00:00
function focusAndSelectUrlBar ( ) {
2011-10-28 14:05:07 +00:00
if ( gURLBar ) {
2009-10-05 13:41:24 +00:00
if ( window . fullScreen )
FullScreen . mouseoverToggle ( true ) ;
2012-08-21 13:53:39 +00:00
2012-09-19 16:55:21 +00:00
gURLBar . select ( ) ;
if ( document . activeElement == gURLBar . inputField )
2009-10-05 13:41:24 +00:00
return true ;
}
return false ;
}
2009-01-21 08:41:34 +00:00
2009-10-05 13:41:24 +00:00
function openLocation ( ) {
if ( focusAndSelectUrlBar ( ) )
2009-01-21 08:41:34 +00:00
return ;
2008-03-08 11:30:39 +00:00
2003-12-02 22:27:25 +00:00
# ifdef XP _MACOSX
2006-08-12 20:33:08 +00:00
if ( window . location . href != getBrowserURL ( ) ) {
2005-06-09 00:18:02 +00:00
var win = getTopWin ( ) ;
if ( win ) {
// If there's an open browser window, it should handle this command
win . focus ( )
win . openLocation ( ) ;
}
else {
// If there are no open browser windows, open a new one
2014-01-25 16:12:20 +00:00
window . openDialog ( "chrome://browser/content/" , "_blank" ,
"chrome,all,dialog=no" , BROWSER _NEW _TAB _URL ) ;
2003-12-02 22:27:25 +00:00
}
2002-09-20 03:52:36 +00:00
}
2005-06-09 00:18:02 +00:00
# endif
2002-08-04 02:53:09 +00:00
}
function BrowserOpenTab ( )
{
2012-01-25 22:43:27 +00:00
openUILinkIn ( BROWSER _NEW _TAB _URL , "tab" ) ;
2002-08-04 02:53:09 +00:00
}
/ * C a l l e d f r o m t h e o p e n L o c a t i o n d i a l o g . T h i s a l l o w s t h a t d i a l o g t o i n s t r u c t
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 . * /
2005-07-15 16:46:37 +00:00
function delayedOpenWindow ( chrome , flags , href , postData )
2002-08-04 02:53:09 +00:00
{
2004-07-07 03:04:09 +00:00
// The other way to use setTimeout,
// setTimeout(openDialog, 10, chrome, "_blank", flags, url),
// doesn't work here. The extra "magic" extra argument setTimeout adds to
2012-06-15 19:09:48 +00:00
// the callback function would confuse gBrowserInit.onLoad() by making
2004-07-07 03:04:09 +00:00
// window.arguments[1] be an integer instead of null.
2005-07-15 16:46:37 +00:00
setTimeout ( function ( ) { openDialog ( chrome , "_blank" , flags , href , null , null , postData ) ; } , 10 ) ;
2002-08-04 02:53:09 +00:00
}
/ * R e q u i r e d b e c a u s e t h e t a b n e e d s t i m e t o s e t u p i t s c o n t e n t v i e w e r s a n d g e t t h e l o a d o f
the URI kicked off before becoming the active content area . * /
2006-04-03 23:17:51 +00:00
function delayedOpenTab ( aUrl , aReferrer , aCharset , aPostData , aAllowThirdPartyFixup )
2002-08-04 02:53:09 +00:00
{
2009-09-17 13:03:15 +00:00
gBrowser . loadOneTab ( aUrl , {
referrerURI : aReferrer ,
charset : aCharset ,
postData : aPostData ,
inBackground : false ,
allowThirdPartyFixup : aAllowThirdPartyFixup } ) ;
2002-08-04 02:53:09 +00:00
}
2009-08-02 17:53:08 +00:00
var gLastOpenDirectory = {
_lastDir : null ,
get path ( ) {
if ( ! this . _lastDir || ! this . _lastDir . exists ( ) ) {
try {
this . _lastDir = gPrefService . getComplexValue ( "browser.open.lastDir" ,
Ci . nsILocalFile ) ;
if ( ! this . _lastDir . exists ( ) )
this . _lastDir = null ;
}
catch ( e ) { }
}
return this . _lastDir ;
} ,
set path ( val ) {
2011-08-30 21:45:31 +00:00
try {
if ( ! val || ! val . isDirectory ( ) )
return ;
} catch ( e ) {
2009-08-02 17:53:08 +00:00
return ;
2011-08-30 21:45:31 +00:00
}
2009-08-02 17:53:08 +00:00
this . _lastDir = val . clone ( ) ;
// Don't save the last open directory pref inside the Private Browsing mode
2012-10-07 21:47:10 +00:00
if ( ! PrivateBrowsingUtils . isWindowPrivate ( window ) )
2009-08-02 17:53:08 +00:00
gPrefService . setComplexValue ( "browser.open.lastDir" , Ci . nsILocalFile ,
this . _lastDir ) ;
} ,
reset : function ( ) {
this . _lastDir = null ;
}
} ;
2002-08-04 02:53:09 +00:00
function BrowserOpenFileWindow ( )
{
// Get filepicker component.
try {
2012-09-19 23:21:38 +00:00
const nsIFilePicker = Ci . nsIFilePicker ;
let fp = Cc [ "@mozilla.org/filepicker;1" ] . createInstance ( nsIFilePicker ) ;
let fpCallback = function fpCallback _done ( aResult ) {
if ( aResult == nsIFilePicker . returnOK ) {
try {
if ( fp . file ) {
gLastOpenDirectory . path =
fp . file . parent . QueryInterface ( Ci . nsILocalFile ) ;
}
} catch ( ex ) {
}
openUILinkIn ( fp . fileURL . spec , "current" ) ;
2011-08-30 21:45:31 +00:00
}
2012-09-19 23:21:38 +00:00
} ;
fp . init ( window , gNavigatorBundle . getString ( "openFile" ) ,
nsIFilePicker . modeOpen ) ;
fp . appendFilters ( nsIFilePicker . filterAll | nsIFilePicker . filterText |
nsIFilePicker . filterImages | nsIFilePicker . filterXML |
nsIFilePicker . filterHTML ) ;
fp . displayDirectory = gLastOpenDirectory . path ;
fp . open ( fpCallback ) ;
2002-08-04 02:53:09 +00:00
} catch ( ex ) {
}
}
2008-09-17 15:07:26 +00:00
function BrowserCloseTabOrWindow ( ) {
2005-04-19 15:32:38 +00:00
# ifdef XP _MACOSX
// If we're not a browser window, just close the window
if ( window . location . href != getBrowserURL ( ) ) {
closeWindow ( true ) ;
return ;
}
# endif
2008-09-17 15:07:26 +00:00
// If the current tab is the last one, this will close the window.
2010-08-06 20:15:18 +00:00
gBrowser . removeCurrentTab ( { animate : true } ) ;
2002-08-04 02:53:09 +00:00
}
2004-10-11 13:32:32 +00:00
function BrowserTryToCloseWindow ( )
{
2009-10-06 12:33:55 +00:00
if ( WindowIsClosing ( ) )
2007-06-15 18:01:25 +00:00
window . close ( ) ; // WindowIsClosing does all the necessary checks
2002-08-04 02:53:09 +00:00
}
2011-07-28 15:37:56 +00:00
function loadURI ( uri , referrer , postData , allowThirdPartyFixup ) {
if ( postData === undefined )
postData = null ;
var flags = nsIWebNavigation . LOAD _FLAGS _NONE ;
2014-01-12 20:02:27 +00:00
if ( allowThirdPartyFixup ) {
2011-07-28 15:37:56 +00:00
flags |= nsIWebNavigation . LOAD _FLAGS _ALLOW _THIRD _PARTY _FIXUP ;
2014-01-12 20:02:27 +00:00
flags |= nsIWebNavigation . LOAD _FLAGS _FIXUP _SCHEME _TYPOS ;
}
2011-07-28 15:37:56 +00:00
2002-08-04 02:53:09 +00:00
try {
2008-07-30 20:28:29 +00:00
gBrowser . loadURIWithFlags ( uri , flags , referrer , null , postData ) ;
2011-07-28 15:37:56 +00:00
} catch ( e ) { }
2002-08-04 02:53:09 +00:00
}
2013-06-25 01:26:22 +00:00
function getShortcutOrURIAndPostData ( aURL ) {
return Task . spawn ( function ( ) {
let mayInheritPrincipal = false ;
let postData = null ;
let shortcutURL = null ;
let keyword = aURL ;
let param = "" ;
2008-02-20 09:43:31 +00:00
2013-06-25 01:26:22 +00:00
let offset = aURL . indexOf ( " " ) ;
if ( offset > 0 ) {
keyword = aURL . substr ( 0 , offset ) ;
param = aURL . substr ( offset + 1 ) ;
}
2008-02-20 09:43:31 +00:00
2013-06-25 01:26:22 +00:00
let engine = Services . search . getEngineByAlias ( keyword ) ;
if ( engine ) {
let submission = engine . getSubmission ( param ) ;
postData = submission . postData ;
throw new Task . Result ( { postData : submission . postData ,
url : submission . uri . spec ,
mayInheritPrincipal : mayInheritPrincipal } ) ;
}
[ shortcutURL , postData ] =
PlacesUtils . getURLAndPostDataForKeyword ( keyword ) ;
if ( ! shortcutURL )
throw new Task . Result ( { postData : postData , url : aURL ,
mayInheritPrincipal : mayInheritPrincipal } ) ;
let escapedPostData = "" ;
if ( postData )
escapedPostData = unescape ( postData ) ;
if ( /%s/i . test ( shortcutURL ) || /%s/i . test ( escapedPostData ) ) {
let charset = "" ;
const re = /^(.*)\&mozcharset=([a-zA-Z][_\-a-zA-Z0-9]+)\s*$/ ;
let matches = shortcutURL . match ( re ) ;
if ( matches )
[ , shortcutURL , charset ] = matches ;
else {
// Try to get the saved character-set.
try {
// makeURI throws if URI is invalid.
// Will return an empty string if character-set is not found.
charset = yield PlacesUtils . getCharsetForURI ( makeURI ( shortcutURL ) ) ;
} catch ( e ) { }
}
2007-06-27 19:25:14 +00:00
2013-06-25 01:26:22 +00:00
// encodeURIComponent produces UTF-8, and cannot be used for other charsets.
// escape() works in those cases, but it doesn't uri-encode +, @, and /.
// Therefore we need to manually replace these ASCII characters by their
// encodeURIComponent result, to match the behavior of nsEscape() with
// url_XPAlphas
let encodedParam = "" ;
if ( charset && charset != "UTF-8" )
encodedParam = escape ( convertFromUnicode ( charset , param ) ) .
replace ( /[+@\/]+/g , encodeURIComponent ) ;
else // Default charset is UTF-8
encodedParam = encodeURIComponent ( param ) ;
2007-06-27 19:25:14 +00:00
2013-06-25 01:26:22 +00:00
shortcutURL = shortcutURL . replace ( /%s/g , encodedParam ) . replace ( /%S/g , param ) ;
2007-06-27 19:25:14 +00:00
2013-06-25 01:26:22 +00:00
if ( /%s/i . test ( escapedPostData ) ) // POST keyword
postData = getPostDataStream ( escapedPostData , param , encodedParam ,
"application/x-www-form-urlencoded" ) ;
}
else if ( param ) {
// This keyword doesn't take a parameter, but one was provided. Just return
// the original URL.
postData = null ;
2004-04-20 09:45:12 +00:00
2013-06-25 01:26:22 +00:00
throw new Task . Result ( { postData : postData , url : aURL ,
mayInheritPrincipal : mayInheritPrincipal } ) ;
}
2008-03-05 22:11:45 +00:00
2013-06-25 01:26:22 +00:00
// This URL came from a bookmark, so it's safe to let it inherit the current
// document's principal.
mayInheritPrincipal = true ;
2011-05-31 21:33:46 +00:00
2013-06-25 01:26:22 +00:00
throw new Task . Result ( { postData : postData , url : shortcutURL ,
mayInheritPrincipal : mayInheritPrincipal } ) ;
} ) ;
2007-06-27 19:25:14 +00:00
}
2010-03-24 21:22:04 +00:00
2007-06-27 19:25:14 +00:00
function getPostDataStream ( aStringData , aKeyword , aEncKeyword , aType ) {
var dataStream = Cc [ "@mozilla.org/io/string-input-stream;1" ] .
createInstance ( Ci . nsIStringInputStream ) ;
2005-08-09 04:53:19 +00:00
aStringData = aStringData . replace ( /%s/g , aEncKeyword ) . replace ( /%S/g , aKeyword ) ;
2006-01-02 03:34:17 +00:00
dataStream . data = aStringData ;
2010-03-24 21:22:04 +00:00
2007-06-27 19:25:14 +00:00
var mimeStream = Cc [ "@mozilla.org/network/mime-input-stream;1" ] .
createInstance ( Ci . nsIMIMEInputStream ) ;
2004-04-20 09:45:12 +00:00
mimeStream . addHeader ( "Content-Type" , aType ) ;
mimeStream . addContentLength = true ;
mimeStream . setData ( dataStream ) ;
2007-06-27 19:25:14 +00:00
return mimeStream . QueryInterface ( Ci . nsIInputStream ) ;
2002-08-04 02:53:09 +00:00
}
2012-04-17 02:14:01 +00:00
function getLoadContext ( ) {
return window . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsILoadContext ) ;
}
2002-08-04 02:53:09 +00:00
function readFromClipboard ( )
{
var url ;
try {
2009-01-11 18:22:37 +00:00
// Create transferable that will transfer the text.
2002-08-04 02:53:09 +00:00
var trans = Components . classes [ "@mozilla.org/widget/transferable;1" ]
. createInstance ( Components . interfaces . nsITransferable ) ;
2012-04-17 02:14:01 +00:00
trans . init ( getLoadContext ( ) ) ;
2002-08-04 02:53:09 +00:00
trans . addDataFlavor ( "text/unicode" ) ;
2004-06-23 22:54:12 +00:00
// If available, use selection clipboard, otherwise global one
2012-12-20 20:34:06 +00:00
if ( Services . clipboard . supportsSelectionClipboard ( ) )
Services . clipboard . getData ( trans , Services . clipboard . kSelectionClipboard ) ;
2004-06-23 22:54:12 +00:00
else
2012-12-20 20:34:06 +00:00
Services . clipboard . getData ( trans , Services . clipboard . kGlobalClipboard ) ;
2002-08-04 02:53:09 +00:00
var data = { } ;
var dataLen = { } ;
trans . getTransferData ( "text/unicode" , data , dataLen ) ;
if ( data ) {
2002-11-04 23:12:08 +00:00
data = data . value . QueryInterface ( Components . interfaces . nsISupportsString ) ;
2002-08-04 02:53:09 +00:00
url = data . data . substring ( 0 , dataLen . value / 2 ) ;
}
} catch ( ex ) {
}
return url ;
}
function BrowserViewSourceOfDocument ( aDocument )
{
var pageCookie ;
var webNav ;
// Get the document charset
2005-11-22 05:36:48 +00:00
var docCharset = "charset=" + aDocument . characterSet ;
2002-08-04 02:53:09 +00:00
// Get the nsIWebNavigation associated with the document
try {
var win ;
var ifRequestor ;
// Get the DOMWindow for the requested document. If the DOMWindow
2005-01-28 16:06:56 +00:00
// cannot be found, then just use the content window...
2002-08-04 02:53:09 +00:00
//
// XXX: This is a bit of a hack...
win = aDocument . defaultView ;
if ( win == window ) {
2005-01-28 16:06:56 +00:00
win = content ;
2002-08-04 02:53:09 +00:00
}
ifRequestor = win . QueryInterface ( Components . interfaces . nsIInterfaceRequestor ) ;
2002-11-16 17:14:12 +00:00
webNav = ifRequestor . getInterface ( nsIWebNavigation ) ;
2002-08-04 02:53:09 +00:00
} catch ( err ) {
// If nsIWebNavigation cannot be found, just get the one for the whole
// window...
2012-06-15 19:09:48 +00:00
webNav = gBrowser . webNavigation ;
2002-08-04 02:53:09 +00:00
}
//
// 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...
}
2008-09-08 12:06:06 +00:00
top . gViewSourceUtils . viewSource ( webNav . currentURI . spec , pageCookie , aDocument ) ;
2002-08-04 02:53:09 +00:00
}
2005-09-21 01:12:29 +00:00
// doc - document to use for source, or null for this window's document
// initialTab - name of the initial tab to display, or null for the first tab
2009-10-29 07:42:45 +00:00
// imageElement - image to load in the Media Tab of the Page Info window; can be null/omitted
function BrowserPageInfo ( doc , initialTab , imageElement ) {
var args = { doc : doc , initialTab : initialTab , imageElement : imageElement } ;
2012-12-20 20:34:06 +00:00
var windows = Services . wm . getEnumerator ( "Browser:page-info" ) ;
2009-11-06 07:04:38 +00:00
var documentURL = doc ? doc . location : window . content . document . location ;
// Check for windows matching the url
while ( windows . hasMoreElements ( ) ) {
var currentWindow = windows . getNext ( ) ;
2013-09-13 21:29:51 +00:00
if ( currentWindow . closed ) {
continue ;
}
2009-11-06 07:04:38 +00:00
if ( currentWindow . document . documentElement . getAttribute ( "relatedUrl" ) == documentURL ) {
currentWindow . focus ( ) ;
currentWindow . resetPageInfo ( args ) ;
return currentWindow ;
}
}
// We didn't find a matching window, so open a new one.
return openDialog ( "chrome://browser/content/pageinfo/pageInfo.xul" , "" ,
"chrome,toolbar,dialog=no,resizable" , args ) ;
2002-08-04 02:53:09 +00:00
}
2010-06-11 13:26:01 +00:00
function URLBarSetURI ( aURI ) {
2008-07-30 20:28:29 +00:00
var value = gBrowser . userTypedValue ;
2008-09-17 14:36:39 +00:00
var valid = false ;
2008-01-12 10:19:31 +00:00
2009-05-26 04:17:22 +00:00
if ( value == null ) {
2012-06-15 19:09:48 +00:00
let uri = aURI || gBrowser . currentURI ;
2012-12-12 09:09:49 +00:00
// Strip off "wyciwyg://" and passwords for the location bar
try {
uri = Services . uriFixup . createExposableURI ( uri ) ;
} catch ( e ) { }
2008-01-12 10:19:31 +00:00
2009-03-03 08:20:14 +00:00
// Replace initial page URIs with an empty string
2008-09-17 14:36:39 +00:00
// only if there's no opener (bug 370555).
2013-04-23 02:47:52 +00:00
// Bug 863515 - Make content.opener checks work in electrolysis.
2009-03-03 08:20:14 +00:00
if ( gInitialPages . indexOf ( uri . spec ) != - 1 )
2013-04-23 02:47:52 +00:00
value = ! gMultiProcessBrowser && content . opener ? uri . spec : "" ;
2008-09-17 14:36:39 +00:00
else
value = losslessDecodeURI ( uri ) ;
2012-01-25 22:43:27 +00:00
valid = ! isBlankPageURL ( uri . spec ) ;
2008-01-12 10:19:31 +00:00
}
gURLBar . value = value ;
2011-09-20 03:35:33 +00:00
gURLBar . valueIsTyped = ! valid ;
2008-09-17 14:36:39 +00:00
SetPageProxyState ( valid ? "valid" : "invalid" ) ;
2008-01-12 10:19:31 +00:00
}
2008-03-28 08:45:18 +00:00
function losslessDecodeURI ( aURI ) {
var value = aURI . spec ;
// Try to decode as UTF-8 if there's no encoding sequence that we would break.
if ( ! /%25(?:3B|2F|3F|3A|40|26|3D|2B|24|2C|23)/i . test ( value ) )
try {
value = decodeURI ( value )
// 1. decodeURI decodes %25 to %, which creates unintended
// encoding sequences. Re-encode it, unless it's part of
// a sequence that survived decodeURI, i.e. one for:
// ';', '/', '?', ':', '@', '&', '=', '+', '$', ',', '#'
// (RFC 3987 section 3.2)
// 2. Re-encode whitespace so that it doesn't get eaten away
// by the location bar (bug 410726).
. replace ( /%(?!3B|2F|3F|3A|40|26|3D|2B|24|2C|23)|[\r\n\t]/ig ,
encodeURIComponent ) ;
} catch ( e ) { }
2013-09-04 09:49:47 +00:00
// Encode invisible characters (C0/C1 control characters, U+007F [DEL],
// U+00A0 [no-break space], line and paragraph separator,
// object replacement character) (bug 452979, bug 909264)
value = value . replace ( /[\u0000-\u001f\u007f-\u00a0\u2028\u2029\ufffc]/g ,
2008-11-12 23:20:04 +00:00
encodeURIComponent ) ;
2010-08-17 12:35:24 +00:00
// Encode default ignorable characters (bug 546013)
// except ZWNJ (U+200C) and ZWJ (U+200D) (bug 582186).
2010-04-28 21:55:44 +00:00
// This includes all bidirectional formatting characters.
2008-03-28 08:45:18 +00:00
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
2013-10-02 13:07:02 +00:00
value = value . replace ( /[\u00ad\u034f\u061c\u115f-\u1160\u17b4-\u17b5\u180b-\u180d\u200b\u200e-\u200f\u202a-\u202e\u2060-\u206f\u3164\ufe00-\ufe0f\ufeff\uffa0\ufff0-\ufff8]|\ud834[\udd73-\udd7a]|[\udb40-\udb43][\udc00-\udfff]/g ,
2008-03-28 08:45:18 +00:00
encodeURIComponent ) ;
return value ;
}
2007-11-15 03:38:16 +00:00
function UpdateUrlbarSearchSplitterState ( )
{
var splitter = document . getElementById ( "urlbar-search-splitter" ) ;
var urlbar = document . getElementById ( "urlbar-container" ) ;
var searchbar = document . getElementById ( "search-container" ) ;
2007-11-19 15:25:39 +00:00
2014-02-03 10:48:21 +00:00
if ( document . documentElement . getAttribute ( "customizing" ) == "true" ) {
if ( splitter ) {
splitter . remove ( ) ;
}
return ;
}
2013-09-10 11:41:24 +00:00
// If the splitter is already in the right place, we don't need to do anything:
if ( splitter &&
( ( splitter . nextSibling == searchbar && splitter . previousSibling == urlbar ) ||
( splitter . nextSibling == urlbar && splitter . previousSibling == searchbar ) ) ) {
return ;
}
2007-11-19 15:25:39 +00:00
2007-11-15 03:38:16 +00:00
var ibefore = null ;
2007-11-19 15:25:39 +00:00
if ( urlbar && searchbar ) {
2013-07-18 16:46:28 +00:00
if ( urlbar . nextSibling == searchbar )
2007-11-19 15:25:39 +00:00
ibefore = searchbar ;
else if ( searchbar . nextSibling == urlbar )
ibefore = urlbar ;
}
2007-11-15 03:38:16 +00:00
if ( ibefore ) {
if ( ! splitter ) {
splitter = document . createElement ( "splitter" ) ;
splitter . id = "urlbar-search-splitter" ;
splitter . setAttribute ( "resizebefore" , "flex" ) ;
splitter . setAttribute ( "resizeafter" , "flex" ) ;
2012-03-25 16:10:36 +00:00
splitter . setAttribute ( "skipintoolbarset" , "true" ) ;
2013-09-25 20:42:23 +00:00
splitter . setAttribute ( "overflows" , "false" ) ;
2008-01-10 09:16:24 +00:00
splitter . className = "chromeclass-toolbar-additional" ;
2007-11-15 03:38:16 +00:00
}
urlbar . parentNode . insertBefore ( splitter , ibefore ) ;
2007-11-19 15:25:39 +00:00
} else if ( splitter )
splitter . parentNode . removeChild ( splitter ) ;
2007-11-15 03:38:16 +00:00
}
2002-08-04 02:53:09 +00:00
function UpdatePageProxyState ( )
{
2002-09-29 01:23:02 +00:00
if ( gURLBar && gURLBar . value != gLastValidURLStr )
2005-04-20 22:01:34 +00:00
SetPageProxyState ( "invalid" ) ;
2002-08-04 02:53:09 +00:00
}
2005-04-20 22:01:34 +00:00
function SetPageProxyState ( aState )
2002-08-04 02:53:09 +00:00
{
2013-05-10 15:19:48 +00:00
BookmarkingUI . onPageProxyStateChanged ( aState ) ;
2013-04-23 14:06:17 +00:00
2002-08-07 07:48:17 +00:00
if ( ! gURLBar )
return ;
2002-09-29 01:23:02 +00:00
2010-09-08 11:39:35 +00:00
if ( ! gProxyFavIcon )
gProxyFavIcon = document . getElementById ( "page-proxy-favicon" ) ;
2007-12-11 19:51:15 +00:00
gURLBar . setAttribute ( "pageproxystate" , aState ) ;
2010-09-08 11:39:35 +00:00
gProxyFavIcon . setAttribute ( "pageproxystate" , aState ) ;
2002-08-04 02:53:09 +00:00
2004-07-29 23:49:31 +00:00
// the page proxy state is set to valid via OnLocationChange, which
2005-06-14 08:04:09 +00:00
// gets called when we switch tabs.
2002-08-04 02:53:09 +00:00
if ( aState == "valid" ) {
gLastValidURLStr = gURLBar . value ;
gURLBar . addEventListener ( "input" , UpdatePageProxyState , false ) ;
} else if ( aState == "invalid" ) {
gURLBar . removeEventListener ( "input" , UpdatePageProxyState , false ) ;
2004-11-30 08:23:02 +00:00
}
}
2010-09-08 11:39:35 +00:00
function PageProxyClickHandler ( aEvent )
{
if ( aEvent . button == 1 && gPrefService . getBoolPref ( "middlemouse.paste" ) )
middleMousePaste ( aEvent ) ;
}
2007-11-03 18:49:47 +00:00
/ * *
* Handle command events bubbling up from error page content
2013-08-22 23:52:18 +00:00
* or from about : newtab
2007-11-03 18:49:47 +00:00
* /
2012-07-31 16:54:51 +00:00
let BrowserOnClick = {
handleEvent : function BrowserOnClick _handleEvent ( aEvent ) {
if ( ! aEvent . isTrusted || // Don't trust synthetic events
2013-08-22 23:52:18 +00:00
aEvent . button == 2 ) {
2007-11-03 18:49:47 +00:00
return ;
2012-07-31 16:54:51 +00:00
}
2008-02-17 05:26:52 +00:00
2012-07-31 16:54:51 +00:00
let originalTarget = aEvent . originalTarget ;
let ownerDoc = originalTarget . ownerDocument ;
2008-03-07 19:51:25 +00:00
2007-11-03 18:49:47 +00:00
// If the event came from an ssl error page, it is probably either the "Add
2007-11-05 22:59:09 +00:00
// Exception…" or "Get me out of here!" button
2012-09-23 19:09:29 +00:00
if ( ownerDoc . documentURI . startsWith ( "about:certerror" ) ) {
2012-07-31 16:54:51 +00:00
this . onAboutCertError ( originalTarget , ownerDoc ) ;
}
2012-09-23 19:09:29 +00:00
else if ( ownerDoc . documentURI . startsWith ( "about:blocked" ) ) {
2012-07-31 16:54:51 +00:00
this . onAboutBlocked ( originalTarget , ownerDoc ) ;
}
2012-09-23 19:09:29 +00:00
else if ( ownerDoc . documentURI . startsWith ( "about:neterror" ) ) {
2012-08-10 03:43:54 +00:00
this . onAboutNetError ( originalTarget , ownerDoc ) ;
}
2013-08-22 23:52:18 +00:00
else if ( gMultiProcessBrowser &&
ownerDoc . documentURI . toLowerCase ( ) == "about:newtab" ) {
this . onE10sAboutNewTab ( aEvent , ownerDoc ) ;
}
2013-09-03 22:11:22 +00:00
else if ( ownerDoc . documentURI . startsWith ( "about:tabcrashed" ) ) {
this . onAboutTabCrashed ( aEvent , ownerDoc ) ;
}
2012-07-31 16:54:51 +00:00
} ,
onAboutCertError : function BrowserOnClick _onAboutCertError ( aTargetElm , aOwnerDoc ) {
let elmId = aTargetElm . getAttribute ( "id" ) ;
2012-12-20 20:34:06 +00:00
let secHistogram = Services . telemetry . getHistogramById ( "SECURITY_UI" ) ;
2013-06-04 22:02:24 +00:00
let isTopFrame = ( aOwnerDoc . defaultView . parent === aOwnerDoc . defaultView ) ;
2012-07-31 16:54:51 +00:00
switch ( elmId ) {
case "exceptionDialogButton" :
2013-06-04 22:02:24 +00:00
if ( isTopFrame ) {
secHistogram . add ( Ci . nsISecurityUITelemetry . WARNING _BAD _CERT _TOP _CLICK _ADD _EXCEPTION ) ;
}
2012-10-13 03:38:19 +00:00
let params = { exceptionAdded : false } ;
2010-03-24 21:22:04 +00:00
2007-11-23 21:59:10 +00:00
try {
2012-07-31 16:54:51 +00:00
switch ( Services . prefs . getIntPref ( "browser.ssl_override_behavior" ) ) {
2007-11-23 21:59:10 +00:00
case 2 : // Pre-fetch & pre-populate
params . prefetchCert = true ;
case 1 : // Pre-populate
2012-07-31 16:54:51 +00:00
params . location = aOwnerDoc . location . href ;
2007-11-23 21:59:10 +00:00
}
} catch ( e ) {
Components . utils . reportError ( "Couldn't get ssl_override pref: " + e ) ;
}
2010-03-24 21:22:04 +00:00
2007-11-03 18:49:47 +00:00
window . openDialog ( 'chrome://pippki/content/exceptionDialog.xul' ,
'' , 'chrome,centerscreen,modal' , params ) ;
2010-03-24 21:22:04 +00:00
2007-11-03 18:49:47 +00:00
// If the user added the exception cert, attempt to reload the page
2012-07-31 16:54:51 +00:00
if ( params . exceptionAdded ) {
aOwnerDoc . location . reload ( ) ;
}
break ;
case "getMeOutOfHereButton" :
2013-06-04 22:02:24 +00:00
if ( isTopFrame ) {
secHistogram . add ( Ci . nsISecurityUITelemetry . WARNING _BAD _CERT _TOP _GET _ME _OUT _OF _HERE ) ;
}
2008-03-07 19:51:25 +00:00
getMeOutOfHere ( ) ;
2012-07-31 16:54:51 +00:00
break ;
2012-08-03 01:51:17 +00:00
case "technicalContent" :
2013-06-04 22:02:24 +00:00
if ( isTopFrame ) {
secHistogram . add ( Ci . nsISecurityUITelemetry . WARNING _BAD _CERT _TOP _TECHNICAL _DETAILS ) ;
}
2012-08-03 01:51:17 +00:00
break ;
case "expertContent" :
2013-06-04 22:02:24 +00:00
if ( isTopFrame ) {
secHistogram . add ( Ci . nsISecurityUITelemetry . WARNING _BAD _CERT _TOP _UNDERSTAND _RISKS ) ;
}
2012-08-03 01:51:17 +00:00
break ;
2008-03-07 19:51:25 +00:00
}
2012-07-31 16:54:51 +00:00
} ,
2010-03-24 21:22:04 +00:00
2012-07-31 16:54:51 +00:00
onAboutBlocked : function BrowserOnClick _onAboutBlocked ( aTargetElm , aOwnerDoc ) {
let elmId = aTargetElm . getAttribute ( "id" ) ;
2012-12-20 20:34:06 +00:00
let secHistogram = Services . telemetry . getHistogramById ( "SECURITY_UI" ) ;
2012-07-31 16:54:51 +00:00
// The event came from a button on a malware/phishing block page
// First check whether it's malware or phishing, so that we can
// use the right strings/links
let isMalware = /e=malwareBlocked/ . test ( aOwnerDoc . documentURI ) ;
2012-08-03 01:51:17 +00:00
let bucketName = isMalware ? "WARNING_MALWARE_PAGE_" : "WARNING_PHISHING_PAGE_" ;
let nsISecTel = Ci . nsISecurityUITelemetry ;
2013-03-28 17:53:01 +00:00
let isIframe = ( aOwnerDoc . defaultView . parent === aOwnerDoc . defaultView ) ;
bucketName += isIframe ? "TOP_" : "FRAME_" ;
2012-07-31 16:54:51 +00:00
switch ( elmId ) {
case "getMeOutButton" :
2012-08-03 01:51:17 +00:00
secHistogram . add ( nsISecTel [ bucketName + "GET_ME_OUT_OF_HERE" ] ) ;
2008-03-07 19:51:25 +00:00
getMeOutOfHere ( ) ;
2012-07-31 16:54:51 +00:00
break ;
case "reportButton" :
2008-03-07 19:51:25 +00:00
// This is the "Why is this site blocked" button. For malware,
// we can fetch a site-specific report, for phishing, we redirect
// to the generic page describing phishing protection.
2009-10-02 16:52:53 +00:00
2013-04-09 19:44:01 +00:00
// We log even if malware/phishing info URL couldn't be found:
2012-08-03 01:51:17 +00:00
// the measurement is for how many users clicked the WHY BLOCKED button
secHistogram . add ( nsISecTel [ bucketName + "WHY_BLOCKED" ] ) ;
2008-10-27 19:36:46 +00:00
if ( isMalware ) {
2008-03-07 19:51:25 +00:00
// Get the stop badware "why is this blocked" report url,
// append the current url, and go there.
try {
2009-10-02 16:52:53 +00:00
let reportURL = formatURL ( "browser.safebrowsing.malware.reportURL" , true ) ;
2012-07-31 16:54:51 +00:00
reportURL += aOwnerDoc . location . href ;
2008-03-07 19:51:25 +00:00
content . location = reportURL ;
} catch ( e ) {
Components . utils . reportError ( "Couldn't get malware report URL: " + e ) ;
}
}
2008-10-27 19:36:46 +00:00
else { // It's a phishing site, not malware
2013-10-08 21:00:48 +00:00
openHelpLink ( "phishing-malware" , false , "current" ) ;
2007-11-03 18:49:47 +00:00
}
2012-07-31 16:54:51 +00:00
break ;
case "ignoreWarningButton" :
2012-08-03 01:51:17 +00:00
secHistogram . add ( nsISecTel [ bucketName + "IGNORE_WARNING" ] ) ;
2012-07-31 16:54:51 +00:00
this . ignoreWarningButton ( isMalware ) ;
break ;
}
} ,
2013-08-22 23:52:18 +00:00
/ * *
* This functions prevents navigation from happening directly through the < a >
* link in about : newtab ( which is loaded in the parent and therefore would load
* the next page also in the parent ) and instructs the browser to open the url
* in the current tab which will make it update the remoteness of the tab .
* /
onE10sAboutNewTab : function ( aEvent , aOwnerDoc ) {
let isTopFrame = ( aOwnerDoc . defaultView . parent === aOwnerDoc . defaultView ) ;
2014-02-14 00:04:01 +00:00
if ( ! isTopFrame || aEvent . button != 0 ) {
2013-08-22 23:52:18 +00:00
return ;
}
let anchorTarget = aEvent . originalTarget . parentNode ;
if ( anchorTarget instanceof HTMLAnchorElement &&
anchorTarget . classList . contains ( "newtab-link" ) ) {
aEvent . preventDefault ( ) ;
openUILinkIn ( anchorTarget . href , "current" ) ;
}
} ,
2013-09-03 22:11:22 +00:00
/ * *
* The about : tabcrashed can ' t do window . reload ( ) because that
* would reload the page but not use a remote browser .
* /
onAboutTabCrashed : function ( aEvent , aOwnerDoc ) {
let isTopFrame = ( aOwnerDoc . defaultView . parent === aOwnerDoc . defaultView ) ;
if ( ! isTopFrame ) {
return ;
}
let button = aEvent . originalTarget ;
if ( button . id == "tryAgain" ) {
2013-09-12 19:24:10 +00:00
# ifdef MOZ _CRASHREPORTER
if ( aOwnerDoc . getElementById ( "checkSendReport" ) . checked ) {
let browser = gBrowser . getBrowserForDocument ( aOwnerDoc ) ;
TabCrashReporter . submitCrashReport ( browser ) ;
}
# endif
2013-09-03 22:11:22 +00:00
openUILinkIn ( button . getAttribute ( "url" ) , "current" ) ;
}
} ,
2012-07-31 16:54:51 +00:00
ignoreWarningButton : function BrowserOnClick _ignoreWarningButton ( aIsMalware ) {
// Allow users to override and continue through to the site,
// but add a notify bar as a reminder, so that they don't lose
// track after, e.g., tab switching.
gBrowser . loadURIWithFlags ( content . location . href ,
nsIWebNavigation . LOAD _FLAGS _BYPASS _CLASSIFIER ,
null , null , null ) ;
Services . perms . add ( makeURI ( content . location . href ) , "safe-browsing" ,
Ci . nsIPermissionManager . ALLOW _ACTION ,
Ci . nsIPermissionManager . EXPIRE _SESSION ) ;
let buttons = [ {
label : gNavigatorBundle . getString ( "safebrowsing.getMeOutOfHereButton.label" ) ,
accessKey : gNavigatorBundle . getString ( "safebrowsing.getMeOutOfHereButton.accessKey" ) ,
callback : function ( ) { getMeOutOfHere ( ) ; }
} ] ;
let title ;
if ( aIsMalware ) {
title = gNavigatorBundle . getString ( "safebrowsing.reportedAttackSite" ) ;
buttons [ 1 ] = {
label : gNavigatorBundle . getString ( "safebrowsing.notAnAttackButton.label" ) ,
accessKey : gNavigatorBundle . getString ( "safebrowsing.notAnAttackButton.accessKey" ) ,
callback : function ( ) {
openUILinkIn ( gSafeBrowsing . getReportURL ( 'MalwareError' ) , 'tab' ) ;
2008-10-27 19:36:46 +00:00
}
2012-07-31 16:54:51 +00:00
} ;
} else {
title = gNavigatorBundle . getString ( "safebrowsing.reportedWebForgery" ) ;
buttons [ 1 ] = {
label : gNavigatorBundle . getString ( "safebrowsing.notAForgeryButton.label" ) ,
accessKey : gNavigatorBundle . getString ( "safebrowsing.notAForgeryButton.accessKey" ) ,
callback : function ( ) {
openUILinkIn ( gSafeBrowsing . getReportURL ( 'Error' ) , 'tab' ) ;
}
} ;
}
2010-03-24 21:22:04 +00:00
2012-07-31 16:54:51 +00:00
let notificationBox = gBrowser . getNotificationBox ( ) ;
let value = "blocked-badware-page" ;
let previousNotification = notificationBox . getNotificationWithValue ( value ) ;
if ( previousNotification ) {
notificationBox . removeNotification ( previousNotification ) ;
2007-11-03 18:49:47 +00:00
}
2012-07-31 16:54:51 +00:00
let notification = notificationBox . appendNotification (
title ,
value ,
"chrome://global/skin/icons/blacklist_favicon.png" ,
notificationBox . PRIORITY _CRITICAL _HIGH ,
buttons
) ;
// Persist the notification until the user removes so it
// doesn't get removed on redirects.
notification . persistence = - 1 ;
} ,
2012-08-10 03:43:54 +00:00
onAboutNetError : function BrowserOnClick _onAboutNetError ( aTargetElm , aOwnerDoc ) {
let elmId = aTargetElm . getAttribute ( "id" ) ;
if ( elmId != "errorTryAgain" || ! /e=netOffline/ . test ( aOwnerDoc . documentURI ) )
return ;
Services . io . offline = false ;
} ,
2012-07-31 16:54:51 +00:00
} ;
2008-03-07 19:51:25 +00:00
/ * *
* Re - direct the browser to a known - safe page . This function is
* used when , for example , the user browses to a known malware page
* and is presented with about : blocked . The "Get me out of here!"
* button should take the user to the default start page so that even
* when their own homepage is infected , we can get them somewhere safe .
* /
function getMeOutOfHere ( ) {
// Get the start page from the *default* pref branch, not the user's
2012-12-20 20:34:06 +00:00
var prefs = Services . prefs . getDefaultBranch ( null ) ;
2012-01-25 22:43:27 +00:00
var url = BROWSER _NEW _TAB _URL ;
2008-03-07 19:51:25 +00:00
try {
2009-07-29 08:49:59 +00:00
url = prefs . getComplexValue ( "browser.startup.homepage" ,
Ci . nsIPrefLocalizedString ) . data ;
2008-03-07 19:51:25 +00:00
// If url is a pipe-delimited set of pages, just take the first one.
2012-09-08 20:58:23 +00:00
if ( url . contains ( "|" ) )
2008-03-07 19:51:25 +00:00
url = url . split ( "|" ) [ 0 ] ;
} catch ( e ) {
Components . utils . reportError ( "Couldn't get homepage pref: " + e ) ;
2007-11-03 18:49:47 +00:00
}
2008-03-07 19:51:25 +00:00
content . location = url ;
}
2007-11-03 18:49:47 +00:00
2002-08-04 02:53:09 +00:00
function BrowserFullScreen ( )
{
window . fullScreen = ! window . fullScreen ;
}
2013-11-19 18:06:58 +00:00
function _checkDefaultAndSwitchToMetro ( ) {
# ifdef HAVE _SHELL _SERVICE
# ifdef XP _WIN
# ifdef MOZ _METRO
let shell = Components . classes [ "@mozilla.org/browser/shell-service;1" ] .
getService ( Components . interfaces . nsIShellService ) ;
let isDefault = shell . isDefaultBrowser ( false , false ) ;
if ( isDefault ) {
let appStartup = Components . classes [ "@mozilla.org/toolkit/app-startup;1" ] .
getService ( Components . interfaces . nsIAppStartup ) ;
2013-11-19 18:18:20 +00:00
Services . prefs . setBoolPref ( 'browser.sessionstore.resume_session_once' , true ) ;
2013-12-18 20:28:40 +00:00
let cancelQuit = Cc [ "@mozilla.org/supports-PRBool;1" ]
. createInstance ( Ci . nsISupportsPRBool ) ;
Services . obs . notifyObservers ( cancelQuit , "quit-application-requested" , "restart" ) ;
if ( ! cancelQuit . data ) {
appStartup . quit ( Components . interfaces . nsIAppStartup . eAttemptQuit |
Components . interfaces . nsIAppStartup . eRestartTouchEnvironment ) ;
}
2013-11-19 18:06:58 +00:00
return true ;
}
return false ;
# endif
# endif
# endif
}
function SwitchToMetro ( ) {
# ifdef HAVE _SHELL _SERVICE
# ifdef XP _WIN
# ifdef MOZ _METRO
if ( this . _checkDefaultAndSwitchToMetro ( ) ) {
return ;
}
let shell = Components . classes [ "@mozilla.org/browser/shell-service;1" ] .
getService ( Components . interfaces . nsIShellService ) ;
shell . setDefaultBrowser ( false , false ) ;
let intervalID = window . setInterval ( this . _checkDefaultAndSwitchToMetro , 1000 ) ;
window . setTimeout ( function ( ) { window . clearInterval ( intervalID ) ; } , 10000 ) ;
# endif
# endif
# endif
}
2010-08-27 04:44:01 +00:00
function onFullScreen ( event ) {
FullScreen . toggle ( event ) ;
2002-08-04 02:53:09 +00:00
}
2012-05-08 21:47:19 +00:00
function onMozEnteredDomFullscreen ( event ) {
FullScreen . enterDomFullscreen ( event ) ;
2011-10-28 08:28:05 +00:00
}
2002-08-04 02:53:09 +00:00
function getWebNavigation ( )
{
2012-06-15 19:09:48 +00:00
return gBrowser . webNavigation ;
2002-08-04 02:53:09 +00:00
}
2008-08-31 21:00:59 +00:00
function BrowserReloadWithFlags ( reloadFlags ) {
2013-09-03 22:11:22 +00:00
let url = gBrowser . currentURI . spec ;
2014-01-21 17:53:33 +00:00
if ( gBrowser . updateBrowserRemoteness ( gBrowser . selectedBrowser , url ) ) {
2013-09-03 22:11:22 +00:00
// If the remoteness has changed, the new browser doesn't have any
// information of what was loaded before, so we need to load the previous
// URL again.
gBrowser . loadURIWithFlags ( url , reloadFlags ) ;
return ;
}
2005-06-14 10:15:58 +00:00
/ * F i r s t , w e ' l l t r y t o u s e t h e s e s s i o n h i s t o r y o b j e c t t o r e l o a d s o
* that framesets are handled properly . If we ' re in a special
* window ( such as view - source ) that has no session history , fall
2002-08-04 02:53:09 +00:00
* back on using the web navigation ' s reload method .
* /
2012-06-15 19:09:48 +00:00
var webNav = gBrowser . webNavigation ;
2002-08-04 02:53:09 +00:00
try {
var sh = webNav . sessionHistory ;
if ( sh )
2002-11-16 17:14:12 +00:00
webNav = sh . QueryInterface ( nsIWebNavigation ) ;
2002-08-04 02:53:09 +00:00
} catch ( e ) {
}
try {
webNav . reload ( reloadFlags ) ;
} catch ( e ) {
}
}
2009-09-09 07:50:46 +00:00
var PrintPreviewListener = {
2010-02-09 16:24:49 +00:00
_printPreviewTab : null ,
_tabBeforePrintPreview : null ,
getPrintPreviewBrowser : function ( ) {
if ( ! this . _printPreviewTab ) {
this . _tabBeforePrintPreview = gBrowser . selectedTab ;
this . _printPreviewTab = gBrowser . loadOneTab ( "about:blank" ,
{ inBackground : false } ) ;
gBrowser . selectedTab = this . _printPreviewTab ;
}
return gBrowser . getBrowserForTab ( this . _printPreviewTab ) ;
} ,
getSourceBrowser : function ( ) {
return this . _tabBeforePrintPreview ?
this . _tabBeforePrintPreview . linkedBrowser : gBrowser . selectedBrowser ;
} ,
getNavToolbox : function ( ) {
return gNavToolbox ;
} ,
2009-09-09 07:50:46 +00:00
onEnter : function ( ) {
gInPrintPreviewMode = true ;
this . _toggleAffectedChrome ( ) ;
} ,
onExit : function ( ) {
2010-02-09 16:24:49 +00:00
gBrowser . selectedTab = this . _tabBeforePrintPreview ;
this . _tabBeforePrintPreview = null ;
2009-09-09 07:50:46 +00:00
gInPrintPreviewMode = false ;
this . _toggleAffectedChrome ( ) ;
2011-01-05 06:59:36 +00:00
gBrowser . removeTab ( this . _printPreviewTab ) ;
this . _printPreviewTab = null ;
2009-09-09 07:50:46 +00:00
} ,
_toggleAffectedChrome : function ( ) {
2011-06-02 20:34:12 +00:00
gNavToolbox . collapsed = gInPrintPreviewMode ;
2009-09-09 07:50:46 +00:00
if ( gInPrintPreviewMode )
this . _hideChrome ( ) ;
else
this . _showChrome ( ) ;
if ( this . _chromeState . sidebarOpen )
toggleSidebar ( this . _sidebarCommand ) ;
2011-01-07 20:28:02 +00:00
2013-09-10 14:51:53 +00:00
TabsInTitlebar . allowedBy ( "print-preview" , ! gInPrintPreviewMode ) ;
2009-09-09 07:50:46 +00:00
} ,
_hideChrome : function ( ) {
this . _chromeState = { } ;
2002-10-19 20:05:43 +00:00
var sidebar = document . getElementById ( "sidebar-box" ) ;
2009-09-09 07:50:46 +00:00
this . _chromeState . sidebarOpen = ! sidebar . hidden ;
this . _sidebarCommand = sidebar . getAttribute ( "sidebarcommand" ) ;
2005-04-23 16:37:20 +00:00
2006-04-19 20:50:25 +00:00
var notificationBox = gBrowser . getNotificationBox ( ) ;
2009-09-09 07:50:46 +00:00
this . _chromeState . notificationsOpen = ! notificationBox . notificationsHidden ;
notificationBox . notificationsHidden = true ;
2005-04-23 16:37:20 +00:00
2008-03-23 12:58:32 +00:00
document . getElementById ( "sidebar" ) . setAttribute ( "src" , "about:blank" ) ;
2011-01-17 14:35:32 +00:00
gBrowser . updateWindowResizers ( ) ;
2005-06-14 10:15:58 +00:00
2010-05-19 16:57:16 +00:00
this . _chromeState . findOpen = gFindBarInitialized && ! gFindBar . hidden ;
if ( gFindBarInitialized )
gFindBar . close ( ) ;
2010-09-10 17:47:57 +00:00
2013-02-05 09:30:21 +00:00
var globalNotificationBox = document . getElementById ( "global-notificationbox" ) ;
this . _chromeState . globalNotificationsOpen = ! globalNotificationBox . notificationsHidden ;
globalNotificationBox . notificationsHidden = true ;
2010-09-10 17:47:57 +00:00
this . _chromeState . syncNotificationsOpen = false ;
var syncNotifications = document . getElementById ( "sync-notifications" ) ;
if ( syncNotifications ) {
this . _chromeState . syncNotificationsOpen = ! syncNotifications . notificationsHidden ;
syncNotifications . notificationsHidden = true ;
}
2009-09-09 07:50:46 +00:00
} ,
_showChrome : function ( ) {
if ( this . _chromeState . notificationsOpen )
gBrowser . getNotificationBox ( ) . notificationsHidden = false ;
2005-04-23 16:37:20 +00:00
2009-09-09 07:50:46 +00:00
if ( this . _chromeState . findOpen )
2006-11-26 22:47:46 +00:00
gFindBar . open ( ) ;
2010-09-10 17:47:57 +00:00
2013-02-05 09:30:21 +00:00
if ( this . _chromeState . globalNotificationsOpen )
document . getElementById ( "global-notificationbox" ) . notificationsHidden = false ;
2010-09-10 17:47:57 +00:00
if ( this . _chromeState . syncNotificationsOpen )
document . getElementById ( "sync-notifications" ) . notificationsHidden = false ;
2004-11-30 08:23:02 +00:00
}
2002-08-04 02:53:09 +00:00
}
function getMarkupDocumentViewer ( )
{
2002-11-16 17:14:12 +00:00
return gBrowser . markupDocumentViewer ;
2002-08-04 02:53:09 +00:00
}
2013-03-21 12:58:07 +00:00
// This function is obsolete. Newer code should use <tooltip page="true"/> instead.
2002-08-04 02:53:09 +00:00
function FillInHTMLTooltip ( tipElement )
{
2013-03-21 12:58:07 +00:00
document . getElementById ( "aHTMLTooltip" ) . fillInPageTooltip ( tipElement ) ;
2002-08-04 02:53:09 +00:00
}
2009-06-21 00:04:07 +00:00
var browserDragAndDrop = {
2010-05-26 15:28:25 +00:00
canDropLink : function ( aEvent ) Services . droppedLinkHandler . canDropLink ( aEvent , true ) ,
2010-12-11 10:44:45 +00:00
dragOver : function ( aEvent )
2009-06-21 00:04:07 +00:00
{
2010-05-26 15:28:25 +00:00
if ( this . canDropLink ( aEvent ) ) {
2009-06-21 00:04:07 +00:00
aEvent . preventDefault ( ) ;
}
2010-04-18 18:27:18 +00:00
} ,
2009-06-21 00:04:07 +00:00
2012-01-31 01:58:30 +00:00
drop : function ( aEvent , aName , aDisallowInherit ) {
return Services . droppedLinkHandler . dropLink ( aEvent , aName , aDisallowInherit ) ;
}
2010-09-08 15:10:46 +00:00
} ;
2010-09-08 11:39:35 +00:00
2002-08-04 02:53:09 +00:00
var homeButtonObserver = {
2009-06-21 00:04:07 +00:00
onDrop : function ( aEvent )
2002-08-04 02:53:09 +00:00
{
2012-01-31 01:58:30 +00:00
// disallow setting home pages that inherit the principal
let url = browserDragAndDrop . drop ( aEvent , { } , true ) ;
setTimeout ( openHomeDialog , 0 , url ) ;
2002-08-04 02:53:09 +00:00
} ,
2009-06-21 00:04:07 +00:00
onDragOver : function ( aEvent )
2002-08-04 02:53:09 +00:00
{
2010-12-11 10:44:45 +00:00
browserDragAndDrop . dragOver ( aEvent ) ;
2009-06-21 00:04:07 +00:00
aEvent . dropEffect = "link" ;
2002-08-04 02:53:09 +00:00
} ,
2010-12-03 16:19:55 +00:00
onDragExit : function ( aEvent )
2002-08-04 02:53:09 +00:00
{
}
}
function openHomeDialog ( aURL )
{
var promptTitle = gNavigatorBundle . getString ( "droponhometitle" ) ;
var promptMsg = gNavigatorBundle . getString ( "droponhomemsg" ) ;
2010-01-28 18:31:45 +00:00
var pressedVal = Services . prompt . confirmEx ( window , promptTitle , promptMsg ,
Services . prompt . STD _YES _NO _BUTTONS ,
2009-07-29 08:49:59 +00:00
null , null , null , null , { value : 0 } ) ;
2002-08-04 02:53:09 +00:00
if ( pressedVal == 0 ) {
2002-10-29 19:55:04 +00:00
try {
var str = Components . classes [ "@mozilla.org/supports-string;1" ]
. createInstance ( Components . interfaces . nsISupportsString ) ;
str . data = aURL ;
gPrefService . setComplexValue ( "browser.startup.homepage" ,
2002-11-16 17:14:12 +00:00
Components . interfaces . nsISupportsString , str ) ;
2002-10-29 19:55:04 +00:00
} catch ( ex ) {
dump ( "Failed to set the home page.\n" + ex + "\n" ) ;
}
2002-08-04 02:53:09 +00:00
}
}
2009-01-23 08:13:13 +00:00
var newTabButtonObserver = {
2009-06-21 00:04:07 +00:00
onDragOver : function ( aEvent )
{
2010-12-11 10:44:45 +00:00
browserDragAndDrop . dragOver ( aEvent ) ;
2009-01-23 08:13:13 +00:00
} ,
2009-06-21 00:04:07 +00:00
2010-12-03 16:19:55 +00:00
onDragExit : function ( aEvent )
2009-06-21 00:04:07 +00:00
{
2009-01-23 08:13:13 +00:00
} ,
2009-06-21 00:04:07 +00:00
onDrop : function ( aEvent )
{
2010-04-18 18:27:18 +00:00
let url = browserDragAndDrop . drop ( aEvent , { } ) ;
2013-06-25 01:26:22 +00:00
Task . spawn ( function ( ) {
let data = yield getShortcutOrURIAndPostData ( url ) ;
if ( data . url ) {
// allow third-party services to fixup this URL
openNewTabWith ( data . url , null , data . postData , aEvent , true ) ;
}
} ) ;
2009-01-23 08:13:13 +00:00
}
}
2005-06-07 19:43:43 +00:00
var newWindowButtonObserver = {
2009-06-21 00:04:07 +00:00
onDragOver : function ( aEvent )
{
2010-12-11 10:44:45 +00:00
browserDragAndDrop . dragOver ( aEvent ) ;
2009-06-21 00:04:07 +00:00
} ,
2010-12-03 16:19:55 +00:00
onDragExit : function ( aEvent )
2009-06-21 00:04:07 +00:00
{
} ,
onDrop : function ( aEvent )
{
2010-04-18 18:27:18 +00:00
let url = browserDragAndDrop . drop ( aEvent , { } ) ;
2013-06-25 01:26:22 +00:00
Task . spawn ( function ( ) {
let data = yield getShortcutOrURIAndPostData ( url ) ;
if ( data . url ) {
// allow third-party services to fixup this URL
openNewWindowWith ( data . url , null , data . postData , true ) ;
}
} ) ;
2009-06-21 00:04:07 +00:00
}
2005-06-07 19:43:43 +00:00
}
2007-10-02 17:54:35 +00:00
const DOMLinkHandler = {
2014-02-09 01:41:34 +00:00
init : function ( ) {
let mm = window . messageManager ;
mm . addMessageListener ( "Link:AddFeed" , this ) ;
mm . addMessageListener ( "Link:AddIcon" , this ) ;
mm . addMessageListener ( "Link:AddSearch" , this ) ;
} ,
receiveMessage : function ( aMsg ) {
switch ( aMsg . name ) {
case "Link:AddFeed" :
let link = { type : aMsg . data . type , href : aMsg . data . href , title : aMsg . data . title } ;
FeedHandler . addFeed ( link , aMsg . target ) ;
break ;
case "Link:AddIcon" :
return this . addIcon ( aMsg . target , aMsg . data . url ) ;
break ;
case "Link:AddSearch" :
this . addSearch ( aMsg . target , aMsg . data . engine , aMsg . data . url ) ;
2007-10-03 21:52:44 +00:00
break ;
}
} ,
2012-08-21 00:52:26 +00:00
2014-02-09 01:41:34 +00:00
addIcon : function ( aBrowser , aURL ) {
if ( gBrowser . isFailedIcon ( aURL ) )
return false ;
2012-08-21 00:52:26 +00:00
2014-02-09 01:41:34 +00:00
let tab = gBrowser . _getTabForBrowser ( aBrowser ) ;
if ( ! tab )
return false ;
2013-04-09 19:44:01 +00:00
2014-02-09 01:41:34 +00:00
gBrowser . setIcon ( tab , aURL ) ;
return true ;
2012-08-21 00:52:26 +00:00
} ,
2006-08-31 17:00:57 +00:00
2014-02-09 01:41:34 +00:00
addSearch : function ( aBrowser , aEngine , aURL ) {
let tab = gBrowser . _getTabForBrowser ( aBrowser ) ;
if ( ! tab )
return false ;
BrowserSearch . addEngine ( aBrowser , aEngine , makeURI ( aURL ) ) ;
} ,
2007-10-02 17:54:35 +00:00
}
const BrowserSearch = {
2014-02-09 01:41:34 +00:00
addEngine : function ( browser , engine , uri ) {
2007-10-08 20:17:14 +00:00
if ( ! this . searchBar )
return ;
2008-02-17 05:26:52 +00:00
// Check to see whether we've already added an engine with this title
if ( browser . engines ) {
if ( browser . engines . some ( function ( e ) e . title == engine . title ) )
return ;
}
2007-10-08 20:17:14 +00:00
// Append the URI and an appropriate title to the browser data.
2008-10-21 20:02:26 +00:00
// Use documentURIObject in the check for shouldLoadFavIcon so that we
// do the right thing with about:-style error pages. Bug 453442
2007-10-08 20:17:14 +00:00
var iconURL = null ;
2014-02-09 01:41:34 +00:00
if ( gBrowser . shouldLoadFavIcon ( uri ) )
iconURL = uri . prePath + "/favicon.ico" ;
2007-10-08 20:17:14 +00:00
var hidden = false ;
// If this engine (identified by title) is already in the list, add it
// to the list of hidden engines rather than to the main list.
// XXX This will need to be changed when engines are identified by URL;
// see bug 335102.
2010-01-28 18:31:45 +00:00
if ( Services . search . getEngineByName ( engine . title ) )
2007-10-08 20:17:14 +00:00
hidden = true ;
var engines = ( hidden ? browser . hiddenEngines : browser . engines ) || [ ] ;
engines . push ( { uri : engine . href ,
title : engine . title ,
icon : iconURL } ) ;
if ( hidden )
browser . hiddenEngines = engines ;
else
2010-09-16 08:45:40 +00:00
browser . engines = engines ;
2006-05-06 02:37:51 +00:00
} ,
2006-03-17 07:16:00 +00:00
/ * *
* Gives focus to the search bar , if it is present on the toolbar , or loads
* the default engine ' s search form otherwise . For Mac , opens a new window
* or focuses an existing window , if necessary .
* /
webSearch : function BrowserSearch _webSearch ( ) {
2005-06-09 00:18:02 +00:00
# ifdef XP _MACOSX
2006-03-17 07:16:00 +00:00
if ( window . location . href != getBrowserURL ( ) ) {
var win = getTopWin ( ) ;
if ( win ) {
// If there's an open browser window, it should handle this command
2011-05-23 20:14:21 +00:00
win . focus ( ) ;
2006-03-17 07:16:00 +00:00
win . BrowserSearch . webSearch ( ) ;
} else {
// If there are no open browser windows, open a new one
2012-11-26 16:18:25 +00:00
var observer = function observer ( subject , topic , data ) {
2011-04-18 21:37:12 +00:00
if ( subject == win ) {
BrowserSearch . webSearch ( ) ;
Services . obs . removeObserver ( observer , "browser-delayed-startup-finished" ) ;
}
2006-07-19 18:29:31 +00:00
}
2011-05-23 20:14:21 +00:00
win = window . openDialog ( getBrowserURL ( ) , "_blank" ,
2006-03-17 07:16:00 +00:00
"chrome,all,dialog=no" , "about:blank" ) ;
2012-05-08 21:47:19 +00:00
Services . obs . addObserver ( observer , "browser-delayed-startup-finished" , false ) ;
2006-03-17 07:16:00 +00:00
}
return ;
2005-06-09 00:18:02 +00:00
}
# endif
2013-12-10 22:50:08 +00:00
let openSearchPageIfFieldIsNotActive = function ( aSearchBar ) {
if ( ! aSearchBar || document . activeElement != aSearchBar . textbox . inputField )
openUILinkIn ( Services . search . defaultEngine . searchForm , "current" ) ;
} ;
let searchBar = this . searchBar ;
let placement = CustomizableUI . getPlacementOfWidget ( "search-container" ) ;
2013-12-12 20:12:01 +00:00
let focusSearchBar = ( ) => {
searchBar = this . searchBar ;
searchBar . select ( ) ;
openSearchPageIfFieldIsNotActive ( searchBar ) ;
} ;
2013-12-10 22:50:08 +00:00
if ( placement && placement . area == CustomizableUI . AREA _PANEL ) {
2013-12-17 18:45:00 +00:00
// The panel is not constructed until the first time it is shown.
PanelUI . show ( ) . then ( focusSearchBar ) ;
2013-12-10 22:50:08 +00:00
return ;
2013-12-12 20:12:01 +00:00
}
2013-12-17 18:45:00 +00:00
if ( placement && placement . area == CustomizableUI . AREA _NAVBAR && searchBar &&
2014-03-04 19:38:33 +00:00
searchBar . parentNode . getAttribute ( "overflowedItem" ) == "true" ) {
2013-12-10 22:50:08 +00:00
let navBar = document . getElementById ( CustomizableUI . AREA _NAVBAR ) ;
navBar . overflowable . show ( ) . then ( ( ) => {
2013-12-12 20:12:01 +00:00
focusSearchBar ( ) ;
2013-12-10 22:50:08 +00:00
} ) ;
return ;
}
2013-12-12 20:12:01 +00:00
if ( searchBar ) {
if ( window . fullScreen )
FullScreen . mouseoverToggle ( true ) ;
2012-08-21 13:53:39 +00:00
searchBar . select ( ) ;
2013-12-10 22:50:08 +00:00
}
openSearchPageIfFieldIsNotActive ( searchBar ) ;
2006-03-17 07:16:00 +00:00
} ,
/ * *
* Loads a search results page , given a set of search terms . Uses the current
* engine if the search bar is visible , or the default engine otherwise .
*
* @ param searchText
* The search terms to use for the search .
*
* @ param useNewTab
* Boolean indicating whether or not the search should load in a new
* tab .
2011-03-18 21:56:46 +00:00
*
2011-12-21 00:20:21 +00:00
* @ param purpose [ optional ]
* A string meant to indicate the context of the search request . This
* allows the search service to provide a different nsISearchSubmission
* depending on e . g . where the search is triggered in the UI .
2013-02-13 20:33:52 +00:00
*
2013-10-29 16:24:46 +00:00
* @ return engine The search engine used to perform a search , or null if no
* search was performed .
2006-03-17 07:16:00 +00:00
* /
2013-10-29 16:24:46 +00:00
_loadSearch : function ( searchText , useNewTab , purpose ) {
let engine ;
2010-03-24 21:22:04 +00:00
2006-04-28 02:18:58 +00:00
// If the search bar is visible, use the current engine, otherwise, fall
// back to the default engine.
2007-10-08 20:17:14 +00:00
if ( isElementVisible ( this . searchBar ) )
2010-01-28 18:31:45 +00:00
engine = Services . search . currentEngine ;
2006-03-17 07:16:00 +00:00
else
2010-01-28 18:31:45 +00:00
engine = Services . search . defaultEngine ;
2010-03-24 21:22:04 +00:00
2013-10-29 16:24:46 +00:00
let submission = engine . getSubmission ( searchText , null , purpose ) ; // HTML response
2006-06-16 19:31:40 +00:00
// getSubmission can return null if the engine doesn't have a URL
// with a text/html response type. This is unlikely (since
// SearchService._addEngineToStore() should fail for such an engine),
// but let's be on the safe side.
2013-02-13 20:33:52 +00:00
if ( ! submission ) {
return null ;
}
2010-03-24 21:22:04 +00:00
2012-02-15 01:50:40 +00:00
let inBackground = Services . prefs . getBoolPref ( "browser.search.context.loadInBackground" ) ;
2011-03-23 11:37:04 +00:00
openLinkIn ( submission . uri . spec ,
useNewTab ? "tab" : "current" ,
{ postData : submission . postData ,
2012-02-15 01:50:40 +00:00
inBackground : inBackground ,
2011-03-23 11:37:04 +00:00
relatedToCurrent : true } ) ;
2013-02-13 20:33:52 +00:00
2013-10-29 16:24:46 +00:00
return engine ;
} ,
/ * *
* Just like _loadSearch , but preserving an old API .
*
* @ return string Name of the search engine used to perform a search or null
* if a search was not performed .
* /
loadSearch : function BrowserSearch _search ( searchText , useNewTab , purpose ) {
let engine = BrowserSearch . _loadSearch ( searchText , useNewTab , purpose ) ;
if ( ! engine ) {
return null ;
}
2013-02-13 20:33:52 +00:00
return engine . name ;
} ,
/ * *
* Perform a search initiated from the context menu .
*
* This should only be called from the context menu . See
* BrowserSearch . loadSearch for the preferred API .
* /
loadSearchFromContext : function ( terms ) {
2013-10-29 16:24:46 +00:00
let engine = BrowserSearch . _loadSearch ( terms , true , "contextmenu" ) ;
2013-02-13 20:33:52 +00:00
if ( engine ) {
BrowserSearch . recordSearchInHealthReport ( engine , "contextmenu" ) ;
}
2006-03-17 07:16:00 +00:00
} ,
2006-05-06 02:37:51 +00:00
2006-03-17 07:16:00 +00:00
/ * *
2007-10-08 20:17:14 +00:00
* Returns the search bar element if it is present in the toolbar , null otherwise .
2006-03-17 07:16:00 +00:00
* /
2007-10-08 20:17:14 +00:00
get searchBar ( ) {
return document . getElementById ( "searchbar" ) ;
2006-04-28 02:18:58 +00:00
} ,
loadAddEngines : function BrowserSearch _loadAddEngines ( ) {
var newWindowPref = gPrefService . getIntPref ( "browser.link.open_newwindow" ) ;
var where = newWindowPref == 3 ? "tab" : "window" ;
2006-09-08 06:56:14 +00:00
var searchEnginesURL = formatURL ( "browser.search.searchEnginesURL" , true ) ;
2006-04-28 02:18:58 +00:00
openUILinkIn ( searchEnginesURL , where ) ;
2013-02-13 18:34:34 +00:00
} ,
/ * *
* Helper to record a search with Firefox Health Report .
*
* FHR records only search counts and nothing pertaining to the search itself .
*
* @ param engine
2013-10-18 19:31:39 +00:00
* ( nsISearchEngine ) The engine handling the search .
2013-02-13 18:34:34 +00:00
* @ param source
* ( string ) Where the search originated from . See the FHR
* SearchesProvider for allowed values .
* /
recordSearchInHealthReport : function ( engine , source ) {
# ifdef MOZ _SERVICES _HEALTHREPORT
let reporter = Cc [ "@mozilla.org/datareporting/service;1" ]
. getService ( )
. wrappedJSObject
. healthReporter ;
// This can happen if the FHR component of the data reporting service is
// disabled. This is controlled by a pref that most will never use.
if ( ! reporter ) {
return ;
}
reporter . onInit ( ) . then ( function record ( ) {
try {
reporter . getProvider ( "org.mozilla.searches" ) . recordSearch ( engine , source ) ;
} catch ( ex ) {
Cu . reportError ( ex ) ;
}
} ) ;
# endif
} ,
} ;
2002-09-20 21:56:57 +00:00
2008-01-30 07:17:45 +00:00
function FillHistoryMenu ( aParent ) {
2008-12-31 19:52:40 +00:00
// Lazily add the hover listeners on first showing and never remove them
if ( ! aParent . hasStatusListener ) {
// Show history item's uri in the status bar when hovering, and clear on exit
aParent . addEventListener ( "DOMMenuItemActive" , function ( aEvent ) {
// Only the current page should have the checked attribute, so skip it
if ( ! aEvent . target . hasAttribute ( "checked" ) )
XULBrowserWindow . setOverLink ( aEvent . target . getAttribute ( "uri" ) ) ;
} , false ) ;
aParent . addEventListener ( "DOMMenuItemInactive" , function ( ) {
XULBrowserWindow . setOverLink ( "" ) ;
} , false ) ;
aParent . hasStatusListener = true ;
}
2008-01-30 07:17:45 +00:00
// Remove old entries if any
var children = aParent . childNodes ;
for ( var i = children . length - 1 ; i >= 0 ; -- i ) {
if ( children [ i ] . hasAttribute ( "index" ) )
aParent . removeChild ( children [ i ] ) ;
}
2006-08-16 06:17:03 +00:00
2012-06-15 19:09:48 +00:00
var webNav = gBrowser . webNavigation ;
2008-01-30 07:17:45 +00:00
var sessionHistory = webNav . sessionHistory ;
var count = sessionHistory . count ;
if ( count <= 1 ) // don't display the popup for a single item
return false ;
2009-07-13 17:34:13 +00:00
const MAX _HISTORY _MENU _ITEMS = 15 ;
var index = sessionHistory . index ;
2008-01-30 07:17:45 +00:00
var half _length = Math . floor ( MAX _HISTORY _MENU _ITEMS / 2 ) ;
var start = Math . max ( index - half _length , 0 ) ;
2009-07-13 17:34:13 +00:00
var end = Math . min ( start == 0 ? MAX _HISTORY _MENU _ITEMS : index + half _length + 1 , count ) ;
2008-01-30 07:17:45 +00:00
if ( end == count )
start = Math . max ( count - MAX _HISTORY _MENU _ITEMS , 0 ) ;
2009-07-13 22:10:04 +00:00
var tooltipBack = gNavigatorBundle . getString ( "tabHistory.goBack" ) ;
var tooltipCurrent = gNavigatorBundle . getString ( "tabHistory.current" ) ;
var tooltipForward = gNavigatorBundle . getString ( "tabHistory.goForward" ) ;
2008-01-30 07:17:45 +00:00
for ( var j = end - 1 ; j >= start ; j -- ) {
let item = document . createElement ( "menuitem" ) ;
let entry = sessionHistory . getEntryAtIndex ( j , false ) ;
2008-12-31 19:52:40 +00:00
let uri = entry . URI . spec ;
2008-01-30 07:17:45 +00:00
2008-12-31 19:52:40 +00:00
item . setAttribute ( "uri" , uri ) ;
item . setAttribute ( "label" , entry . title || uri ) ;
2008-01-30 07:17:45 +00:00
item . setAttribute ( "index" , j ) ;
2008-02-07 09:30:08 +00:00
if ( j != index ) {
2012-04-12 10:27:14 +00:00
PlacesUtils . favicons . getFaviconURLForPage ( entry . URI , function ( aURI ) {
if ( aURI ) {
let iconURL = PlacesUtils . favicons . getFaviconLinkForIcon ( aURI ) . spec ;
item . style . listStyleImage = "url(" + iconURL + ")" ;
}
} ) ;
2008-02-07 09:30:08 +00:00
}
2008-01-30 07:17:45 +00:00
if ( j < index ) {
2010-03-24 09:17:40 +00:00
item . className = "unified-nav-back menuitem-iconic menuitem-with-favicon" ;
2008-01-30 07:17:45 +00:00
item . setAttribute ( "tooltiptext" , tooltipBack ) ;
} else if ( j == index ) {
item . setAttribute ( "type" , "radio" ) ;
item . setAttribute ( "checked" , "true" ) ;
item . className = "unified-nav-current" ;
item . setAttribute ( "tooltiptext" , tooltipCurrent ) ;
} else {
2010-03-24 09:17:40 +00:00
item . className = "unified-nav-forward menuitem-iconic menuitem-with-favicon" ;
2008-01-30 07:17:45 +00:00
item . setAttribute ( "tooltiptext" , tooltipForward ) ;
}
aParent . appendChild ( item ) ;
2002-08-04 02:53:09 +00:00
}
2008-01-30 07:17:45 +00:00
return true ;
}
2002-08-04 02:53:09 +00:00
2008-09-25 11:33:51 +00:00
function addToUrlbarHistory ( aUrlToAdd ) {
2012-02-18 06:40:10 +00:00
if ( ! PrivateBrowsingUtils . isWindowPrivate ( window ) &&
aUrlToAdd &&
2012-09-08 20:58:23 +00:00
! aUrlToAdd . contains ( " " ) &&
2008-09-25 11:33:51 +00:00
! /[\x00-\x1F]/ . test ( aUrlToAdd ) )
PlacesUIUtils . markPageAsTyped ( aUrlToAdd ) ;
2002-08-04 02:53:09 +00:00
}
function toJavaScriptConsole ( )
{
2003-03-01 08:07:13 +00:00
toOpenWindowByType ( "global:console" , "chrome://global/content/console.xul" ) ;
2002-08-04 02:53:09 +00:00
}
2008-01-26 21:01:44 +00:00
function BrowserDownloadsUI ( )
{
Cc [ "@mozilla.org/download-manager-ui;1" ] .
2008-01-30 18:15:01 +00:00
getService ( Ci . nsIDownloadManagerUI ) . show ( window ) ;
2008-01-26 21:01:44 +00:00
}
2003-12-01 06:33:00 +00:00
function toOpenWindowByType ( inType , uri , features )
2002-08-04 02:53:09 +00:00
{
2010-01-28 18:31:45 +00:00
var topWindow = Services . wm . getMostRecentWindow ( inType ) ;
2005-06-14 10:15:58 +00:00
2003-12-01 06:33:00 +00:00
if ( topWindow )
2002-08-04 02:53:09 +00:00
topWindow . focus ( ) ;
2003-12-01 06:33:00 +00:00
else if ( features )
window . open ( uri , "_blank" , features ) ;
2002-08-04 02:53:09 +00:00
else
window . open ( uri , "_blank" , "chrome,extrachrome,menubar,resizable,scrollbars,status,toolbar" ) ;
}
2012-10-07 19:39:42 +00:00
function OpenBrowserWindow ( options )
2002-08-04 02:53:09 +00:00
{
2012-03-20 15:20:56 +00:00
var telemetryObj = { } ;
TelemetryStopwatch . start ( "FX_NEW_WINDOW_MS" , telemetryObj ) ;
function newDocumentShown ( doc , topic , data ) {
if ( topic == "document-shown" &&
doc != document &&
doc . defaultView == win ) {
Services . obs . removeObserver ( newDocumentShown , "document-shown" ) ;
2013-11-02 15:14:52 +00:00
Services . obs . removeObserver ( windowClosed , "domwindowclosed" ) ;
2012-03-20 15:20:56 +00:00
TelemetryStopwatch . finish ( "FX_NEW_WINDOW_MS" , telemetryObj ) ;
}
2013-11-02 15:14:52 +00:00
}
function windowClosed ( subject ) {
if ( subject == win ) {
Services . obs . removeObserver ( newDocumentShown , "document-shown" ) ;
Services . obs . removeObserver ( windowClosed , "domwindowclosed" ) ;
}
}
// Make sure to remove the 'document-shown' observer in case the window
// is being closed right after it was opened to avoid leaking.
2012-03-20 15:20:56 +00:00
Services . obs . addObserver ( newDocumentShown , "document-shown" , false ) ;
2013-11-02 15:14:52 +00:00
Services . obs . addObserver ( windowClosed , "domwindowclosed" , false ) ;
2012-03-20 15:20:56 +00:00
2002-08-04 02:53:09 +00:00
var charsetArg = new String ( ) ;
2005-01-17 18:50:18 +00:00
var handler = Components . classes [ "@mozilla.org/browser/clh;1" ]
. getService ( Components . interfaces . nsIBrowserHandler ) ;
2005-04-05 03:17:13 +00:00
var defaultArgs = handler . defaultArgs ;
2006-01-06 21:08:48 +00:00
var wintype = document . documentElement . getAttribute ( 'windowtype' ) ;
2002-08-04 02:53:09 +00:00
2012-10-07 19:39:42 +00:00
var extraFeatures = "" ;
2012-12-15 23:59:19 +00:00
if ( options && options . private ) {
2012-10-07 19:39:42 +00:00
extraFeatures = ",private" ;
2013-03-24 16:07:28 +00:00
if ( ! PrivateBrowsingUtils . permanentPrivateBrowsing ) {
// Force the new window to load about:privatebrowsing instead of the default home page
defaultArgs = "about:privatebrowsing" ;
}
2012-12-10 11:39:00 +00:00
} else {
extraFeatures = ",non-private" ;
2012-10-07 19:39:42 +00:00
}
2014-02-11 17:01:08 +00:00
if ( options && options . remote ) {
2014-02-21 01:26:41 +00:00
let omtcEnabled = gPrefService . getBoolPref ( "layers.offmainthreadcomposition.enabled" ) ;
if ( ! omtcEnabled ) {
alert ( "To use out-of-process tabs, you must set the layers.offmainthreadcomposition.enabled preference and restart. Opening a normal window instead." ) ;
} else {
extraFeatures += ",remote" ;
}
2014-02-11 17:01:08 +00:00
} else if ( options && options . remote === false ) {
extraFeatures += ",non-remote" ;
}
2002-08-04 02:53:09 +00:00
// 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...
2005-06-09 00:18:02 +00:00
var win ;
2005-01-28 16:06:56 +00:00
if ( window && ( wintype == "navigator:browser" ) && window . content && window . content . document )
2002-08-04 02:53:09 +00:00
{
2005-01-28 16:06:56 +00:00
var DocCharset = window . content . document . characterSet ;
2002-08-04 02:53:09 +00:00
charsetArg = "charset=" + DocCharset ;
//we should "inherit" the charset menu setting in a new window
2012-10-07 19:39:42 +00:00
win = window . openDialog ( "chrome://browser/content/" , "_blank" , "chrome,all,dialog=no" + extraFeatures , defaultArgs , charsetArg ) ;
2002-08-04 02:53:09 +00:00
}
else // forget about the charset information.
{
2012-10-07 19:39:42 +00:00
win = window . openDialog ( "chrome://browser/content/" , "_blank" , "chrome,all,dialog=no" + extraFeatures , defaultArgs ) ;
2002-08-04 02:53:09 +00:00
}
2005-06-09 00:18:02 +00:00
return win ;
2002-08-04 02:53:09 +00:00
}
2014-01-18 00:43:21 +00:00
// Only here for backwards compat, we should remove this soon
2012-06-06 11:01:19 +00:00
function BrowserCustomizeToolbar ( ) {
2013-03-26 21:23:23 +00:00
gCustomizeMode . enter ( ) ;
2002-09-27 04:06:56 +00:00
}
2008-01-26 05:48:51 +00:00
/ * *
* Update the global flag that tracks whether or not any edit UI ( the Edit menu ,
* edit - related items in the context menu , and edit - related toolbar buttons
* is visible , then update the edit commands ' enabled state accordingly . We use
* this flag to skip updating the edit commands on focus or selection changes
* when no UI is visible to improve performance ( including pageload performance ,
* since focus changes when you load a new page ) .
*
2008-01-26 20:56:23 +00:00
* If UI is visible , we use goUpdateGlobalEditMenuItems to set the commands '
* enabled state so the UI will reflect it appropriately .
2010-03-24 21:22:04 +00:00
*
2008-01-26 05:48:51 +00:00
* If the UI isn ' t visible , we enable all edit commands so keyboard shortcuts
* still work and just lazily disable them as needed when the user presses a
* shortcut .
*
* This doesn ' t work on Mac , since Mac menus flash when users press their
* keyboard shortcuts , so edit UI is essentially always visible on the Mac ,
* and we need to always update the edit commands . Thus on Mac this function
* is a no op .
* /
function updateEditUIVisibility ( )
{
# ifndef XP _MACOSX
let editMenuPopupState = document . getElementById ( "menu_EditPopup" ) . state ;
let contextMenuPopupState = document . getElementById ( "contentAreaContextMenu" ) . state ;
2008-01-26 20:56:23 +00:00
let placesContextMenuPopupState = document . getElementById ( "placesContext" ) . state ;
2008-01-26 05:48:51 +00:00
// The UI is visible if the Edit menu is opening or open, if the context menu
// is open, or if the toolbar has been customized to include the Cut, Copy,
// or Paste toolbar buttons.
gEditUIVisible = editMenuPopupState == "showing" ||
editMenuPopupState == "open" ||
contextMenuPopupState == "showing" ||
contextMenuPopupState == "open" ||
2008-01-26 20:56:23 +00:00
placesContextMenuPopupState == "showing" ||
placesContextMenuPopupState == "open" ||
2013-06-03 16:46:42 +00:00
document . getElementById ( "edit-controls" ) ? true : false ;
2008-01-26 05:48:51 +00:00
// If UI is visible, update the edit commands' enabled state to reflect
// whether or not they are actually enabled for the current focus/selection.
if ( gEditUIVisible )
goUpdateGlobalEditMenuItems ( ) ;
// Otherwise, enable all commands, so that keyboard shortcuts still work,
// then lazily determine their actual enabled state when the user presses
// a keyboard shortcut.
else {
2008-01-26 20:56:23 +00:00
goSetCommandEnabled ( "cmd_undo" , true ) ;
goSetCommandEnabled ( "cmd_redo" , true ) ;
goSetCommandEnabled ( "cmd_cut" , true ) ;
goSetCommandEnabled ( "cmd_copy" , true ) ;
goSetCommandEnabled ( "cmd_paste" , true ) ;
goSetCommandEnabled ( "cmd_selectAll" , true ) ;
goSetCommandEnabled ( "cmd_delete" , true ) ;
goSetCommandEnabled ( "cmd_switchTextDirection" , true ) ;
2008-01-26 05:48:51 +00:00
}
# endif
}
2013-01-31 17:10:28 +00:00
/ * *
* Makes the Character Encoding menu enabled or disabled as appropriate .
* To be called when the View menu or the app menu is opened .
* /
function updateCharacterEncodingMenuState ( )
{
let charsetMenu = document . getElementById ( "charsetMenu" ) ;
// gBrowser is null on Mac when the menubar shows in the context of
2013-04-09 19:44:01 +00:00
// non-browser windows. The above elements may be null depending on
2013-01-31 17:10:28 +00:00
// what parts of the menubar are present. E.g. no app menu on Mac.
if ( gBrowser &&
gBrowser . docShell &&
gBrowser . docShell . mayEnableCharacterEncodingMenu ) {
if ( charsetMenu ) {
charsetMenu . removeAttribute ( "disabled" ) ;
}
} else {
if ( charsetMenu ) {
charsetMenu . setAttribute ( "disabled" , "true" ) ;
}
}
}
2007-09-02 22:11:38 +00:00
/ * *
* Returns true if | aMimeType | is text - based , false otherwise .
*
* @ param aMimeType
* The MIME type to check .
2008-03-06 20:12:09 +00:00
*
2010-03-24 21:22:04 +00:00
* If adding types to this function , please also check the similar
2008-03-06 20:12:09 +00:00
* function in findbar . xml
2007-09-02 22:11:38 +00:00
* /
function mimeTypeIsTextBased ( aMimeType )
{
2012-12-20 20:34:06 +00:00
return aMimeType . startsWith ( "text/" ) ||
aMimeType . endsWith ( "+xml" ) ||
2007-09-02 22:11:38 +00:00
aMimeType == "application/x-javascript" ||
2008-03-06 20:12:09 +00:00
aMimeType == "application/javascript" ||
2013-06-14 01:28:23 +00:00
aMimeType == "application/json" ||
2007-09-02 22:11:38 +00:00
aMimeType == "application/xml" ||
aMimeType == "mozilla.application/cached-xul" ;
}
2008-09-07 19:18:57 +00:00
var XULBrowserWindow = {
2002-08-09 01:41:39 +00:00
// Stored Status, Link and Loading values
2008-09-07 19:18:57 +00:00
status : "" ,
defaultStatus : "" ,
2011-02-03 06:48:39 +00:00
overLink : "" ,
2008-09-07 19:18:57 +00:00
startTime : 0 ,
2002-10-13 02:22:40 +00:00
statusText : "" ,
2008-10-25 13:15:53 +00:00
isBusy : false ,
2013-05-14 18:20:45 +00:00
// Left here for add-on compatibility, see bug 752434
inContentWhitelist : [ ] ,
2002-08-09 01:41:39 +00:00
2008-09-07 19:18:57 +00:00
QueryInterface : function ( aIID ) {
2007-02-08 13:15:50 +00:00
if ( aIID . equals ( Ci . nsIWebProgressListener ) ||
aIID . equals ( Ci . nsIWebProgressListener2 ) ||
aIID . equals ( Ci . nsISupportsWeakReference ) ||
aIID . equals ( Ci . nsIXULBrowserWindow ) ||
aIID . equals ( Ci . nsISupports ) )
2002-08-09 01:41:39 +00:00
return this ;
2007-02-08 13:15:50 +00:00
throw Cr . NS _NOINTERFACE ;
2002-08-09 01:41:39 +00:00
} ,
2008-09-07 19:18:57 +00:00
get stopCommand ( ) {
delete this . stopCommand ;
return this . stopCommand = document . getElementById ( "Browser:Stop" ) ;
} ,
get reloadCommand ( ) {
delete this . reloadCommand ;
return this . reloadCommand = document . getElementById ( "Browser:Reload" ) ;
} ,
2011-01-28 13:35:49 +00:00
get statusTextField ( ) {
2013-09-12 21:36:05 +00:00
return gBrowser . getStatusPanel ( ) ;
2011-01-28 13:35:49 +00:00
} ,
2008-09-07 19:18:57 +00:00
get isImage ( ) {
delete this . isImage ;
return this . isImage = document . getElementById ( "isImage" ) ;
} ,
init : function ( ) {
2013-07-15 15:58:09 +00:00
// Initialize the security button's state and tooltip text.
2008-07-30 20:28:29 +00:00
var securityUI = gBrowser . securityUI ;
2005-05-19 22:52:26 +00:00
this . onSecurityChange ( null , null , securityUI . state ) ;
2002-08-09 01:41:39 +00:00
} ,
2013-02-18 21:01:21 +00:00
setJSStatus : function ( ) {
// unsupported
2002-08-09 01:41:39 +00:00
} ,
2008-09-07 19:18:57 +00:00
setDefaultStatus : function ( status ) {
2002-08-09 01:41:39 +00:00
this . defaultStatus = status ;
2011-01-28 13:35:49 +00:00
this . updateStatusField ( ) ;
2002-08-09 01:41:39 +00:00
} ,
2010-11-16 22:39:41 +00:00
setOverLink : function ( url , anchorElt ) {
2011-02-03 06:48:39 +00:00
// Encode bidirectional formatting characters.
// (RFC 3987 sections 3.2 and 4.1 paragraph 6)
2012-03-14 12:20:03 +00:00
url = url . replace ( /[\u200e\u200f\u202a\u202b\u202c\u202d\u202e]/g ,
encodeURIComponent ) ;
if ( gURLBar && gURLBar . _mayTrimURLs /* corresponds to browser.urlbar.trimURLs */ )
url = trimURL ( url ) ;
this . overLink = url ;
2011-02-03 06:48:39 +00:00
LinkTargetDisplay . update ( ) ;
} ,
2011-01-28 13:35:49 +00:00
2014-01-22 20:27:23 +00:00
showTooltip : function ( x , y , tooltip ) {
// The x,y coordinates are relative to the <browser> element using
// the chrome zoom level.
let elt = document . getElementById ( "remoteBrowserTooltip" ) ;
elt . label = tooltip ;
let anchor = gBrowser . selectedBrowser ;
elt . openPopupAtScreen ( anchor . boxObject . screenX + x , anchor . boxObject . screenY + y , false , null ) ;
} ,
hideTooltip : function ( ) {
let elt = document . getElementById ( "remoteBrowserTooltip" ) ;
elt . hidePopup ( ) ;
} ,
2011-01-28 13:35:49 +00:00
updateStatusField : function ( ) {
2011-02-09 21:40:13 +00:00
var text , type , types = [ "overLink" ] ;
if ( this . _busyUI )
types . push ( "status" ) ;
2013-02-18 21:01:21 +00:00
types . push ( "defaultStatus" ) ;
2012-08-21 16:56:07 +00:00
for ( type of types ) {
2011-02-09 21:40:13 +00:00
text = this [ type ] ;
2012-08-21 16:56:07 +00:00
if ( text )
break ;
2011-02-09 21:40:13 +00:00
}
2011-01-28 13:35:49 +00:00
// check the current value so we don't trigger an attribute change
// and cause needless (slow!) UI updates
if ( this . statusText != text ) {
2011-02-09 21:40:13 +00:00
let field = this . statusTextField ;
field . setAttribute ( "previoustype" , field . getAttribute ( "type" ) ) ;
field . setAttribute ( "type" , type ) ;
field . label = text ;
2011-02-28 11:58:44 +00:00
field . setAttribute ( "crop" , type == "overLink" ? "center" : "end" ) ;
2011-01-28 13:35:49 +00:00
this . statusText = text ;
}
2002-08-09 01:41:39 +00:00
} ,
2010-11-16 22:39:41 +00:00
2010-10-28 22:00:31 +00:00
// Called before links are navigated to to allow us to retarget them if needed.
onBeforeLinkTraversal : function ( originalTarget , linkURI , linkNode , isAppTab ) {
2012-10-16 06:58:13 +00:00
let target = this . _onBeforeLinkTraversal ( originalTarget , linkURI , linkNode , isAppTab ) ;
SocialUI . closeSocialPanelForLinkTraversal ( target , linkNode ) ;
return target ;
} ,
_onBeforeLinkTraversal : function ( originalTarget , linkURI , linkNode , isAppTab ) {
2010-10-28 22:00:31 +00:00
// Don't modify non-default targets or targets that aren't in top-level app
// tab docshells (isAppTab will be false for app tab subframes).
if ( originalTarget != "" || ! isAppTab )
return originalTarget ;
2010-11-29 21:22:25 +00:00
// External links from within app tabs should always open in new tabs
// instead of replacing the app tab's page (Bug 575561)
let linkHost ;
let docHost ;
2010-10-28 22:00:31 +00:00
try {
2010-11-29 21:22:25 +00:00
linkHost = linkURI . host ;
docHost = linkNode . ownerDocument . documentURIObject . host ;
2010-10-28 22:00:31 +00:00
} catch ( e ) {
2010-11-29 21:22:25 +00:00
// nsIURI.host can throw for non-nsStandardURL nsIURIs.
// If we fail to get either host, just return originalTarget.
return originalTarget ;
2010-10-28 22:00:31 +00:00
}
2010-11-29 21:22:25 +00:00
if ( docHost == linkHost )
return originalTarget ;
// Special case: ignore "www" prefix if it is part of host string
let [ longHost , shortHost ] =
linkHost . length > docHost . length ? [ linkHost , docHost ] : [ docHost , linkHost ] ;
if ( longHost == "www." + shortHost )
return originalTarget ;
return "_blank" ;
2010-10-28 22:00:31 +00:00
} ,
2002-08-09 01:41:39 +00:00
2008-09-07 19:18:57 +00:00
onProgressChange : function ( aWebProgress , aRequest ,
aCurSelfProgress , aMaxSelfProgress ,
aCurTotalProgress , aMaxTotalProgress ) {
2010-10-12 03:47:59 +00:00
// Do nothing.
2002-08-09 01:41:39 +00:00
} ,
2008-09-07 19:18:57 +00:00
onProgressChange64 : function ( aWebProgress , aRequest ,
aCurSelfProgress , aMaxSelfProgress ,
aCurTotalProgress , aMaxTotalProgress ) {
2007-02-08 13:15:50 +00:00
return this . onProgressChange ( aWebProgress , aRequest ,
aCurSelfProgress , aMaxSelfProgress , aCurTotalProgress ,
aMaxTotalProgress ) ;
} ,
2013-04-15 22:34:27 +00:00
// This function fires only for the currently selected tab.
2008-09-07 19:18:57 +00:00
onStateChange : function ( aWebProgress , aRequest , aStateFlags , aStatus ) {
2009-09-09 16:31:25 +00:00
const nsIWebProgressListener = Ci . nsIWebProgressListener ;
const nsIChannel = Ci . nsIChannel ;
2010-08-19 23:06:07 +00:00
2014-03-12 03:13:41 +00:00
let browser = gBrowser . selectedBrowser ;
2010-01-05 07:28:46 +00:00
if ( aStateFlags & nsIWebProgressListener . STATE _START &&
aStateFlags & nsIWebProgressListener . STATE _IS _NETWORK ) {
2013-04-25 05:29:24 +00:00
if ( aRequest && aWebProgress . isTopLevel ) {
2013-04-15 22:34:27 +00:00
// clear out feed data
2014-03-12 03:13:41 +00:00
browser . feeds = null ;
2013-04-15 22:34:27 +00:00
// clear out search-engine data
2014-03-12 03:13:41 +00:00
browser . engines = null ;
2013-04-15 22:34:27 +00:00
}
2008-09-07 19:18:57 +00:00
2008-10-25 13:15:53 +00:00
this . isBusy = true ;
2009-09-09 16:31:25 +00:00
if ( ! ( aStateFlags & nsIWebProgressListener . STATE _RESTORING ) ) {
this . _busyUI = true ;
// XXX: This needs to be based on window activity...
this . stopCommand . removeAttribute ( "disabled" ) ;
2010-01-05 07:28:46 +00:00
CombinedStopReload . switchToStop ( ) ;
2008-09-07 19:18:57 +00:00
}
2002-08-09 01:41:39 +00:00
}
else if ( aStateFlags & nsIWebProgressListener . STATE _STOP ) {
2002-09-20 02:54:41 +00:00
// This (thanks to the filter) is a network stop or the last
// request stop outside of loading the document, stop throbbers
// and progress bars and such
if ( aRequest ) {
2008-09-07 19:18:57 +00:00
let msg = "" ;
2008-09-19 19:03:06 +00:00
let location ;
2008-09-07 19:18:57 +00:00
// Get the URI either from a channel or a pseudo-object
if ( aRequest instanceof nsIChannel || "URI" in aRequest ) {
2008-09-19 19:03:06 +00:00
location = aRequest . URI ;
2008-09-07 19:18:57 +00:00
// For keyword URIs clear the user typed value since they will be changed into real URIs
2013-04-25 05:29:24 +00:00
if ( location . scheme == "keyword" && aWebProgress . isTopLevel )
2008-09-07 19:18:57 +00:00
gBrowser . userTypedValue = null ;
if ( location . spec != "about:blank" ) {
switch ( aStatus ) {
2008-09-10 04:33:27 +00:00
case Components . results . NS _ERROR _NET _TIMEOUT :
2008-09-07 19:18:57 +00:00
msg = gNavigatorBundle . getString ( "nv_timeout" ) ;
break ;
2002-08-09 01:41:39 +00:00
}
}
}
2008-09-07 19:18:57 +00:00
this . status = "" ;
this . setDefaultStatus ( msg ) ;
2002-08-09 01:41:39 +00:00
2008-09-07 19:18:57 +00:00
// Disable menu entries for images, enable otherwise
2014-03-12 03:13:41 +00:00
if ( browser . documentContentType && mimeTypeIsTextBased ( browser . documentContentType ) )
2008-09-07 19:18:57 +00:00
this . isImage . removeAttribute ( 'disabled' ) ;
else
this . isImage . setAttribute ( 'disabled' , 'true' ) ;
}
2002-10-09 07:37:55 +00:00
2008-10-25 13:15:53 +00:00
this . isBusy = false ;
2009-09-09 16:31:25 +00:00
if ( this . _busyUI ) {
this . _busyUI = false ;
2002-08-09 01:41:39 +00:00
2009-09-09 16:31:25 +00:00
this . stopCommand . setAttribute ( "disabled" , "true" ) ;
2010-01-05 07:28:46 +00:00
CombinedStopReload . switchToReload ( aRequest instanceof Ci . nsIRequest ) ;
2009-09-09 16:31:25 +00:00
}
2002-08-09 01:41:39 +00:00
}
} ,
2011-11-10 14:01:11 +00:00
onLocationChange : function ( aWebProgress , aRequest , aLocationURI , aFlags ) {
2006-11-22 17:42:35 +00:00
var location = aLocationURI ? aLocationURI . spec : "" ;
2007-10-04 20:02:36 +00:00
2010-09-11 04:10:31 +00:00
// Hide the form invalid popup.
2012-07-31 00:43:29 +00:00
if ( gFormSubmitObserver . panel ) {
2010-09-11 04:10:31 +00:00
gFormSubmitObserver . panel . hidePopup ( ) ;
}
2013-03-21 12:58:07 +00:00
let pageTooltip = document . getElementById ( "aHTMLTooltip" ) ;
let tooltipNode = pageTooltip . triggerNode ;
if ( tooltipNode ) {
2006-11-22 17:42:35 +00:00
// Optimise for the common case
2013-04-25 05:29:24 +00:00
if ( aWebProgress . isTopLevel ) {
2013-03-21 12:58:07 +00:00
pageTooltip . hidePopup ( ) ;
2006-11-22 17:42:35 +00:00
}
else {
2013-03-21 12:58:07 +00:00
for ( let tooltipWindow = tooltipNode . ownerDocument . defaultView ;
2006-11-22 17:42:35 +00:00
tooltipWindow != tooltipWindow . parent ;
tooltipWindow = tooltipWindow . parent ) {
if ( tooltipWindow == aWebProgress . DOMWindow ) {
2013-03-21 12:58:07 +00:00
pageTooltip . hidePopup ( ) ;
2006-11-22 17:42:35 +00:00
break ;
}
}
}
}
2006-06-21 03:10:01 +00:00
2014-03-12 03:13:41 +00:00
let browser = gBrowser . selectedBrowser ;
2005-09-18 21:31:34 +00:00
// Disable menu entries for images, enable otherwise
2014-03-12 03:13:41 +00:00
if ( browser . documentContentType && mimeTypeIsTextBased ( browser . documentContentType ) )
2005-09-18 21:31:34 +00:00
this . isImage . removeAttribute ( 'disabled' ) ;
else
this . isImage . setAttribute ( 'disabled' , 'true' ) ;
2010-11-16 22:39:41 +00:00
this . hideOverLinkImmediately = true ;
2002-08-09 01:41:39 +00:00
this . setOverLink ( "" , null ) ;
2010-11-16 22:39:41 +00:00
this . hideOverLinkImmediately = false ;
2005-06-14 10:15:58 +00:00
2002-08-09 01:41:39 +00:00
// We should probably not do this if the value has changed since the user
// searched
// Update urlbar only if a new page was loaded on the primary content area
// Do not update urlbar if there was a subframe navigation
2013-04-25 05:29:24 +00:00
if ( aWebProgress . isTopLevel ) {
2013-04-23 02:47:52 +00:00
if ( ( location == "about:blank" && ( gMultiProcessBrowser || ! content . opener ) ) ||
2008-09-07 19:18:57 +00:00
location == "" ) { // Second condition is for new tabs, otherwise
// reload function is enabled until tab is refreshed.
2005-04-20 22:04:03 +00:00
this . reloadCommand . setAttribute ( "disabled" , "true" ) ;
} else {
this . reloadCommand . removeAttribute ( "disabled" ) ;
}
2004-11-30 08:23:02 +00:00
if ( gURLBar ) {
2012-12-12 09:09:49 +00:00
URLBarSetURI ( aLocationURI ) ;
2008-09-17 14:36:39 +00:00
2014-02-18 18:29:51 +00:00
BookmarkingUI . onLocationChange ( ) ;
2013-09-06 17:56:01 +00:00
SocialUI . updateState ( ) ;
2002-08-09 01:41:39 +00:00
}
2010-12-15 20:53:08 +00:00
2012-10-05 10:56:22 +00:00
// Utility functions for disabling find
2012-11-26 16:18:25 +00:00
var shouldDisableFind = function shouldDisableFind ( aDocument ) {
2012-10-05 10:56:22 +00:00
let docElt = aDocument . documentElement ;
return docElt && docElt . getAttribute ( "disablefastfind" ) == "true" ;
}
2012-11-26 16:18:25 +00:00
var disableFindCommands = function disableFindCommands ( aDisable ) {
2012-10-05 10:56:22 +00:00
let findCommands = [ document . getElementById ( "cmd_find" ) ,
document . getElementById ( "cmd_findAgain" ) ,
document . getElementById ( "cmd_findPrevious" ) ] ;
for ( let elt of findCommands ) {
if ( aDisable )
elt . setAttribute ( "disabled" , "true" ) ;
else
elt . removeAttribute ( "disabled" ) ;
}
2013-07-06 00:56:36 +00:00
}
2012-10-05 10:56:22 +00:00
2012-11-26 16:18:25 +00:00
var onContentRSChange = function onContentRSChange ( e ) {
2012-10-05 11:17:57 +00:00
if ( e . target . readyState != "interactive" && e . target . readyState != "complete" )
2012-10-05 10:56:22 +00:00
return ;
2013-02-21 05:26:35 +00:00
e . target . removeEventListener ( "readystatechange" , onContentRSChange ) ;
2012-10-05 10:56:22 +00:00
disableFindCommands ( shouldDisableFind ( e . target ) ) ;
}
2011-01-21 17:18:21 +00:00
// Disable find commands in documents that ask for them to be disabled.
2013-04-23 02:47:52 +00:00
if ( ! gMultiProcessBrowser && aLocationURI &&
2012-01-05 09:13:34 +00:00
( aLocationURI . schemeIs ( "about" ) || aLocationURI . schemeIs ( "chrome" ) ) ) {
2012-10-05 10:56:22 +00:00
// Don't need to re-enable/disable find commands for same-document location changes
// (e.g. the replaceStates in about:addons)
2013-02-08 14:51:54 +00:00
if ( ! ( aFlags & Ci . nsIWebProgressListener . LOCATION _CHANGE _SAME _DOCUMENT ) ) {
2012-10-08 08:32:16 +00:00
if ( content . document . readyState == "interactive" || content . document . readyState == "complete" )
2012-10-05 10:56:22 +00:00
disableFindCommands ( shouldDisableFind ( content . document ) ) ;
else {
content . document . addEventListener ( "readystatechange" , onContentRSChange ) ;
}
}
} else
disableFindCommands ( false ) ;
2006-11-26 22:47:46 +00:00
2013-06-29 08:25:56 +00:00
// Try not to instantiate gCustomizeMode as much as possible,
// so don't use CustomizeMode.jsm to check for URI or customizing.
let customizingURI = "about:customizing" ;
2014-01-10 15:54:48 +00:00
if ( location == customizingURI ) {
2013-06-29 08:25:56 +00:00
gCustomizeMode . enter ( ) ;
} else if ( location != customizingURI &&
2014-01-10 15:54:48 +00:00
( CustomizationHandler . isEnteringCustomizeMode ||
CustomizationHandler . isCustomizing ( ) ) ) {
2013-06-29 08:25:56 +00:00
gCustomizeMode . exit ( ) ;
}
2010-05-19 16:57:16 +00:00
}
2011-02-12 00:11:24 +00:00
UpdateBackForwardCommands ( gBrowser . webNavigation ) ;
2009-05-19 23:51:22 +00:00
2013-01-31 21:52:31 +00:00
gGestureSupport . restoreRotationState ( ) ;
2006-11-01 18:07:51 +00:00
// See bug 358202, when tabs are switched during a drag operation,
// timers don't fire on windows (bug 203573)
2008-09-07 19:18:57 +00:00
if ( aRequest )
setTimeout ( function ( ) { XULBrowserWindow . asyncUpdateUI ( ) ; } , 0 ) ;
2006-11-01 18:07:51 +00:00
else
this . asyncUpdateUI ( ) ;
2014-01-27 16:45:28 +00:00
# ifdef MOZ _CRASHREPORTER
if ( aLocationURI ) {
let uri = aLocationURI . clone ( ) ;
try {
// If the current URI contains a username/password, remove it.
uri . userPass = "" ;
} catch ( ex ) { /* Ignore failures on about: URIs. */ }
try {
2014-01-31 02:53:35 +00:00
gCrashReporter . annotateCrashReport ( "URL" , uri . spec ) ;
2014-01-27 16:45:28 +00:00
} catch ( ex if ex . result == Components . results . NS _ERROR _NOT _INITIALIZED ) {
// Don't make noise when the crash reporter is built but not enabled.
}
}
# endif
2006-03-09 02:08:45 +00:00
} ,
2010-03-24 21:22:04 +00:00
2010-09-16 08:40:32 +00:00
asyncUpdateUI : function ( ) {
2006-03-09 02:08:45 +00:00
FeedHandler . updateFeeds ( ) ;
2002-08-09 01:41:39 +00:00
} ,
2013-05-14 18:20:45 +00:00
// Left here for add-on compatibility, see bug 752434
hideChromeForLocation : function ( ) { } ,
2011-02-04 00:47:18 +00:00
2010-09-16 08:40:32 +00:00
onStatusChange : function ( aWebProgress , aRequest , aStatus , aMessage ) {
2002-08-09 01:41:39 +00:00
this . status = aMessage ;
2011-01-28 13:35:49 +00:00
this . updateStatusField ( ) ;
2002-08-09 01:41:39 +00:00
} ,
2007-09-27 15:34:01 +00:00
// Properties used to cache security state used to update the UI
_state : null ,
2013-07-15 15:58:09 +00:00
_lastLocation : null ,
2007-09-27 15:34:01 +00:00
2010-09-16 08:40:32 +00:00
onSecurityChange : function ( aWebProgress , aRequest , aState ) {
2007-09-27 15:34:01 +00:00
// Don't need to do anything if the data we use to update the UI hasn't
// changed
2013-07-15 15:58:09 +00:00
let uri = gBrowser . currentURI ;
let spec = uri . spec ;
2007-09-27 15:34:01 +00:00
if ( this . _state == aState &&
2013-07-15 15:58:09 +00:00
this . _lastLocation == spec )
2007-09-27 15:34:01 +00:00
return ;
this . _state = aState ;
2013-07-15 15:58:09 +00:00
this . _lastLocation = spec ;
2007-09-27 15:34:01 +00:00
// aState is defined as a bitmask that may be extended in the future.
// We filter out any unknown bits before testing for known values.
const wpl = Components . interfaces . nsIWebProgressListener ;
2007-07-23 11:03:22 +00:00
const wpl _security _bits = wpl . STATE _IS _SECURE |
wpl . STATE _IS _BROKEN |
2012-11-11 04:49:29 +00:00
wpl . STATE _IS _INSECURE ;
2008-09-07 19:18:57 +00:00
var level ;
2007-07-23 11:03:22 +00:00
2007-09-27 15:34:01 +00:00
switch ( this . _state & wpl _security _bits ) {
2012-11-11 04:49:29 +00:00
case wpl . STATE _IS _SECURE :
2007-09-27 15:34:01 +00:00
level = "high" ;
2002-08-09 01:41:39 +00:00
break ;
case wpl . STATE _IS _BROKEN :
2007-09-27 15:34:01 +00:00
level = "broken" ;
2002-08-09 01:41:39 +00:00
break ;
}
2007-09-27 15:34:01 +00:00
if ( level ) {
2008-11-18 08:10:54 +00:00
// We don't style the Location Bar based on the the 'level' attribute
// anymore, but still set it for third-party themes.
if ( gURLBar )
gURLBar . setAttribute ( "level" , level ) ;
2007-09-27 15:34:01 +00:00
} else {
2008-11-18 08:10:54 +00:00
if ( gURLBar )
gURLBar . removeAttribute ( "level" ) ;
2007-09-27 15:34:01 +00:00
}
2008-03-28 18:05:46 +00:00
try {
2013-07-10 02:45:07 +00:00
uri = Services . uriFixup . createExposableURI ( uri ) ;
} catch ( e ) { }
gIdentityHandler . checkIdentity ( this . _state , uri ) ;
2002-08-09 01:41:39 +00:00
} ,
2006-03-23 03:31:18 +00:00
// simulate all change notifications after switching tabs
2010-09-16 06:09:27 +00:00
onUpdateCurrentBrowser : function XWB _onUpdateCurrentBrowser ( aStateFlags , aStatus , aMessage , aTotalProgress ) {
2009-03-01 11:22:44 +00:00
if ( FullZoom . updateBackgroundTabs )
2009-08-02 17:53:01 +00:00
FullZoom . onLocationChange ( gBrowser . currentURI , true ) ;
2013-12-17 18:43:50 +00:00
CombinedBackForward . setForwardButtonOcclusion ( ! gBrowser . webProgress . canGoForward ) ;
2006-03-23 03:31:18 +00:00
var nsIWebProgressListener = Components . interfaces . nsIWebProgressListener ;
var loadingDone = aStateFlags & nsIWebProgressListener . STATE _STOP ;
2010-05-23 19:26:15 +00:00
// use a pseudo-object instead of a (potentially nonexistent) channel for getting
2006-03-23 03:31:18 +00:00
// a correct error message - and make sure that the UI is always either in
// loading (STATE_START) or done (STATE_STOP) mode
this . onStateChange (
gBrowser . webProgress ,
{ URI : gBrowser . currentURI } ,
loadingDone ? nsIWebProgressListener . STATE _STOP : nsIWebProgressListener . STATE _START ,
aStatus
) ;
// status message and progress value are undefined if we're done with loading
if ( loadingDone )
return ;
this . onStatusChange ( gBrowser . webProgress , null , 0 , aMessage ) ;
2004-11-30 08:23:02 +00:00
}
2010-01-05 07:28:46 +00:00
} ;
2011-02-03 06:48:39 +00:00
var LinkTargetDisplay = {
2011-02-08 19:16:37 +00:00
get DELAY _SHOW ( ) {
delete this . DELAY _SHOW ;
return this . DELAY _SHOW = Services . prefs . getIntPref ( "browser.overlink-delay" ) ;
} ,
2011-09-27 07:51:56 +00:00
DELAY _HIDE : 250 ,
2011-02-03 06:48:39 +00:00
_timer : 0 ,
get _isVisible ( ) XULBrowserWindow . statusTextField . label != "" ,
update : function ( ) {
clearTimeout ( this . _timer ) ;
window . removeEventListener ( "mousemove" , this , true ) ;
if ( ! XULBrowserWindow . overLink ) {
if ( XULBrowserWindow . hideOverLinkImmediately )
this . _hide ( ) ;
else
this . _timer = setTimeout ( this . _hide . bind ( this ) , this . DELAY _HIDE ) ;
return ;
}
if ( this . _isVisible ) {
XULBrowserWindow . updateStatusField ( ) ;
} else {
// Let the display appear when the mouse doesn't move within the delay
this . _showDelayed ( ) ;
window . addEventListener ( "mousemove" , this , true ) ;
}
} ,
handleEvent : function ( event ) {
switch ( event . type ) {
case "mousemove" :
// Restart the delay since the mouse was moved
clearTimeout ( this . _timer ) ;
this . _showDelayed ( ) ;
break ;
}
} ,
_showDelayed : function ( ) {
this . _timer = setTimeout ( function ( self ) {
XULBrowserWindow . updateStatusField ( ) ;
window . removeEventListener ( "mousemove" , self , true ) ;
} , this . DELAY _SHOW , this ) ;
} ,
_hide : function ( ) {
clearTimeout ( this . _timer ) ;
XULBrowserWindow . updateStatusField ( ) ;
}
} ;
2013-12-17 18:43:50 +00:00
let CombinedBackForward = {
init : function ( ) {
this . forwardButton = document . getElementById ( "forward-button" ) ;
// Add a transition listener to the url bar to hide the forward button
// when necessary
if ( gURLBar )
gURLBar . addEventListener ( "transitionend" , this ) ;
// On startup, or if the user customizes, our listener isn't attached,
// and no transitions fire anyway, so we need to make sure we've hidden the
// button if necessary:
if ( this . forwardButton && this . forwardButton . hasAttribute ( "disabled" ) ) {
this . setForwardButtonOcclusion ( true ) ;
}
} ,
uninit : function ( ) {
if ( gURLBar )
gURLBar . removeEventListener ( "transitionend" , this ) ;
} ,
handleEvent : function ( aEvent ) {
if ( aEvent . type == "transitionend" &&
( aEvent . propertyName == "margin-left" || aEvent . propertyName == "margin-right" ) &&
this . forwardButton . hasAttribute ( "disabled" ) ) {
this . setForwardButtonOcclusion ( true ) ;
}
} ,
setForwardButtonOcclusion : function ( shouldBeOccluded ) {
if ( ! this . forwardButton )
return ;
let hasAttribute = this . forwardButton . hasAttribute ( "occluded-by-urlbar" ) ;
if ( shouldBeOccluded && ! hasAttribute )
this . forwardButton . setAttribute ( "occluded-by-urlbar" , "true" ) ;
else if ( ! shouldBeOccluded && hasAttribute )
this . forwardButton . removeAttribute ( "occluded-by-urlbar" ) ;
}
}
2010-01-05 07:28:46 +00:00
var CombinedStopReload = {
init : function ( ) {
if ( this . _initialized )
return ;
2013-07-18 16:46:28 +00:00
let reload = document . getElementById ( "urlbar-reload-button" ) ;
let stop = document . getElementById ( "urlbar-stop-button" ) ;
2010-09-03 02:20:12 +00:00
if ( ! stop || ! reload || reload . nextSibling != stop )
2010-01-05 07:28:46 +00:00
return ;
this . _initialized = true ;
if ( XULBrowserWindow . stopCommand . getAttribute ( "disabled" ) != "true" )
reload . setAttribute ( "displaystop" , "true" ) ;
stop . addEventListener ( "click" , this , false ) ;
2010-08-20 09:50:09 +00:00
this . reload = reload ;
2010-09-03 02:20:12 +00:00
this . stop = stop ;
2010-01-05 07:28:46 +00:00
} ,
uninit : function ( ) {
if ( ! this . _initialized )
return ;
this . _cancelTransition ( ) ;
this . _initialized = false ;
this . stop . removeEventListener ( "click" , this , false ) ;
this . reload = null ;
this . stop = null ;
} ,
handleEvent : function ( event ) {
// the only event we listen to is "click" on the stop button
if ( event . button == 0 &&
! this . stop . disabled )
this . _stopClicked = true ;
} ,
switchToStop : function ( ) {
if ( ! this . _initialized )
return ;
this . _cancelTransition ( ) ;
this . reload . setAttribute ( "displaystop" , "true" ) ;
} ,
switchToReload : function ( aDelay ) {
if ( ! this . _initialized )
return ;
2010-10-13 21:56:30 +00:00
this . reload . removeAttribute ( "displaystop" ) ;
2010-01-05 07:28:46 +00:00
if ( ! aDelay || this . _stopClicked ) {
this . _stopClicked = false ;
this . _cancelTransition ( ) ;
2010-10-13 21:56:30 +00:00
this . reload . disabled = XULBrowserWindow . reloadCommand
. getAttribute ( "disabled" ) == "true" ;
2010-01-05 07:28:46 +00:00
return ;
}
if ( this . _timer )
return ;
2010-10-13 21:56:30 +00:00
// Temporarily disable the reload button to prevent the user from
// accidentally reloading the page when intending to click the stop button
this . reload . disabled = true ;
2010-01-05 07:28:46 +00:00
this . _timer = setTimeout ( function ( self ) {
self . _timer = 0 ;
2010-10-13 21:56:30 +00:00
self . reload . disabled = XULBrowserWindow . reloadCommand
. getAttribute ( "disabled" ) == "true" ;
2010-01-05 07:28:46 +00:00
} , 650 , this ) ;
} ,
_cancelTransition : function ( ) {
if ( this . _timer ) {
clearTimeout ( this . _timer ) ;
this . _timer = 0 ;
}
}
} ;
2004-11-30 08:23:02 +00:00
2008-11-18 16:03:34 +00:00
var TabsProgressListener = {
2010-07-09 23:44:55 +00:00
onStateChange : function ( aBrowser , aWebProgress , aRequest , aStateFlags , aStatus ) {
2012-09-27 16:26:31 +00:00
// Collect telemetry data about tab load times.
2013-04-25 05:29:24 +00:00
if ( aWebProgress . isTopLevel ) {
2013-02-18 18:23:50 +00:00
if ( aStateFlags & Ci . nsIWebProgressListener . STATE _IS _WINDOW ) {
if ( aStateFlags & Ci . nsIWebProgressListener . STATE _START )
TelemetryStopwatch . start ( "FX_PAGE_LOAD_MS" , aBrowser ) ;
else if ( aStateFlags & Ci . nsIWebProgressListener . STATE _STOP )
TelemetryStopwatch . finish ( "FX_PAGE_LOAD_MS" , aBrowser ) ;
} else if ( aStateFlags & Ci . nsIWebProgressListener . STATE _STOP &&
aStatus == Cr . NS _BINDING _ABORTED ) {
TelemetryStopwatch . cancel ( "FX_PAGE_LOAD_MS" , aBrowser ) ;
}
2012-09-27 16:26:31 +00:00
}
2010-08-19 23:06:07 +00:00
// Attach a listener to watch for "click" events bubbling up from error
2013-08-22 23:52:18 +00:00
// pages and other similar pages (like about:newtab). This lets us fix bugs
// like 401575 which require error page UI to do privileged things, without
// letting error pages have any privilege themselves.
2010-08-19 23:06:07 +00:00
// We can't look for this during onLocationChange since at that point the
// document URI is not yet the about:-uri of the error page.
2013-08-22 23:52:18 +00:00
let isRemoteBrowser = aBrowser . isRemoteBrowser ;
// We check isRemoteBrowser here to avoid requesting the doc CPOW
let doc = isRemoteBrowser ? null : aWebProgress . DOMWindow . document ;
if ( ! isRemoteBrowser &&
2013-04-23 02:47:52 +00:00
aStateFlags & Ci . nsIWebProgressListener . STATE _STOP &&
2012-03-15 22:58:09 +00:00
Components . isSuccessCode ( aStatus ) &&
2013-02-07 21:27:40 +00:00
doc . documentURI . startsWith ( "about:" ) &&
2013-03-13 19:15:20 +00:00
! doc . documentURI . toLowerCase ( ) . startsWith ( "about:blank" ) &&
2013-07-05 20:55:00 +00:00
! doc . documentURI . toLowerCase ( ) . startsWith ( "about:home" ) &&
2013-02-07 21:27:40 +00:00
! doc . documentElement . hasAttribute ( "hasBrowserHandlers" ) ) {
// STATE_STOP may be received twice for documents, thus store an
// attribute to ensure handling it just once.
doc . documentElement . setAttribute ( "hasBrowserHandlers" , "true" ) ;
2012-08-10 03:43:54 +00:00
aBrowser . addEventListener ( "click" , BrowserOnClick , true ) ;
2012-06-13 22:44:28 +00:00
aBrowser . addEventListener ( "pagehide" , function onPageHide ( event ) {
if ( event . target . defaultView . frameElement )
return ;
2012-08-10 03:43:54 +00:00
aBrowser . removeEventListener ( "click" , BrowserOnClick , true ) ;
2012-04-16 22:35:34 +00:00
aBrowser . removeEventListener ( "pagehide" , onPageHide , true ) ;
2013-06-20 19:53:36 +00:00
if ( event . target . documentElement )
event . target . documentElement . removeAttribute ( "hasBrowserHandlers" ) ;
2010-08-19 23:06:07 +00:00
} , true ) ;
2013-09-12 19:24:10 +00:00
# ifdef MOZ _CRASHREPORTER
if ( doc . documentURI . startsWith ( "about:tabcrashed" ) )
TabCrashReporter . onAboutTabCrashedLoad ( aBrowser ) ;
# endif
2010-08-19 23:06:07 +00:00
}
} ,
2011-11-10 14:01:11 +00:00
onLocationChange : function ( aBrowser , aWebProgress , aRequest , aLocationURI ,
aFlags ) {
2013-03-31 13:47:04 +00:00
// Filter out location changes caused by anchor navigation
// or history.push/pop/replaceState.
if ( aFlags & Ci . nsIWebProgressListener . LOCATION _CHANGE _SAME _DOCUMENT )
return ;
2013-11-01 05:13:43 +00:00
// Filter out location changes in sub documents.
if ( ! aWebProgress . isTopLevel )
return ;
2013-03-31 13:47:04 +00:00
// Only need to call locationChange if the PopupNotifications object
// for this window has already been initialized (i.e. its getter no
// longer exists)
if ( ! Object . getOwnPropertyDescriptor ( window , "PopupNotifications" ) . get )
PopupNotifications . locationChange ( aBrowser ) ;
gBrowser . getNotificationBox ( aBrowser ) . removeTransientNotifications ( ) ;
2013-11-01 05:13:43 +00:00
FullZoom . onLocationChange ( aLocationURI , false , aBrowser ) ;
2008-11-18 16:03:34 +00:00
} ,
2010-03-24 21:22:04 +00:00
2008-11-18 16:03:34 +00:00
onRefreshAttempted : function ( aBrowser , aWebProgress , aURI , aDelay , aSameURI ) {
if ( gPrefService . getBoolPref ( "accessibility.blockautorefresh" ) ) {
let brandBundle = document . getElementById ( "bundle_brand" ) ;
let brandShortName = brandBundle . getString ( "brandShortName" ) ;
let refreshButtonText =
gNavigatorBundle . getString ( "refreshBlocked.goButton" ) ;
let refreshButtonAccesskey =
gNavigatorBundle . getString ( "refreshBlocked.goButton.accesskey" ) ;
let message =
gNavigatorBundle . getFormattedString ( aSameURI ? "refreshBlocked.refreshLabel"
: "refreshBlocked.redirectLabel" ,
[ brandShortName ] ) ;
let docShell = aWebProgress . DOMWindow
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShell ) ;
let notificationBox = gBrowser . getNotificationBox ( aBrowser ) ;
let notification = notificationBox . getNotificationWithValue ( "refresh-blocked" ) ;
if ( notification ) {
notification . label = message ;
notification . refreshURI = aURI ;
notification . delay = aDelay ;
notification . docShell = docShell ;
} else {
let buttons = [ {
label : refreshButtonText ,
accessKey : refreshButtonAccesskey ,
callback : function ( aNotification , aButton ) {
var refreshURI = aNotification . docShell
. QueryInterface ( Ci . nsIRefreshURI ) ;
refreshURI . forceRefreshURI ( aNotification . refreshURI ,
aNotification . delay , true ) ;
}
} ] ;
notification =
notificationBox . appendNotification ( message , "refresh-blocked" ,
"chrome://browser/skin/Info.png" ,
notificationBox . PRIORITY _INFO _MEDIUM ,
buttons ) ;
notification . refreshURI = aURI ;
notification . delay = aDelay ;
notification . docShell = docShell ;
}
return false ;
}
return true ;
}
}
2009-10-06 15:58:00 +00:00
function nsBrowserAccess ( ) { }
2004-11-30 08:23:02 +00:00
2009-10-06 15:58:00 +00:00
nsBrowserAccess . prototype = {
QueryInterface : XPCOMUtils . generateQI ( [ Ci . nsIBrowserDOMWindow , Ci . nsISupports ] ) ,
2004-11-30 08:23:02 +00:00
2013-08-08 21:01:45 +00:00
_openURIInNewTab : function ( aURI , aOpener , aIsExternal ) {
let win , needToFocusWin ;
// try the current window. if we're in a popup, fall back on the most recent browser window
if ( window . toolbar . visible )
win = window ;
else {
let isPrivate = PrivateBrowsingUtils . isWindowPrivate ( aOpener || window ) ;
win = RecentWindow . getMostRecentBrowserWindow ( { private : isPrivate } ) ;
needToFocusWin = true ;
}
if ( ! win ) {
// we couldn't find a suitable window, a new one needs to be opened.
return null ;
}
if ( aIsExternal && ( ! aURI || aURI . spec == "about:blank" ) ) {
win . BrowserOpenTab ( ) ; // this also focuses the location bar
win . focus ( ) ;
return win . gBrowser . selectedBrowser ;
}
let loadInBackground = gPrefService . getBoolPref ( "browser.tabs.loadDivertedInBackground" ) ;
let referrer = aOpener ? makeURI ( aOpener . location . href ) : null ;
let tab = win . gBrowser . loadOneTab ( aURI ? aURI . spec : "about:blank" , {
referrerURI : referrer ,
fromExternal : aIsExternal ,
inBackground : loadInBackground } ) ;
let browser = win . gBrowser . getBrowserForTab ( tab ) ;
if ( needToFocusWin || ( ! loadInBackground && aIsExternal ) )
win . focus ( ) ;
return browser ;
} ,
2009-10-06 15:58:00 +00:00
openURI : function ( aURI , aOpener , aWhere , aContext ) {
2004-11-30 08:23:02 +00:00
var newWindow = null ;
2007-03-25 03:41:16 +00:00
var isExternal = ( aContext == Ci . nsIBrowserDOMWindow . OPEN _EXTERNAL ) ;
2005-07-07 09:45:47 +00:00
if ( isExternal && aURI && aURI . schemeIs ( "chrome" ) ) {
dump ( "use -chrome command-line option to load external chrome urls\n" ) ;
return null ;
}
2011-10-08 08:36:11 +00:00
if ( aWhere == Ci . nsIBrowserDOMWindow . OPEN _DEFAULTWINDOW ) {
if ( isExternal &&
gPrefService . prefHasUserValue ( "browser.link.open_newwindow.override.external" ) )
aWhere = gPrefService . getIntPref ( "browser.link.open_newwindow.override.external" ) ;
else
aWhere = gPrefService . getIntPref ( "browser.link.open_newwindow" ) ;
}
2008-10-12 17:36:01 +00:00
switch ( aWhere ) {
2007-03-25 03:41:16 +00:00
case Ci . nsIBrowserDOMWindow . OPEN _NEWWINDOW :
2007-12-14 17:27:31 +00:00
// FIXME: Bug 408379. So how come this doesn't send the
// referrer like the other loads do?
2012-06-14 18:29:31 +00:00
var url = aURI ? aURI . spec : "about:blank" ;
2008-07-03 20:30:24 +00:00
// Pass all params to openDialog to ensure that "url" isn't passed through
// loadOneOrMoreURIs, which splits based on "|"
newWindow = openDialog ( getBrowserURL ( ) , "_blank" , "all,dialog=no" , url , null , null , null ) ;
2004-11-30 08:23:02 +00:00
break ;
2007-03-25 03:41:16 +00:00
case Ci . nsIBrowserDOMWindow . OPEN _NEWTAB :
2013-08-08 21:01:45 +00:00
let browser = this . _openURIInNewTab ( aURI , aOpener , isExternal ) ;
2013-09-16 09:21:46 +00:00
if ( browser )
newWindow = browser . contentWindow ;
2004-11-30 08:23:02 +00:00
break ;
default : // OPEN_CURRENTWINDOW or an illegal value
2009-09-09 07:50:07 +00:00
newWindow = content ;
if ( aURI ) {
let referrer = aOpener ? makeURI ( aOpener . location . href ) : null ;
2010-06-08 20:13:55 +00:00
let loadflags = isExternal ?
Ci . nsIWebNavigation . LOAD _FLAGS _FROM _EXTERNAL :
Ci . nsIWebNavigation . LOAD _FLAGS _NONE ;
2010-01-02 08:28:09 +00:00
gBrowser . loadURIWithFlags ( aURI . spec , loadflags , referrer , null , null ) ;
2004-11-30 08:23:02 +00:00
}
2009-09-09 07:50:07 +00:00
if ( ! gPrefService . getBoolPref ( "browser.tabs.loadDivertedInBackground" ) )
2012-09-19 10:59:26 +00:00
window . focus ( ) ;
2004-11-30 08:23:02 +00:00
}
return newWindow ;
2004-12-07 16:08:48 +00:00
} ,
2013-08-08 21:01:45 +00:00
openURIInFrame : function browser _openURIInFrame ( aURI , aOpener , aWhere , aContext ) {
if ( aWhere != Ci . nsIBrowserDOMWindow . OPEN _NEWTAB ) {
dump ( "Error: openURIInFrame can only open in new tabs" ) ;
return null ;
}
var isExternal = ( aContext == Ci . nsIBrowserDOMWindow . OPEN _EXTERNAL ) ;
let browser = this . _openURIInNewTab ( aURI , aOpener , isExternal ) ;
2013-09-16 09:21:46 +00:00
if ( browser )
return browser . QueryInterface ( Ci . nsIFrameLoaderOwner ) ;
return null ;
2013-08-08 21:01:45 +00:00
} ,
2009-10-06 15:58:00 +00:00
isTabContentWindow : function ( aWindow ) {
2008-09-02 12:15:06 +00:00
return gBrowser . browsers . some ( function ( browser ) browser . contentWindow == aWindow ) ;
2013-05-08 21:16:46 +00:00
} ,
get contentWindow ( ) {
return gBrowser . contentWindow ;
2002-08-09 01:41:39 +00:00
}
}
2013-11-21 21:59:49 +00:00
function getTogglableToolbars ( ) {
let toolbarNodes = Array . slice ( gNavToolbox . childNodes ) ;
toolbarNodes = toolbarNodes . concat ( gNavToolbox . externalToolbars ) ;
toolbarNodes = toolbarNodes . filter ( node => node . getAttribute ( "toolbarname" ) ) ;
return toolbarNodes ;
}
2010-08-19 18:59:20 +00:00
function onViewToolbarsPopupShowing ( aEvent , aInsertPoint ) {
2002-09-27 04:06:56 +00:00
var popup = aEvent . target ;
2010-06-13 08:20:58 +00:00
if ( popup != aEvent . currentTarget )
return ;
2002-09-27 04:06:56 +00:00
// Empty the menu
2010-10-21 08:15:48 +00:00
for ( var i = popup . childNodes . length - 1 ; i >= 0 ; -- i ) {
2002-09-27 04:06:56 +00:00
var deadItem = popup . childNodes [ i ] ;
2010-09-16 06:09:27 +00:00
if ( deadItem . hasAttribute ( "toolbarId" ) )
2002-09-27 04:06:56 +00:00
popup . removeChild ( deadItem ) ;
}
2005-06-14 10:15:58 +00:00
2010-08-19 18:59:20 +00:00
var firstMenuItem = aInsertPoint || popup . firstChild ;
2005-06-14 10:15:58 +00:00
2013-11-21 21:59:49 +00:00
let toolbarNodes = getTogglableToolbars ( ) ;
2010-10-21 08:15:48 +00:00
2012-08-21 16:56:07 +00:00
for ( let toolbar of toolbarNodes ) {
2013-11-21 21:59:49 +00:00
let menuItem = document . createElement ( "menuitem" ) ;
let hidingAttribute = toolbar . getAttribute ( "type" ) == "menubar" ?
"autohide" : "collapsed" ;
menuItem . setAttribute ( "id" , "toggle_" + toolbar . id ) ;
menuItem . setAttribute ( "toolbarId" , toolbar . id ) ;
menuItem . setAttribute ( "type" , "checkbox" ) ;
menuItem . setAttribute ( "label" , toolbar . getAttribute ( "toolbarname" ) ) ;
menuItem . setAttribute ( "checked" , toolbar . getAttribute ( hidingAttribute ) != "true" ) ;
menuItem . setAttribute ( "accesskey" , toolbar . getAttribute ( "accesskey" ) ) ;
if ( popup . id != "toolbar-context-menu" )
menuItem . setAttribute ( "key" , toolbar . getAttribute ( "key" ) ) ;
popup . insertBefore ( menuItem , firstMenuItem ) ;
menuItem . addEventListener ( "command" , onViewToolbarCommand , false ) ;
2012-08-21 16:56:07 +00:00
}
2013-11-22 04:09:34 +00:00
2013-11-28 14:53:02 +00:00
2013-12-17 21:21:37 +00:00
let moveToPanel = popup . querySelector ( ".customize-context-moveToPanel" ) ;
2013-11-28 14:53:02 +00:00
let removeFromToolbar = popup . querySelector ( ".customize-context-removeFromToolbar" ) ;
2013-12-17 21:21:37 +00:00
// View -> Toolbars menu doesn't have the moveToPanel or removeFromToolbar items.
if ( ! moveToPanel || ! removeFromToolbar ) {
2013-11-28 14:53:02 +00:00
return ;
}
2013-12-05 11:06:43 +00:00
// triggerNode can be a nested child element of a toolbaritem.
let toolbarItem = popup . triggerNode ;
2013-11-22 04:09:34 +00:00
if ( toolbarItem && toolbarItem . localName == "toolbarpaletteitem" ) {
toolbarItem = toolbarItem . firstChild ;
2014-02-25 00:14:41 +00:00
} else if ( toolbarItem && toolbarItem . localName != "toolbar" ) {
2013-11-22 04:09:34 +00:00
while ( toolbarItem && toolbarItem . parentNode ) {
let parent = toolbarItem . parentNode ;
if ( ( parent . classList && parent . classList . contains ( "customization-target" ) ) ||
2014-02-12 17:32:23 +00:00
parent . getAttribute ( "overflowfortoolbar" ) || // Needs to work in the overflow list as well.
2013-11-22 04:09:34 +00:00
parent . localName == "toolbarpaletteitem" ||
parent . localName == "toolbar" )
break ;
toolbarItem = parent ;
}
2014-02-25 00:14:41 +00:00
} else {
toolbarItem = null ;
2013-11-22 04:09:34 +00:00
}
// Right-clicking on an empty part of the tabstrip will exit
// the above loop with toolbarItem being the xul:document.
2013-11-28 14:53:02 +00:00
// That has no parentNode, and we should disable the items in
// this case.
let movable = toolbarItem && toolbarItem . parentNode &&
CustomizableUI . isWidgetRemovable ( toolbarItem ) ;
2013-11-22 04:09:34 +00:00
if ( movable ) {
2013-12-17 21:21:37 +00:00
moveToPanel . removeAttribute ( "disabled" ) ;
2013-11-22 04:09:34 +00:00
removeFromToolbar . removeAttribute ( "disabled" ) ;
} else {
2013-12-17 21:21:37 +00:00
moveToPanel . setAttribute ( "disabled" , true ) ;
2013-11-22 04:09:34 +00:00
removeFromToolbar . setAttribute ( "disabled" , true ) ;
}
2002-09-27 04:06:56 +00:00
}
2010-06-13 08:20:58 +00:00
function onViewToolbarCommand ( aEvent ) {
2010-09-16 06:09:27 +00:00
var toolbarId = aEvent . originalTarget . getAttribute ( "toolbarId" ) ;
var toolbar = document . getElementById ( toolbarId ) ;
var isVisible = aEvent . originalTarget . getAttribute ( "checked" ) == "true" ;
setToolbarVisibility ( toolbar , isVisible ) ;
2010-07-16 19:03:04 +00:00
}
2010-09-16 06:09:27 +00:00
function setToolbarVisibility ( toolbar , isVisible ) {
2014-02-18 17:07:27 +00:00
let hidingAttribute ;
if ( toolbar . getAttribute ( "type" ) == "menubar" ) {
hidingAttribute = "autohide" ;
# ifdef MOZ _WIDGET _GTK
Services . prefs . setBoolPref ( "ui.key.menuAccessKeyFocuses" , ! isVisible ) ;
# endif
} else {
hidingAttribute = "collapsed" ;
}
2003-08-10 04:28:02 +00:00
2010-09-16 06:09:27 +00:00
toolbar . setAttribute ( hidingAttribute , ! isVisible ) ;
2009-06-13 06:08:20 +00:00
document . persist ( toolbar . id , hidingAttribute ) ;
2013-07-10 12:05:35 +00:00
let eventParams = {
detail : {
visible : isVisible
} ,
bubbles : true
} ;
let event = new CustomEvent ( "toolbarvisibilitychange" , eventParams ) ;
toolbar . dispatchEvent ( event ) ;
2010-06-13 08:20:58 +00:00
2010-07-16 19:03:04 +00:00
PlacesToolbarHelper . init ( ) ;
2013-05-10 15:19:48 +00:00
BookmarkingUI . onToolbarVisibilityChange ( ) ;
2011-01-17 14:35:32 +00:00
gBrowser . updateWindowResizers ( ) ;
2010-04-06 06:34:27 +00:00
}
2011-01-07 20:28:02 +00:00
var TabsInTitlebar = {
init : function ( ) {
# ifdef CAN _DRAW _IN _TITLEBAR
this . _readPref ( ) ;
Services . prefs . addObserver ( this . _prefName , this , false ) ;
2013-02-14 15:59:13 +00:00
// We need to update the appearance of the titlebar when the menu changes
// from the active to the inactive state. We can't, however, rely on
// DOMMenuBarInactive, because the menu fires this event and then removes
// the inactive attribute after an event-loop spin.
//
// Because updating the appearance involves sampling the heights and margins
// of various elements, it's important that the layout be more or less
// settled before updating the titlebar. So instead of listening to
// DOMMenuBarActive and DOMMenuBarInactive, we use a MutationObserver to
// watch the "invalid" attribute directly.
let menu = document . getElementById ( "toolbar-menubar" ) ;
this . _menuObserver = new MutationObserver ( this . _onMenuMutate ) ;
this . _menuObserver . observe ( menu , { attributes : true } ) ;
2013-08-19 15:19:31 +00:00
2013-11-13 20:56:42 +00:00
this . onAreaReset = function ( aArea ) {
if ( aArea == CustomizableUI . AREA _TABSTRIP || aArea == CustomizableUI . AREA _MENUBAR )
this . _update ( true ) ;
} ;
this . onWidgetAdded = this . onWidgetRemoved = function ( aWidgetId , aArea ) {
if ( aArea == CustomizableUI . AREA _TABSTRIP || aArea == CustomizableUI . AREA _MENUBAR )
this . _update ( true ) ;
} ;
CustomizableUI . addListener ( this ) ;
2011-01-07 20:28:02 +00:00
this . _initialized = true ;
# endif
} ,
allowedBy : function ( condition , allow ) {
# ifdef CAN _DRAW _IN _TITLEBAR
if ( allow ) {
if ( condition in this . _disallowed ) {
delete this . _disallowed [ condition ] ;
2013-02-14 15:59:13 +00:00
this . _update ( true ) ;
2011-01-07 20:28:02 +00:00
}
} else {
if ( ! ( condition in this . _disallowed ) ) {
this . _disallowed [ condition ] = null ;
2013-02-14 15:59:13 +00:00
this . _update ( true ) ;
2011-01-07 20:28:02 +00:00
}
}
# endif
} ,
2013-02-14 15:59:13 +00:00
updateAppearance : function updateAppearance ( aForce ) {
# ifdef CAN _DRAW _IN _TITLEBAR
this . _update ( aForce ) ;
# endif
} ,
2011-06-15 22:46:12 +00:00
get enabled ( ) {
return document . documentElement . getAttribute ( "tabsintitlebar" ) == "true" ;
} ,
2011-01-07 20:28:02 +00:00
# ifdef CAN _DRAW _IN _TITLEBAR
observe : function ( subject , topic , data ) {
if ( topic == "nsPref:changed" )
this . _readPref ( ) ;
} ,
2013-02-14 15:59:13 +00:00
_onMenuMutate : function ( aMutations ) {
for ( let mutation of aMutations ) {
if ( mutation . attributeName == "inactive" ||
mutation . attributeName == "autohide" ) {
TabsInTitlebar . _update ( true ) ;
return ;
}
}
} ,
2011-01-07 20:28:02 +00:00
_initialized : false ,
_disallowed : { } ,
_prefName : "browser.tabs.drawInTitlebar" ,
2013-02-14 15:59:13 +00:00
_lastSizeMode : null ,
2011-01-07 20:28:02 +00:00
_readPref : function ( ) {
this . allowedBy ( "pref" ,
Services . prefs . getBoolPref ( this . _prefName ) ) ;
} ,
2013-02-14 15:59:13 +00:00
_update : function ( aForce = false ) {
2013-05-16 01:11:29 +00:00
function $ ( id ) document . getElementById ( id ) ;
function rect ( ele ) ele . getBoundingClientRect ( ) ;
2013-11-01 06:18:00 +00:00
function verticalMargins ( cstyle ) parseFloat ( cstyle . marginBottom ) + parseFloat ( cstyle . marginTop ) ;
2013-05-16 01:11:29 +00:00
2011-01-20 08:36:23 +00:00
if ( ! this . _initialized || window . fullScreen )
2011-01-07 20:28:02 +00:00
return ;
let allowed = true ;
2013-02-14 15:59:13 +00:00
if ( ! aForce ) {
// _update is called on resize events, because the window is not ready
// after sizemode events. However, we only care about the event when the
// sizemode is different from the last time we updated the appearance of
// the tabs in the titlebar.
let sizemode = document . documentElement . getAttribute ( "sizemode" ) ;
if ( this . _lastSizeMode == sizemode ) {
return ;
}
this . _lastSizeMode = sizemode ;
}
2011-01-07 20:28:02 +00:00
for ( let something in this . _disallowed ) {
allowed = false ;
break ;
}
let titlebar = $ ( "titlebar" ) ;
2013-02-14 15:59:13 +00:00
let titlebarContent = $ ( "titlebar-content" ) ;
let menubar = $ ( "toolbar-menubar" ) ;
2011-01-07 20:28:02 +00:00
if ( allowed ) {
2013-02-14 15:59:13 +00:00
// We set the tabsintitlebar attribute first so that our CSS for
// tabsintitlebar manifests before we do our measurements.
document . documentElement . setAttribute ( "tabsintitlebar" , "true" ) ;
2013-09-10 14:51:53 +00:00
updateTitlebarDisplay ( ) ;
2011-03-26 12:32:51 +00:00
2013-07-04 22:03:27 +00:00
// Try to avoid reflows in this code by calculating dimensions first and
// then later set the properties affecting layout together in a batch.
2011-03-26 12:32:51 +00:00
2014-02-04 21:17:00 +00:00
// Get the full height of the tabs toolbar:
let tabsToolbar = $ ( "TabsToolbar" ) ;
let fullTabsHeight = rect ( tabsToolbar ) . height ;
2013-08-19 15:19:31 +00:00
// Buttons first:
2013-07-04 22:03:27 +00:00
let captionButtonsBoxWidth = rect ( $ ( "titlebar-buttonbox" ) ) . width ;
# ifdef XP _MACOSX
let fullscreenButtonWidth = rect ( $ ( "titlebar-fullscreen-button" ) ) . width ;
2013-08-19 15:19:31 +00:00
// No need to look up the menubar stuff on OS X:
let menuHeight = 0 ;
let fullMenuHeight = 0 ;
2013-06-12 21:42:00 +00:00
// Instead, look up the titlebar padding:
let titlebarPadding = parseInt ( window . getComputedStyle ( titlebar ) . paddingTop , 10 ) ;
2013-08-19 15:19:31 +00:00
# else
// Otherwise, get the height and margins separately for the menubar
let menuHeight = rect ( menubar ) . height ;
let menuStyles = window . getComputedStyle ( menubar ) ;
let fullMenuHeight = verticalMargins ( menuStyles ) + menuHeight ;
let tabsStyles = window . getComputedStyle ( tabsToolbar ) ;
2014-02-04 21:17:00 +00:00
fullTabsHeight += verticalMargins ( tabsStyles ) ;
# endif
2013-08-19 15:19:31 +00:00
// If the navbar overlaps the tabbar using negative margins, we need to take those into
// account so we don't overlap it
2013-11-01 06:18:00 +00:00
let navbarMarginTop = parseFloat ( window . getComputedStyle ( $ ( "nav-bar" ) ) . marginTop ) ;
2013-08-19 15:19:31 +00:00
navbarMarginTop = Math . min ( navbarMarginTop , 0 ) ;
// And get the height of what's in the titlebar:
let titlebarContentHeight = rect ( titlebarContent ) . height ;
2013-07-04 22:03:27 +00:00
// Begin setting CSS properties which will cause a reflow
2011-01-07 20:28:02 +00:00
2013-08-19 15:19:31 +00:00
// If the menubar is around (menuHeight is non-zero), try to adjust
// its full height (i.e. including margins) to match the titlebar,
// by changing the menubar's bottom padding
if ( menuHeight ) {
// Calculate the difference between the titlebar's height and that of the menubar
let menuTitlebarDelta = titlebarContentHeight - fullMenuHeight ;
let paddingBottom ;
// The titlebar is bigger:
if ( menuTitlebarDelta > 0 ) {
fullMenuHeight += menuTitlebarDelta ;
// If there is already padding on the menubar, we need to add that
// to the difference so the total padding is correct:
if ( ( paddingBottom = menuStyles . paddingBottom ) ) {
2013-11-01 06:18:00 +00:00
menuTitlebarDelta += parseFloat ( paddingBottom ) ;
2013-08-19 15:19:31 +00:00
}
menubar . style . paddingBottom = menuTitlebarDelta + "px" ;
// The menubar is bigger, but has bottom padding we can remove:
} else if ( menuTitlebarDelta < 0 && ( paddingBottom = menuStyles . paddingBottom ) ) {
2013-11-01 06:18:00 +00:00
let existingPadding = parseFloat ( paddingBottom ) ;
2013-08-19 15:19:31 +00:00
// menuTitlebarDelta is negative; work out what's left, but don't set negative padding:
let desiredPadding = Math . max ( 0 , existingPadding + menuTitlebarDelta ) ;
menubar . style . paddingBottom = desiredPadding + "px" ;
// We've changed the menu height now:
fullMenuHeight += desiredPadding - existingPadding ;
}
2013-02-14 15:59:13 +00:00
}
2011-01-07 20:28:02 +00:00
2013-02-14 15:59:13 +00:00
// Next, we calculate how much we need to stretch the titlebar down to
2013-08-19 15:19:31 +00:00
// go all the way to the bottom of the tab strip, if necessary.
let tabAndMenuHeight = fullTabsHeight + fullMenuHeight ;
if ( tabAndMenuHeight > titlebarContentHeight ) {
// We need to increase the titlebar content's outer height (ie including margins)
// to match the tab and menu height:
let extraMargin = tabAndMenuHeight - titlebarContentHeight ;
// We need to reduce the height by the amount of navbar overlap
// (this value is 0 or negative):
extraMargin += navbarMarginTop ;
2013-06-12 21:42:00 +00:00
// On non-OSX, we can just use bottom margin:
# ifndef XP _MACOSX
2013-08-19 15:19:31 +00:00
titlebarContent . style . marginBottom = extraMargin + "px" ;
2013-06-12 21:42:00 +00:00
# endif
2013-08-19 15:19:31 +00:00
titlebarContentHeight += extraMargin ;
}
2011-01-20 15:38:26 +00:00
2013-08-19 15:19:31 +00:00
// Then we bring up the titlebar by the same amount, but we add any negative margin:
titlebar . style . marginBottom = "-" + titlebarContentHeight + "px" ;
2011-01-20 15:38:26 +00:00
2013-08-19 15:19:31 +00:00
// Finally, size the placeholders:
# ifdef XP _MACOSX
this . _sizePlaceholder ( "fullscreen-button" , fullscreenButtonWidth ) ;
# endif
this . _sizePlaceholder ( "caption-buttons" , captionButtonsBoxWidth ) ;
2013-02-14 15:59:13 +00:00
if ( ! this . _draghandles ) {
this . _draghandles = { } ;
2011-01-20 15:38:26 +00:00
let tmp = { } ;
Components . utils . import ( "resource://gre/modules/WindowDraggingUtils.jsm" , tmp ) ;
2013-02-14 15:59:13 +00:00
let mouseDownCheck = function ( ) {
2011-06-15 22:46:12 +00:00
return ! this . _dragBindingAlive && TabsInTitlebar . enabled ;
2011-01-20 15:38:26 +00:00
} ;
2013-02-14 15:59:13 +00:00
this . _draghandles . tabsToolbar = new tmp . WindowDraggingElement ( tabsToolbar ) ;
this . _draghandles . tabsToolbar . mouseDownCheck = mouseDownCheck ;
this . _draghandles . navToolbox = new tmp . WindowDraggingElement ( gNavToolbox ) ;
this . _draghandles . navToolbox . mouseDownCheck = mouseDownCheck ;
2011-01-20 15:38:26 +00:00
}
2011-01-07 20:28:02 +00:00
} else {
2011-06-15 22:46:12 +00:00
document . documentElement . removeAttribute ( "tabsintitlebar" ) ;
2013-09-10 14:51:53 +00:00
updateTitlebarDisplay ( ) ;
2011-01-07 20:28:02 +00:00
2013-08-19 15:19:31 +00:00
// Reset the margins and padding that might have been modified:
2014-02-04 21:17:00 +00:00
titlebarContent . style . marginTop = "" ;
2013-08-19 15:19:31 +00:00
titlebarContent . style . marginBottom = "" ;
2011-01-07 20:28:02 +00:00
titlebar . style . marginBottom = "" ;
2013-08-19 15:19:31 +00:00
menubar . style . paddingBottom = "" ;
2011-01-07 20:28:02 +00:00
}
} ,
_sizePlaceholder : function ( type , width ) {
Array . forEach ( document . querySelectorAll ( ".titlebar-placeholder[type='" + type + "']" ) ,
function ( node ) { node . width = width ; } ) ;
} ,
# endif
uninit : function ( ) {
# ifdef CAN _DRAW _IN _TITLEBAR
this . _initialized = false ;
Services . prefs . removeObserver ( this . _prefName , this ) ;
2013-02-14 15:59:13 +00:00
this . _menuObserver . disconnect ( ) ;
2013-11-13 20:56:42 +00:00
CustomizableUI . removeListener ( this ) ;
2011-01-07 20:28:02 +00:00
# endif
}
} ;
2010-11-05 08:26:46 +00:00
# ifdef CAN _DRAW _IN _TITLEBAR
2013-05-06 15:36:17 +00:00
function updateTitlebarDisplay ( ) {
2014-02-04 21:17:00 +00:00
# ifdef XP _MACOSX
// OS X and the other platforms differ enough to necessitate this kind of
// special-casing. Like the other platforms where we CAN_DRAW_IN_TITLEBAR,
// we draw in the OS X titlebar when putting the tabs up there. However, OS X
// also draws in the titlebar when a lightweight theme is applied, regardless
// of whether or not the tabs are drawn in the titlebar.
if ( TabsInTitlebar . enabled ) {
document . documentElement . setAttribute ( "chromemargin-nonlwtheme" , "0,-1,-1,-1" ) ;
document . documentElement . setAttribute ( "chromemargin" , "0,-1,-1,-1" ) ;
document . documentElement . removeAttribute ( "drawtitle" ) ;
} else {
// We set chromemargin-nonlwtheme to "" instead of removing it as a way of
// making sure that LightweightThemeConsumer doesn't take it upon itself to
// detect this value again if and when we do a lwtheme state change.
document . documentElement . setAttribute ( "chromemargin-nonlwtheme" , "" ) ;
let isCustomizing = document . documentElement . hasAttribute ( "customizing" ) ;
let hasLWTheme = document . documentElement . hasAttribute ( "lwtheme" ) ;
if ( ! hasLWTheme || isCustomizing ) {
document . documentElement . removeAttribute ( "chromemargin" ) ;
}
document . documentElement . setAttribute ( "drawtitle" , "true" ) ;
}
# else
2010-06-25 12:19:12 +00:00
2013-09-10 14:51:53 +00:00
if ( TabsInTitlebar . enabled )
2012-01-13 15:10:05 +00:00
document . documentElement . setAttribute ( "chromemargin" , "0,2,2,2" ) ;
2010-06-25 12:19:12 +00:00
else
document . documentElement . removeAttribute ( "chromemargin" ) ;
2014-02-04 21:17:00 +00:00
# endif
2010-06-13 08:20:58 +00:00
}
2010-11-05 08:26:46 +00:00
# endif
2010-08-25 03:03:37 +00:00
2010-11-05 08:26:46 +00:00
# ifdef CAN _DRAW _IN _TITLEBAR
2010-08-25 03:03:37 +00:00
function onTitlebarMaxClick ( ) {
if ( window . windowState == window . STATE _MAXIMIZED )
window . restore ( ) ;
else
window . maximize ( ) ;
}
2010-06-13 08:20:58 +00:00
# endif
2004-05-23 10:25:30 +00:00
function displaySecurityInfo ( )
2002-08-09 01:41:39 +00:00
{
2008-01-06 03:50:37 +00:00
BrowserPageInfo ( null , "securityTab" ) ;
2002-08-09 01:41:39 +00:00
}
2006-10-31 14:56:00 +00:00
/ * *
* Opens or closes the sidebar identified by commandID .
*
* @ param commandID a string identifying the sidebar to toggle ; see the
* note below . ( Optional if a sidebar is already open . )
* @ param forceOpen boolean indicating whether the sidebar should be
2008-10-02 06:49:45 +00:00
* opened regardless of its current state ( optional ) .
2006-10-31 14:56:00 +00:00
* @ note
* We expect to find a xul : broadcaster element with the specified ID .
* The following attributes on that element may be used and / or modified :
* - id ( required ) the string to match commandID . The convention
* is to use this naming scheme : 'view<sidebar-name>Sidebar' .
* - sidebarurl ( required ) specifies the URL to load in this sidebar .
2010-03-24 21:22:04 +00:00
* - sidebartitle or label ( in that order ) specify the title to
2006-10-31 14:56:00 +00:00
* display on the sidebar .
* - checked indicates whether the sidebar is currently displayed .
* Note that toggleSidebar updates this attribute when
* it changes the sidebar ' s visibility .
* - group this attribute must be set to "sidebar" .
* /
function toggleSidebar ( commandID , forceOpen ) {
2003-10-29 08:01:27 +00:00
2002-09-28 22:55:58 +00:00
var sidebarBox = document . getElementById ( "sidebar-box" ) ;
2006-10-31 14:56:00 +00:00
if ( ! commandID )
commandID = sidebarBox . getAttribute ( "sidebarcommand" ) ;
2002-09-30 04:03:00 +00:00
2006-10-31 14:56:00 +00:00
var sidebarBroadcaster = document . getElementById ( commandID ) ;
var sidebar = document . getElementById ( "sidebar" ) ; // xul:browser
2002-09-28 22:55:58 +00:00
var sidebarTitle = document . getElementById ( "sidebar-title" ) ;
2002-09-28 01:49:18 +00:00
var sidebarSplitter = document . getElementById ( "sidebar-splitter" ) ;
2006-10-31 14:56:00 +00:00
if ( sidebarBroadcaster . getAttribute ( "checked" ) == "true" ) {
if ( ! forceOpen ) {
2012-07-21 17:37:56 +00:00
// Replace the document currently displayed in the sidebar with about:blank
// so that we can free memory by unloading the page. We need to explicitly
// create a new content viewer because the old one doesn't get destroyed
// until about:blank has loaded (which does not happen as long as the
// element is hidden).
sidebar . setAttribute ( "src" , "about:blank" ) ;
sidebar . docShell . createAboutBlankContentViewer ( null ) ;
2006-10-31 14:56:00 +00:00
sidebarBroadcaster . removeAttribute ( "checked" ) ;
sidebarBox . setAttribute ( "sidebarcommand" , "" ) ;
sidebarTitle . value = "" ;
sidebarBox . hidden = true ;
sidebarSplitter . hidden = true ;
2012-09-19 10:59:26 +00:00
gBrowser . selectedBrowser . focus ( ) ;
2008-03-12 22:47:59 +00:00
} else {
fireSidebarFocusedEvent ( ) ;
2006-10-31 14:56:00 +00:00
}
2002-09-28 01:49:18 +00:00
return ;
}
2005-06-14 10:15:58 +00:00
2006-10-31 14:56:00 +00:00
// now we need to show the specified sidebar
2002-09-30 01:58:19 +00:00
2006-10-31 14:56:00 +00:00
// ..but first update the 'checked' state of all sidebar broadcasters
var broadcasters = document . getElementsByAttribute ( "group" , "sidebar" ) ;
2012-08-21 16:56:07 +00:00
for ( let broadcaster of broadcasters ) {
2006-10-31 14:56:00 +00:00
// skip elements that observe sidebar broadcasters and random
// other elements
2012-08-21 16:56:07 +00:00
if ( broadcaster . localName != "broadcaster" )
2006-10-31 14:56:00 +00:00
continue ;
2002-09-28 01:49:18 +00:00
2012-08-21 16:56:07 +00:00
if ( broadcaster != sidebarBroadcaster )
broadcaster . removeAttribute ( "checked" ) ;
2006-10-31 14:56:00 +00:00
else
sidebarBroadcaster . setAttribute ( "checked" , "true" ) ;
2002-09-28 01:49:18 +00:00
}
2005-06-14 10:15:58 +00:00
2006-10-31 14:56:00 +00:00
sidebarBox . hidden = false ;
sidebarSplitter . hidden = false ;
var url = sidebarBroadcaster . getAttribute ( "sidebarurl" ) ;
var title = sidebarBroadcaster . getAttribute ( "sidebartitle" ) ;
2002-09-28 22:55:58 +00:00
if ( ! title )
2006-10-31 14:56:00 +00:00
title = sidebarBroadcaster . getAttribute ( "label" ) ;
2008-03-12 22:47:59 +00:00
sidebar . setAttribute ( "src" , url ) ; // kick off async load
2006-10-31 14:56:00 +00:00
sidebarBox . setAttribute ( "sidebarcommand" , sidebarBroadcaster . id ) ;
sidebarTitle . value = title ;
2008-03-12 22:47:59 +00:00
// We set this attribute here in addition to setting it on the <browser>
2012-06-15 19:09:48 +00:00
// element itself, because the code in gBrowserInit.onUnload persists this
2008-03-12 22:47:59 +00:00
// attribute, not the "src" of the <browser id="sidebar">. The reason it
// does that is that we want to delay sidebar load a bit when a browser
// window opens. See delayedStartup().
2002-11-05 00:29:14 +00:00
sidebarBox . setAttribute ( "src" , url ) ;
2008-03-12 22:47:59 +00:00
if ( sidebar . contentDocument . location . href != url )
sidebar . addEventListener ( "load" , sidebarOnLoad , true ) ;
else // older code handled this case, so we do it too
fireSidebarFocusedEvent ( ) ;
}
function sidebarOnLoad ( event ) {
var sidebar = document . getElementById ( "sidebar" ) ;
sidebar . removeEventListener ( "load" , sidebarOnLoad , true ) ;
// We're handling the 'load' event before it bubbles up to the usual
// (non-capturing) event handlers. Let it bubble up before firing the
// SidebarFocused event.
setTimeout ( fireSidebarFocusedEvent , 0 ) ;
}
/ * *
* Fire a "SidebarFocused" event on the sidebar ' s | window | to give the sidebar
2008-03-12 22:49:59 +00:00
* a chance to adjust focus as needed . An additional event is needed , because
* we don 't want to focus the sidebar when it' s opened on startup or in a new
* window , only when the user opens the sidebar .
* /
2008-03-12 22:47:59 +00:00
function fireSidebarFocusedEvent ( ) {
var sidebar = document . getElementById ( "sidebar" ) ;
var event = document . createEvent ( "Events" ) ;
event . initEvent ( "SidebarFocused" , true , false ) ;
sidebar . contentWindow . dispatchEvent ( event ) ;
2002-09-28 01:49:18 +00:00
}
2013-05-22 14:17:05 +00:00
2003-12-16 00:37:01 +00:00
var gHomeButton = {
prefDomain : "browser.startup.homepage" ,
observe : function ( aSubject , aTopic , aPrefName )
{
if ( aTopic != "nsPref:changed" || aPrefName != this . prefDomain )
return ;
2005-06-14 10:15:58 +00:00
2003-12-16 00:37:01 +00:00
this . updateTooltip ( ) ;
} ,
2005-06-14 10:15:58 +00:00
2008-02-20 09:56:52 +00:00
updateTooltip : function ( homeButton )
2003-12-16 00:37:01 +00:00
{
2008-02-20 09:56:52 +00:00
if ( ! homeButton )
homeButton = document . getElementById ( "home-button" ) ;
2003-12-16 00:37:01 +00:00
if ( homeButton ) {
var homePage = this . getHomePage ( ) ;
homePage = homePage . replace ( /\|/g , ', ' ) ;
2010-09-14 22:56:37 +00:00
if ( homePage . toLowerCase ( ) == "about:home" )
homeButton . setAttribute ( "tooltiptext" , homeButton . getAttribute ( "aboutHomeOverrideTooltip" ) ) ;
else
homeButton . setAttribute ( "tooltiptext" , homePage ) ;
2003-12-16 00:37:01 +00:00
}
} ,
2005-06-14 10:15:58 +00:00
2003-12-16 00:37:01 +00:00
getHomePage : function ( )
{
var url ;
try {
url = gPrefService . getComplexValue ( this . prefDomain ,
Components . interfaces . nsIPrefLocalizedString ) . data ;
} catch ( e ) {
}
// use this if we can't find the pref
if ( ! url ) {
2012-12-20 20:34:06 +00:00
var configBundle = Services . strings
. createBundle ( "chrome://branding/locale/browserconfig.properties" ) ;
2006-08-29 17:29:44 +00:00
url = configBundle . GetStringFromName ( this . prefDomain ) ;
2003-12-16 00:37:01 +00:00
}
return url ;
2008-01-30 10:43:29 +00:00
} ,
2008-02-20 09:56:52 +00:00
updatePersonalToolbarStyle : function ( homeButton )
2008-01-30 10:43:29 +00:00
{
2008-02-20 09:56:52 +00:00
if ( ! homeButton )
homeButton = document . getElementById ( "home-button" ) ;
2008-01-30 10:43:29 +00:00
if ( homeButton )
2008-02-04 19:37:26 +00:00
homeButton . className = homeButton . parentNode . id == "PersonalToolbar"
|| homeButton . parentNode . parentNode . id == "PersonalToolbar" ?
2008-01-30 23:16:52 +00:00
homeButton . className . replace ( "toolbarbutton-1" , "bookmark-item" ) :
homeButton . className . replace ( "bookmark-item" , "toolbarbutton-1" ) ;
2014-01-02 20:32:09 +00:00
} ,
2003-12-16 00:37:01 +00:00
} ;
2002-09-29 20:30:20 +00:00
2014-01-31 00:16:05 +00:00
const nodeToTooltipMap = {
"bookmarks-menu-button" : "bookmarksMenuButton.tooltip" ,
# ifdef XP _MACOSX
"print-button" : "printButton.tooltip" ,
# endif
"new-window-button" : "newWindowButton.tooltip" ,
"fullscreen-button" : "fullscreenButton.tooltip" ,
"tabview-button" : "tabviewButton.tooltip" ,
} ;
const nodeToShortcutMap = {
"bookmarks-menu-button" : "manBookmarkKb" ,
# ifdef XP _MACOSX
"print-button" : "printKb" ,
# endif
"new-window-button" : "key_newNavigator" ,
"fullscreen-button" : "key_fullScreen" ,
"tabview-button" : "key_tabview" ,
} ;
const gDynamicTooltipCache = new Map ( ) ;
2014-02-26 19:29:57 +00:00
function UpdateDynamicShortcutTooltipText ( aTooltip ) {
let nodeId = aTooltip . triggerNode . id ;
2014-01-31 00:16:05 +00:00
if ( ! gDynamicTooltipCache . has ( nodeId ) && nodeId in nodeToTooltipMap ) {
let strId = nodeToTooltipMap [ nodeId ] ;
let args = [ ] ;
if ( nodeId in nodeToShortcutMap ) {
let shortcutId = nodeToShortcutMap [ nodeId ] ;
let shortcut = document . getElementById ( shortcutId ) ;
if ( shortcut ) {
args . push ( ShortcutUtils . prettifyShortcut ( shortcut ) ) ;
}
}
gDynamicTooltipCache . set ( nodeId , gNavigatorBundle . getFormattedString ( strId , args ) ) ;
}
2014-02-26 19:29:57 +00:00
aTooltip . setAttribute ( "label" , gDynamicTooltipCache . get ( nodeId ) ) ;
2014-01-31 00:16:05 +00:00
}
2006-03-17 07:16:00 +00:00
/ * *
* Gets the selected text in the active browser . Leading and trailing
* whitespace is removed , and consecutive whitespace is replaced by a single
* space . A maximum of 150 characters will be returned , regardless of the value
* of aCharLen .
*
* @ param aCharLen
* The maximum number of characters to return .
* /
function getBrowserSelection ( aCharLen ) {
// selections of more than 150 characters aren't useful
const kMaxSelectionLen = 150 ;
const charLen = Math . min ( aCharLen || kMaxSelectionLen , kMaxSelectionLen ) ;
2014-03-14 18:47:46 +00:00
let [ element , focusedWindow ] = BrowserUtils . getFocusSync ( document ) ;
2006-03-17 07:16:00 +00:00
var selection = focusedWindow . getSelection ( ) . toString ( ) ;
2011-04-24 16:15:53 +00:00
// try getting a selected text in text input.
if ( ! selection ) {
2012-11-26 16:18:25 +00:00
var isOnTextInput = function isOnTextInput ( elem ) {
2011-04-24 16:15:53 +00:00
// we avoid to return a value if a selection is in password field.
// ref. bug 565717
return elem instanceof HTMLTextAreaElement ||
( elem instanceof HTMLInputElement && elem . mozIsTextField ( true ) ) ;
} ;
if ( isOnTextInput ( element ) ) {
selection = element . QueryInterface ( Ci . nsIDOMNSEditableElement )
. editor . selection . toString ( ) ;
}
}
2006-03-17 07:16:00 +00:00
if ( selection ) {
if ( selection . length > charLen ) {
// only use the first charLen important chars. see bug 221361
var pattern = new RegExp ( "^(?:\\s*.){0," + charLen + "}" ) ;
pattern . test ( selection ) ;
selection = RegExp . lastMatch ;
}
2012-12-20 20:34:06 +00:00
selection = selection . trim ( ) . replace ( /\s+/g , " " ) ;
2006-03-17 07:16:00 +00:00
if ( selection . length > charLen )
selection = selection . substr ( 0 , charLen ) ;
}
return selection ;
}
2003-08-03 01:58:52 +00:00
var gWebPanelURI ;
2003-08-04 03:40:27 +00:00
function openWebPanel ( aTitle , aURI )
2003-08-03 01:58:52 +00:00
{
// Ensure that the web panels sidebar is open.
toggleSidebar ( 'viewWebPanelsSidebar' , true ) ;
2005-06-14 10:15:58 +00:00
2003-08-04 03:40:27 +00:00
// Set the title of the panel.
document . getElementById ( "sidebar-title" ) . value = aTitle ;
2005-06-14 10:15:58 +00:00
2003-08-03 01:58:52 +00:00
// Tell the Web Panels sidebar to load the bookmark.
var sidebar = document . getElementById ( "sidebar" ) ;
2005-01-09 01:41:03 +00:00
if ( sidebar . docShell && sidebar . contentDocument && sidebar . contentDocument . getElementById ( 'web-panels-browser' ) ) {
2003-08-03 01:58:52 +00:00
sidebar . contentWindow . loadWebPanel ( aURI ) ;
if ( gWebPanelURI ) {
gWebPanelURI = "" ;
sidebar . removeEventListener ( "load" , asyncOpenWebPanel , true ) ;
}
}
else {
// The panel is still being constructed. Attach an onload handler.
if ( ! gWebPanelURI )
sidebar . addEventListener ( "load" , asyncOpenWebPanel , true ) ;
gWebPanelURI = aURI ;
}
}
function asyncOpenWebPanel ( event )
{
var sidebar = document . getElementById ( "sidebar" ) ;
2003-08-04 03:40:27 +00:00
if ( gWebPanelURI && sidebar . contentDocument && sidebar . contentDocument . getElementById ( 'web-panels-browser' ) )
2003-08-03 01:58:52 +00:00
sidebar . contentWindow . loadWebPanel ( gWebPanelURI ) ;
gWebPanelURI = "" ;
sidebar . removeEventListener ( "load" , asyncOpenWebPanel , true ) ;
}
2002-10-13 16:35:19 +00:00
/ *
* - [ Dependencies ] -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -
* utilityOverlay . js :
* - gatherTextUnder
* /
2010-03-24 21:21:54 +00:00
/ * *
* Extracts linkNode and href for the current click target .
*
* @ param event
* The click event .
* @ return [ href , linkNode ] .
*
* @ note linkNode will be null if the click wasn ' t on an anchor
* element ( or XLink ) .
* /
function hrefAndLinkNodeForClickEvent ( event )
{
function isHTMLLink ( aNode )
{
2010-12-27 20:42:10 +00:00
// Be consistent with what nsContextMenu.js does.
return ( ( aNode instanceof HTMLAnchorElement && aNode . href ) ||
( aNode instanceof HTMLAreaElement && aNode . href ) ||
aNode instanceof HTMLLinkElement ) ;
2010-03-24 21:21:54 +00:00
}
2010-12-27 20:42:10 +00:00
let node = event . target ;
while ( node && ! isHTMLLink ( node ) ) {
node = node . parentNode ;
2010-03-24 21:21:54 +00:00
}
2010-12-27 20:42:10 +00:00
if ( node )
return [ node . href , node ] ;
2010-03-24 21:21:54 +00:00
// If there is no linkNode, try simple XLink.
let href , baseURI ;
2010-12-27 20:42:10 +00:00
node = event . target ;
2011-06-30 13:34:12 +00:00
while ( node && ! href ) {
2010-03-24 21:21:54 +00:00
if ( node . nodeType == Node . ELEMENT _NODE ) {
href = node . getAttributeNS ( "http://www.w3.org/1999/xlink" , "href" ) ;
if ( href )
baseURI = node . baseURI ;
}
node = node . parentNode ;
}
// In case of XLink, we don't return the node we got href from since
// callers expect <a>-like elements.
return [ href ? makeURLAbsolute ( baseURI , href ) : null , null ] ;
}
/ * *
* Called whenever the user clicks in the content area .
*
* @ param event
* The click event .
* @ param isPanelClick
* Whether the event comes from a web panel .
* @ note default event is prevented if the click is handled .
* /
function contentAreaClick ( event , isPanelClick )
{
2011-12-08 09:21:32 +00:00
if ( ! event . isTrusted || event . defaultPrevented || event . button == 2 )
2012-02-10 13:11:53 +00:00
return ;
2002-10-13 23:52:36 +00:00
2010-03-24 21:21:54 +00:00
let [ href , linkNode ] = hrefAndLinkNodeForClickEvent ( event ) ;
if ( ! href ) {
// Not a link, handle middle mouse navigation.
if ( event . button == 1 &&
gPrefService . getBoolPref ( "middlemouse.contentLoadURL" ) &&
! gPrefService . getBoolPref ( "general.autoScroll" ) ) {
middleMousePaste ( event ) ;
event . preventDefault ( ) ;
}
2012-02-10 13:11:53 +00:00
return ;
2010-03-24 21:21:54 +00:00
}
// This code only applies if we have a linkNode (i.e. clicks on real anchor
// elements, as opposed to XLink).
if ( linkNode && event . button == 0 &&
! event . ctrlKey && ! event . shiftKey && ! event . altKey && ! event . metaKey ) {
// A Web panel's links should target the main content area. Do this
// if no modifier keys are down and if there's no target or the target
// equals _main (the IE convention) or _content (the Mozilla convention).
let target = linkNode . target ;
let mainTarget = ! target || target == "_content" || target == "_main" ;
if ( isPanelClick && mainTarget ) {
// javascript and data links should be executed in the current browser.
if ( linkNode . getAttribute ( "onclick" ) ||
2012-12-20 20:34:06 +00:00
href . startsWith ( "javascript:" ) ||
href . startsWith ( "data:" ) )
2012-02-10 13:11:53 +00:00
return ;
2010-03-24 21:21:54 +00:00
try {
urlSecurityCheck ( href , linkNode . ownerDocument . nodePrincipal ) ;
}
catch ( ex ) {
// Prevent loading unsecure destinations.
event . preventDefault ( ) ;
2012-02-10 13:11:53 +00:00
return ;
2010-03-24 21:21:54 +00:00
}
2012-11-04 13:48:37 +00:00
loadURI ( href , null , null , false ) ;
2010-03-24 21:21:54 +00:00
event . preventDefault ( ) ;
2012-02-10 13:11:53 +00:00
return ;
2010-03-24 21:21:54 +00:00
}
if ( linkNode . getAttribute ( "rel" ) == "sidebar" ) {
// This is the Opera convention for a special link that, when clicked,
// allows to add a sidebar panel. The link's title attribute contains
// the title that should be used for the sidebar panel.
2011-10-27 09:11:43 +00:00
PlacesUIUtils . showBookmarkDialog ( { action : "add"
, type : "bookmark"
, uri : makeURI ( href )
, title : linkNode . getAttribute ( "title" )
, loadBookmarkInSidebar : true
, hiddenRows : [ "description"
, "location"
, "keyword" ]
2011-11-11 21:39:26 +00:00
} , window ) ;
2010-03-24 21:21:54 +00:00
event . preventDefault ( ) ;
2012-02-10 13:11:53 +00:00
return ;
2010-03-24 21:21:54 +00:00
}
}
handleLinkClick ( event , href , linkNode ) ;
2010-11-08 14:03:49 +00:00
// Mark the page as a user followed link. This is done so that history can
// distinguish automatic embed visits from user activated ones. For example
// pages loaded in frames are embed visits and lost with the session, while
// visits across frames should be preserved.
try {
2012-02-18 06:40:10 +00:00
if ( ! PrivateBrowsingUtils . isWindowPrivate ( window ) )
PlacesUIUtils . markPageAsFollowedLink ( href ) ;
2010-11-08 14:03:49 +00:00
} catch ( ex ) { /* Skip invalid URIs. */ }
2010-03-24 21:21:54 +00:00
}
/ * *
* Handles clicks on links .
*
* @ return true if the click event was handled , false otherwise .
* /
2010-10-23 12:01:33 +00:00
function handleLinkClick ( event , href , linkNode ) {
if ( event . button == 2 ) // right click
return false ;
2010-03-24 21:22:04 +00:00
2010-10-23 12:01:33 +00:00
var where = whereToOpenLink ( event ) ;
if ( where == "current" )
return false ;
2005-06-14 10:15:58 +00:00
2010-10-23 12:01:33 +00:00
var doc = event . target . ownerDocument ;
2005-06-14 10:15:58 +00:00
2010-10-23 12:01:33 +00:00
if ( where == "save" ) {
2011-11-22 00:46:13 +00:00
saveURL ( href , linkNode ? gatherTextUnder ( linkNode ) : "" , null , true ,
2012-10-03 17:10:20 +00:00
true , doc . documentURIObject , doc ) ;
2010-03-24 21:21:54 +00:00
event . preventDefault ( ) ;
2010-10-23 12:01:33 +00:00
return true ;
2002-10-13 16:35:19 +00:00
}
2010-10-23 12:01:33 +00:00
2013-10-11 04:26:32 +00:00
var referrerURI = doc . documentURIObject ;
// if the mixedContentChannel is present and the referring URI passes
// a same origin check with the target URI, we can preserve the users
// decision of disabling MCB on a page for it's child tabs.
var persistDisableMCBInChildTab = false ;
if ( where == "tab" && gBrowser . docShell . mixedContentChannel ) {
const sm = Services . scriptSecurityManager ;
try {
var targetURI = makeURI ( href ) ;
sm . checkSameOriginURI ( referrerURI , targetURI , false ) ;
persistDisableMCBInChildTab = true ;
}
catch ( e ) { }
}
2010-10-23 12:01:33 +00:00
urlSecurityCheck ( href , doc . nodePrincipal ) ;
2013-10-11 04:26:32 +00:00
openLinkIn ( href , where , { referrerURI : referrerURI ,
charset : doc . characterSet ,
disableMCB : persistDisableMCBInChildTab } ) ;
2010-03-24 21:21:54 +00:00
event . preventDefault ( ) ;
2010-10-23 12:01:33 +00:00
return true ;
2002-10-13 23:52:36 +00:00
}
2002-10-13 16:35:19 +00:00
2010-04-22 07:25:54 +00:00
function middleMousePaste ( event ) {
2010-11-04 07:14:07 +00:00
let clipboard = readFromClipboard ( ) ;
if ( ! clipboard )
return ;
// Strip embedded newlines and surrounding whitespace, to match the URL
// bar's behavior (stripsurroundingwhitespace)
2011-04-17 01:17:17 +00:00
clipboard = clipboard . replace ( /\s*\n\s*/g , "" ) ;
2010-11-04 07:14:07 +00:00
2013-06-25 01:26:22 +00:00
// if it's not the current tab, we don't need to do anything because the
// browser doesn't exist.
let where = whereToOpenLink ( event , true , false ) ;
let lastLocationChange ;
if ( where == "current" ) {
lastLocationChange = gBrowser . selectedBrowser . lastLocationChange ;
2010-04-22 07:25:54 +00:00
}
2004-03-17 01:51:49 +00:00
2013-06-25 01:26:22 +00:00
Task . spawn ( function ( ) {
let data = yield getShortcutOrURIAndPostData ( clipboard ) ;
try {
makeURI ( data . url ) ;
} catch ( ex ) {
// Not a valid URI.
return ;
}
2005-07-05 23:08:30 +00:00
2013-06-25 01:26:22 +00:00
try {
addToUrlbarHistory ( data . url ) ;
} catch ( ex ) {
// Things may go wrong when adding url to session history,
// but don't let that interfere with the loading of the url.
Cu . reportError ( ex ) ;
}
if ( where != "current" ||
lastLocationChange == gBrowser . selectedBrowser . lastLocationChange ) {
openUILink ( data . url , event ,
{ ignoreButton : true ,
disallowInheritPrincipal : ! data . mayInheritPrincipal } ) ;
}
} ) ;
2002-10-13 16:35:19 +00:00
2006-03-25 22:03:49 +00:00
event . stopPropagation ( ) ;
2002-10-13 23:52:36 +00:00
}
2002-10-13 16:35:19 +00:00
2010-04-18 18:27:18 +00:00
function handleDroppedLink ( event , url , name )
{
2013-06-25 01:26:22 +00:00
let lastLocationChange = gBrowser . selectedBrowser . lastLocationChange ;
Task . spawn ( function ( ) {
let data = yield getShortcutOrURIAndPostData ( url ) ;
if ( data . url &&
lastLocationChange == gBrowser . selectedBrowser . lastLocationChange )
loadURI ( data . url , null , data . postData , false ) ;
} ) ;
2010-04-18 18:27:18 +00:00
// Keep the event from being handled by the dragDrop listeners
// built-in to gecko if they happen to be above us.
event . preventDefault ( ) ;
2002-12-07 20:44:19 +00:00
} ;
function BrowserSetForcedCharacterSet ( aCharset )
{
2014-02-23 18:28:04 +00:00
if ( aCharset ) {
gBrowser . docShell . gatherCharsetMenuTelemetry ( ) ;
gBrowser . docShell . charset = aCharset ;
// Save the forced character-set
if ( ! PrivateBrowsingUtils . isWindowPrivate ( window ) )
PlacesUtils . setCharsetForURI ( getWebNavigation ( ) . currentURI , aCharset ) ;
}
2012-01-24 09:52:05 +00:00
BrowserCharsetReload ( ) ;
2002-12-07 20:44:19 +00:00
}
2012-01-24 09:52:05 +00:00
function BrowserCharsetReload ( )
2002-12-07 20:44:19 +00:00
{
2012-01-24 09:52:05 +00:00
BrowserReloadWithFlags ( nsIWebNavigation . LOAD _FLAGS _CHARSET _CHANGE ) ;
2002-12-07 20:44:19 +00:00
}
2014-02-23 18:28:04 +00:00
function charsetMenuGetElement ( parent , charset ) {
return parent . getElementsByAttribute ( "charset" , charset ) [ 0 ] ;
2010-09-21 22:20:16 +00:00
}
function UpdateCurrentCharset ( target ) {
2008-07-06 00:53:48 +00:00
// extract the charset from DOM
2002-10-13 16:39:47 +00:00
var wnd = document . commandDispatcher . focusedWindow ;
2005-01-28 16:06:56 +00:00
if ( ( window == wnd ) || ( wnd == null ) ) wnd = window . content ;
2002-10-13 16:39:47 +00:00
2008-07-06 00:53:48 +00:00
// Uncheck previous item
if ( gPrevCharset ) {
2014-02-23 18:28:04 +00:00
var pref _item = charsetMenuGetElement ( target , gPrevCharset ) ;
2008-07-06 00:53:48 +00:00
if ( pref _item )
pref _item . setAttribute ( 'checked' , 'false' ) ;
}
2014-02-23 18:28:04 +00:00
var menuitem = charsetMenuGetElement ( target , CharsetMenu . foldCharset ( wnd . document . characterSet ) ) ;
2002-10-13 16:39:47 +00:00
if ( menuitem ) {
menuitem . setAttribute ( 'checked' , 'true' ) ;
}
}
2012-08-21 07:54:57 +00:00
function charsetLoadListener ( ) {
2014-02-23 18:28:04 +00:00
var charset = CharsetMenu . foldCharset ( window . content . document . characterSet ) ;
2002-10-13 16:39:47 +00:00
2010-01-28 18:31:45 +00:00
if ( charset . length > 0 && ( charset != gLastBrowserCharset ) ) {
gPrevCharset = gLastBrowserCharset ;
gLastBrowserCharset = charset ;
}
2002-10-13 16:39:47 +00:00
}
2003-08-05 10:16:09 +00:00
2012-03-05 10:53:34 +00:00
var gPageStyleMenu = {
2003-08-10 08:04:58 +00:00
2014-03-12 03:13:45 +00:00
// This maps from a <browser> element (or, more specifically, a
// browser's permanentKey) to a CPOW that gives synchronous access
// to the list of style sheets in a content window. The use of the
// permanentKey is to avoid issues with docshell swapping.
_pageStyleSyncHandlers : new WeakMap ( ) ,
init : function ( ) {
let mm = window . messageManager ;
mm . addMessageListener ( "PageStyle:SetSyncHandler" , ( msg ) => {
this . _pageStyleSyncHandlers . set ( msg . target . permanentKey , msg . objects . syncHandler ) ;
} ) ;
} ,
getAllStyleSheets : function ( ) {
let handler = this . _pageStyleSyncHandlers . get ( gBrowser . selectedBrowser . permanentKey ) ;
try {
return handler . getAllStyleSheets ( ) ;
} catch ( ex ) {
// In case the child died or timed out.
return [ ] ;
}
} ,
_getStyleSheetInfo : function ( browser ) {
let handler = this . _pageStyleSyncHandlers . get ( gBrowser . selectedBrowser . permanentKey ) ;
try {
return handler . getStyleSheetInfo ( ) ;
} catch ( ex ) {
// In case the child died or timed out.
return { styleSheets : [ ] , authorStyleDisabled : false , preferredStyleSheetSet : true } ;
2012-03-05 10:53:34 +00:00
}
} ,
2005-06-14 10:15:58 +00:00
2012-03-11 04:23:51 +00:00
fillPopup : function ( menuPopup ) {
2014-03-12 03:13:45 +00:00
let styleSheetInfo = this . _getStyleSheetInfo ( gBrowser . selectedBrowser ) ;
2012-03-05 10:53:34 +00:00
var noStyle = menuPopup . firstChild ;
var persistentOnly = noStyle . nextSibling ;
var sep = persistentOnly . nextSibling ;
while ( sep . nextSibling )
menuPopup . removeChild ( sep . nextSibling ) ;
2008-08-09 19:37:00 +00:00
2014-03-12 03:13:45 +00:00
let styleSheets = styleSheetInfo . styleSheets ;
2012-03-05 10:53:34 +00:00
var currentStyleSheets = { } ;
2014-03-12 03:13:45 +00:00
var styleDisabled = styleSheetInfo . authorStyleDisabled ;
2012-03-05 10:53:34 +00:00
var haveAltSheets = false ;
var altStyleSelected = false ;
2005-06-14 10:15:58 +00:00
2012-08-21 16:56:07 +00:00
for ( let currentStyleSheet of styleSheets ) {
2012-03-05 10:53:34 +00:00
if ( ! currentStyleSheet . disabled )
altStyleSelected = true ;
haveAltSheets = true ;
let lastWithSameTitle = null ;
if ( currentStyleSheet . title in currentStyleSheets )
lastWithSameTitle = currentStyleSheets [ currentStyleSheet . title ] ;
if ( ! lastWithSameTitle ) {
let menuItem = document . createElement ( "menuitem" ) ;
menuItem . setAttribute ( "type" , "radio" ) ;
menuItem . setAttribute ( "label" , currentStyleSheet . title ) ;
menuItem . setAttribute ( "data" , currentStyleSheet . title ) ;
menuItem . setAttribute ( "checked" , ! currentStyleSheet . disabled && ! styleDisabled ) ;
2012-03-21 08:13:36 +00:00
menuItem . setAttribute ( "oncommand" , "gPageStyleMenu.switchStyleSheet(this.getAttribute('data'));" ) ;
2012-03-05 10:53:34 +00:00
menuPopup . appendChild ( menuItem ) ;
currentStyleSheets [ currentStyleSheet . title ] = menuItem ;
} else if ( currentStyleSheet . disabled ) {
lastWithSameTitle . removeAttribute ( "checked" ) ;
}
}
2008-08-09 19:37:00 +00:00
2012-03-05 10:53:34 +00:00
noStyle . setAttribute ( "checked" , styleDisabled ) ;
persistentOnly . setAttribute ( "checked" , ! altStyleSelected && ! styleDisabled ) ;
2014-03-12 03:13:45 +00:00
persistentOnly . hidden = styleSheetInfo . preferredStyleSheetSet ? haveAltSheets : false ;
2012-03-05 10:53:34 +00:00
sep . hidden = ( noStyle . hidden && persistentOnly . hidden ) || ! haveAltSheets ;
} ,
2008-08-09 19:37:00 +00:00
2014-03-12 03:13:45 +00:00
switchStyleSheet : function ( title ) {
let mm = gBrowser . selectedBrowser . messageManager ;
mm . sendAsyncMessage ( "PageStyle:Switch" , { title : title } ) ;
2012-03-11 04:24:35 +00:00
} ,
disableStyle : function ( ) {
2014-03-12 03:13:45 +00:00
let mm = gBrowser . selectedBrowser . messageManager ;
mm . sendAsyncMessage ( "PageStyle:Disable" ) ;
2012-03-05 10:53:34 +00:00
} ,
} ;
2008-08-09 19:37:00 +00:00
2012-03-05 10:53:34 +00:00
/* Legacy global page-style functions */
2014-03-12 03:13:45 +00:00
var getAllStyleSheets = gPageStyleMenu . getAllStyleSheets . bind ( gPageStyleMenu ) ;
2012-03-11 04:23:51 +00:00
var stylesheetFillPopup = gPageStyleMenu . fillPopup . bind ( gPageStyleMenu ) ;
2012-03-11 04:25:02 +00:00
function stylesheetSwitchAll ( contentWindow , title ) {
2014-03-12 03:13:45 +00:00
// We ignore the contentWindow param. Add-ons don't appear to use
// it, and it's difficult to support in e10s (where it will be a
// CPOW).
gPageStyleMenu . switchStyleSheet ( title ) ;
2012-03-11 04:25:02 +00:00
}
2012-03-11 04:24:35 +00:00
function setStyleDisabled ( disabled ) {
if ( disabled )
gPageStyleMenu . disableStyle ( ) ;
}
2003-08-10 08:04:58 +00:00
2003-12-02 00:29:22 +00:00
var BrowserOffline = {
2010-11-26 20:24:51 +00:00
_inited : false ,
2003-12-02 00:29:22 +00:00
/////////////////////////////////////////////////////////////////////////////
// BrowserOffline Public Methods
init : function ( )
{
2006-04-04 21:26:17 +00:00
if ( ! this . _uiElement )
2010-09-21 09:16:29 +00:00
this . _uiElement = document . getElementById ( "workOfflineMenuitemState" ) ;
2006-04-04 21:26:17 +00:00
2010-01-28 18:31:45 +00:00
Services . obs . addObserver ( this , "network:offline-status-changed" , false ) ;
2009-07-29 08:49:59 +00:00
2010-01-28 18:31:45 +00:00
this . _updateOfflineUI ( Services . io . offline ) ;
2010-11-26 20:24:51 +00:00
this . _inited = true ;
2003-12-02 00:29:22 +00:00
} ,
2005-06-14 10:15:58 +00:00
2003-12-02 00:29:22 +00:00
uninit : function ( )
{
2010-11-26 20:24:51 +00:00
if ( this . _inited ) {
2010-01-28 18:31:45 +00:00
Services . obs . removeObserver ( this , "network:offline-status-changed" ) ;
2004-02-25 00:27:13 +00:00
}
2003-12-02 00:29:22 +00:00
} ,
toggleOfflineStatus : function ( )
{
2010-01-28 18:31:45 +00:00
var ioService = Services . io ;
2009-07-29 08:49:59 +00:00
2006-04-04 21:26:17 +00:00
// Stop automatic management of the offline status
try {
2009-07-29 08:49:59 +00:00
ioService . manageOfflineStatus = false ;
2006-04-04 21:26:17 +00:00
} catch ( ex ) {
}
2010-03-24 21:22:04 +00:00
2009-07-29 08:49:59 +00:00
if ( ! ioService . offline && ! this . _canGoOffline ( ) ) {
2003-12-02 00:59:33 +00:00
this . _updateOfflineUI ( false ) ;
2003-12-02 00:29:22 +00:00
return ;
2003-12-02 00:59:33 +00:00
}
2003-12-02 00:29:22 +00:00
2009-07-29 08:49:59 +00:00
ioService . offline = ! ioService . offline ;
2003-12-02 00:29:22 +00:00
} ,
2005-06-14 10:15:58 +00:00
2003-12-02 00:29:22 +00:00
/////////////////////////////////////////////////////////////////////////////
// nsIObserver
2005-06-14 10:15:58 +00:00
observe : function ( aSubject , aTopic , aState )
2003-12-02 00:29:22 +00:00
{
if ( aTopic != "network:offline-status-changed" )
return ;
2005-06-14 10:15:58 +00:00
2003-12-02 00:29:22 +00:00
this . _updateOfflineUI ( aState == "offline" ) ;
} ,
/////////////////////////////////////////////////////////////////////////////
// BrowserOffline Implementation Methods
_canGoOffline : function ( )
{
2010-01-28 18:31:45 +00:00
try {
var cancelGoOffline = Cc [ "@mozilla.org/supports-PRBool;1" ] . createInstance ( Ci . nsISupportsPRBool ) ;
Services . obs . notifyObservers ( cancelGoOffline , "offline-requested" , null ) ;
2005-06-14 10:15:58 +00:00
2010-01-28 18:31:45 +00:00
// Something aborted the quit process.
if ( cancelGoOffline . data )
return false ;
2003-12-02 00:29:22 +00:00
}
2010-01-28 18:31:45 +00:00
catch ( ex ) {
}
2003-12-02 00:29:22 +00:00
return true ;
} ,
_uiElement : null ,
_updateOfflineUI : function ( aOffline )
{
var offlineLocked = gPrefService . prefIsLocked ( "network.online" ) ;
2005-06-14 10:15:58 +00:00
if ( offlineLocked )
2003-12-02 00:29:22 +00:00
this . _uiElement . setAttribute ( "disabled" , "true" ) ;
2005-06-14 10:15:58 +00:00
2003-12-02 00:29:22 +00:00
this . _uiElement . setAttribute ( "checked" , aOffline ) ;
}
} ;
2008-01-23 02:10:50 +00:00
var OfflineApps = {
/////////////////////////////////////////////////////////////////////////////
// OfflineApps Public Methods
init : function ( )
{
2010-01-28 18:31:45 +00:00
Services . obs . addObserver ( this , "offline-cache-update-completed" , false ) ;
2008-01-23 02:10:50 +00:00
} ,
uninit : function ( )
{
2010-01-28 18:31:45 +00:00
Services . obs . removeObserver ( this , "offline-cache-update-completed" ) ;
2008-01-23 02:10:50 +00:00
} ,
2009-02-22 19:09:10 +00:00
handleEvent : function ( event ) {
if ( event . type == "MozApplicationManifest" ) {
this . offlineAppRequested ( event . originalTarget . defaultView ) ;
}
} ,
2008-01-23 02:10:50 +00:00
/////////////////////////////////////////////////////////////////////////////
// OfflineApps Implementation Methods
// XXX: _getBrowserWindowForContentWindow and _getBrowserForContentWindow
// were taken from browser/components/feeds/src/WebContentConverter.
_getBrowserWindowForContentWindow : function ( aContentWindow ) {
return aContentWindow . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShellTreeItem )
. rootTreeItem
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIDOMWindow )
. wrappedJSObject ;
} ,
_getBrowserForContentWindow : function ( aBrowserWindow , aContentWindow ) {
// This depends on pseudo APIs of browser.js and tabbrowser.xml
aContentWindow = aContentWindow . top ;
2009-09-18 18:18:26 +00:00
var browsers = aBrowserWindow . gBrowser . browsers ;
2012-08-21 16:56:07 +00:00
for ( let browser of browsers ) {
if ( browser . contentWindow == aContentWindow )
return browser ;
2008-01-23 02:10:50 +00:00
}
2013-06-21 23:14:22 +00:00
// handle other browser/iframe elements that may need popupnotifications
let browser = aContentWindow
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShell )
. chromeEventHandler ;
if ( browser . getAttribute ( "popupnotificationanchor" ) )
return browser ;
2009-09-18 18:18:26 +00:00
return null ;
2008-01-23 02:10:50 +00:00
} ,
2008-02-26 21:13:17 +00:00
_getManifestURI : function ( aWindow ) {
2009-09-18 18:18:26 +00:00
if ( ! aWindow . document . documentElement )
return null ;
2008-02-26 21:13:17 +00:00
var attr = aWindow . document . documentElement . getAttribute ( "manifest" ) ;
2009-09-18 18:18:26 +00:00
if ( ! attr )
return null ;
2009-07-28 07:41:07 +00:00
try {
2009-07-29 05:55:03 +00:00
var contentURI = makeURI ( aWindow . location . href , null , null ) ;
return makeURI ( attr , aWindow . document . characterSet , contentURI ) ;
2009-07-28 07:41:07 +00:00
} catch ( e ) {
return null ;
}
2008-02-26 21:13:17 +00:00
} ,
// A cache update isn't tied to a specific window. Try to find
// the best browser in which to warn the user about space usage
_getBrowserForCacheUpdate : function ( aCacheUpdate ) {
// Prefer the current browser
2009-09-18 18:18:26 +00:00
var uri = this . _getManifestURI ( content ) ;
2008-02-26 21:13:17 +00:00
if ( uri && uri . equals ( aCacheUpdate . manifestURI ) ) {
2009-09-18 18:18:26 +00:00
return gBrowser . selectedBrowser ;
2008-02-26 21:13:17 +00:00
}
2008-07-30 20:28:29 +00:00
var browsers = gBrowser . browsers ;
2012-08-21 16:56:07 +00:00
for ( let browser of browsers ) {
uri = this . _getManifestURI ( browser . contentWindow ) ;
2008-02-26 21:13:17 +00:00
if ( uri && uri . equals ( aCacheUpdate . manifestURI ) ) {
2012-08-21 16:56:07 +00:00
return browser ;
2008-02-26 21:13:17 +00:00
}
}
2013-06-21 23:14:22 +00:00
// is this from a non-tab browser/iframe?
browsers = document . querySelectorAll ( "iframe[popupnotificationanchor] | browser[popupnotificationanchor]" ) ;
for ( let browser of browsers ) {
uri = this . _getManifestURI ( browser . contentWindow ) ;
if ( uri && uri . equals ( aCacheUpdate . manifestURI ) ) {
return browser ;
}
}
2008-02-26 21:13:17 +00:00
return null ;
} ,
_warnUsage : function ( aBrowser , aURI ) {
if ( ! aBrowser )
return ;
2013-06-11 22:08:44 +00:00
let mainAction = {
label : gNavigatorBundle . getString ( "offlineApps.manageUsage" ) ,
accessKey : gNavigatorBundle . getString ( "offlineApps.manageUsageAccessKey" ) ,
callback : OfflineApps . manage
} ;
2008-02-26 21:13:17 +00:00
2013-06-11 22:08:44 +00:00
let warnQuota = gPrefService . getIntPref ( "offline-apps.quota.warn" ) ;
let message = gNavigatorBundle . getFormattedString ( "offlineApps.usage" ,
[ aURI . host ,
warnQuota / 1024 ] ) ;
2008-02-26 21:13:17 +00:00
2013-06-11 22:08:44 +00:00
let anchorID = "indexedDB-notification-icon" ;
PopupNotifications . show ( aBrowser , "offline-app-usage" , message ,
anchorID , mainAction ) ;
2008-02-26 21:13:17 +00:00
// Now that we've warned once, prevent the warning from showing up
// again.
2010-02-25 22:13:00 +00:00
Services . perms . add ( aURI , "offline-app" ,
Ci . nsIOfflineCacheUpdateService . ALLOW _NO _WARN ) ;
2008-02-26 21:13:17 +00:00
} ,
2008-03-28 21:26:42 +00:00
// XXX: duplicated in preferences/advanced.js
2009-02-22 19:09:10 +00:00
_getOfflineAppUsage : function ( host , groups )
2008-03-28 21:26:42 +00:00
{
2010-01-28 18:31:45 +00:00
var cacheService = Cc [ "@mozilla.org/network/application-cache-service;1" ] .
getService ( Ci . nsIApplicationCacheService ) ;
2009-11-04 19:23:20 +00:00
if ( ! groups )
groups = cacheService . getGroups ( ) ;
2008-08-26 23:09:02 +00:00
var usage = 0 ;
2012-08-21 16:56:07 +00:00
for ( let group of groups ) {
var uri = Services . io . newURI ( group , null , null ) ;
2009-02-22 19:09:10 +00:00
if ( uri . asciiHost == host ) {
2012-08-21 16:56:07 +00:00
var cache = cacheService . getActiveCache ( group ) ;
2009-02-22 19:09:10 +00:00
usage += cache . usage ;
}
}
2008-03-28 21:26:42 +00:00
return usage ;
} ,
2008-02-26 21:13:17 +00:00
_checkUsage : function ( aURI ) {
// if the user has already allowed excessive usage, don't bother checking
2010-02-25 22:13:00 +00:00
if ( Services . perms . testExactPermission ( aURI , "offline-app" ) !=
2008-02-26 21:13:17 +00:00
Ci . nsIOfflineCacheUpdateService . ALLOW _NO _WARN ) {
2008-03-28 21:26:42 +00:00
var usage = this . _getOfflineAppUsage ( aURI . asciiHost ) ;
2008-02-26 21:13:17 +00:00
var warnQuota = gPrefService . getIntPref ( "offline-apps.quota.warn" ) ;
if ( usage >= warnQuota * 1024 ) {
return true ;
}
}
return false ;
} ,
2008-01-23 02:10:50 +00:00
offlineAppRequested : function ( aContentWindow ) {
2008-02-22 06:34:15 +00:00
if ( ! gPrefService . getBoolPref ( "browser.offline-apps.notify" ) ) {
return ;
}
2013-04-29 07:38:53 +00:00
let browserWindow = this . _getBrowserWindowForContentWindow ( aContentWindow ) ;
let browser = this . _getBrowserForContentWindow ( browserWindow ,
2008-01-23 02:10:50 +00:00
aContentWindow ) ;
2013-04-29 07:38:53 +00:00
let currentURI = aContentWindow . document . documentURIObject ;
2008-01-23 02:10:50 +00:00
// don't bother showing UI if the user has already made a decision
2010-02-25 22:13:00 +00:00
if ( Services . perms . testExactPermission ( currentURI , "offline-app" ) != Services . perms . UNKNOWN _ACTION )
2008-01-23 02:10:50 +00:00
return ;
try {
if ( gPrefService . getBoolPref ( "offline-apps.allow_by_default" ) ) {
// all pages can use offline capabilities, no need to ask the user
return ;
}
} catch ( e ) {
// this pref isn't set by default, ignore failures
}
2013-04-29 07:38:53 +00:00
let host = currentURI . asciiHost ;
let notificationID = "offline-app-requested-" + host ;
let notification = PopupNotifications . getNotification ( notificationID , browser ) ;
2009-02-22 19:09:10 +00:00
if ( notification ) {
2013-04-29 07:38:53 +00:00
notification . options . documents . push ( aContentWindow . document ) ;
2009-02-22 19:09:10 +00:00
} else {
2013-04-29 07:38:53 +00:00
let mainAction = {
2009-07-13 22:10:04 +00:00
label : gNavigatorBundle . getString ( "offlineApps.allow" ) ,
accessKey : gNavigatorBundle . getString ( "offlineApps.allowAccessKey" ) ,
2009-02-22 19:09:10 +00:00
callback : function ( ) {
2013-04-29 07:38:53 +00:00
for ( let document of notification . options . documents ) {
2012-08-21 16:56:07 +00:00
OfflineApps . allowSite ( document ) ;
2009-02-22 19:09:10 +00:00
}
}
2013-04-29 07:38:53 +00:00
} ;
let secondaryActions = [ {
2009-07-13 22:10:04 +00:00
label : gNavigatorBundle . getString ( "offlineApps.never" ) ,
accessKey : gNavigatorBundle . getString ( "offlineApps.neverAccessKey" ) ,
2009-02-22 19:09:10 +00:00
callback : function ( ) {
2013-04-29 07:38:53 +00:00
for ( let document of notification . options . documents ) {
2012-08-21 16:56:07 +00:00
OfflineApps . disallowSite ( document ) ;
2009-02-22 19:09:10 +00:00
}
}
2008-01-23 02:10:50 +00:00
} ] ;
2013-04-29 07:38:53 +00:00
let message = gNavigatorBundle . getFormattedString ( "offlineApps.available" ,
2009-07-13 22:10:04 +00:00
[ host ] ) ;
2013-04-29 07:38:53 +00:00
let anchorID = "indexedDB-notification-icon" ;
let options = {
documents : [ aContentWindow . document ]
} ;
notification = PopupNotifications . show ( browser , notificationID , message ,
anchorID , mainAction ,
secondaryActions , options ) ;
2008-01-23 02:10:50 +00:00
}
} ,
2009-02-22 19:09:10 +00:00
allowSite : function ( aDocument ) {
2010-02-25 22:13:00 +00:00
Services . perms . add ( aDocument . documentURIObject , "offline-app" , Services . perms . ALLOW _ACTION ) ;
2008-01-23 02:10:50 +00:00
2009-02-22 19:09:10 +00:00
// When a site is enabled while loading, manifest resources will
// start fetching immediately. This one time we need to do it
// ourselves.
this . _startFetching ( aDocument ) ;
2008-01-23 02:10:50 +00:00
} ,
2009-02-22 19:09:10 +00:00
disallowSite : function ( aDocument ) {
2010-02-25 22:13:00 +00:00
Services . perms . add ( aDocument . documentURIObject , "offline-app" , Services . perms . DENY _ACTION ) ;
2008-02-22 06:34:15 +00:00
} ,
2008-02-26 21:13:17 +00:00
manage : function ( ) {
openAdvancedPreferences ( "networkTab" ) ;
} ,
2009-02-22 19:09:10 +00:00
_startFetching : function ( aDocument ) {
if ( ! aDocument . documentElement )
return ;
var manifest = aDocument . documentElement . getAttribute ( "manifest" ) ;
2008-01-23 02:10:50 +00:00
if ( ! manifest )
return ;
2009-07-29 05:55:03 +00:00
var manifestURI = makeURI ( manifest , aDocument . characterSet ,
aDocument . documentURIObject ) ;
2008-01-23 02:10:50 +00:00
var updateService = Cc [ "@mozilla.org/offlinecacheupdate-service;1" ] .
getService ( Ci . nsIOfflineCacheUpdateService ) ;
2010-10-20 17:12:32 +00:00
updateService . scheduleUpdate ( manifestURI , aDocument . documentURIObject , window ) ;
2008-02-26 21:13:17 +00:00
} ,
/////////////////////////////////////////////////////////////////////////////
// nsIObserver
observe : function ( aSubject , aTopic , aState )
{
2012-09-13 18:46:50 +00:00
if ( aTopic == "offline-cache-update-completed" ) {
2008-02-26 21:13:17 +00:00
var cacheUpdate = aSubject . QueryInterface ( Ci . nsIOfflineCacheUpdate ) ;
var uri = cacheUpdate . manifestURI ;
if ( OfflineApps . _checkUsage ( uri ) ) {
var browser = this . _getBrowserForCacheUpdate ( cacheUpdate ) ;
if ( browser ) {
OfflineApps . _warnUsage ( browser , cacheUpdate . manifestURI ) ;
}
}
}
2008-01-23 02:10:50 +00:00
}
} ;
2010-09-09 22:15:40 +00:00
var IndexedDBPromptHelper = {
_permissionsPrompt : "indexedDB-permissions-prompt" ,
_permissionsResponse : "indexedDB-permissions-response" ,
_quotaPrompt : "indexedDB-quota-prompt" ,
_quotaResponse : "indexedDB-quota-response" ,
2010-12-16 17:53:16 +00:00
_quotaCancel : "indexedDB-quota-cancel" ,
2010-09-09 22:15:40 +00:00
_notificationIcon : "indexedDB-notification-icon" ,
init :
function IndexedDBPromptHelper _init ( ) {
Services . obs . addObserver ( this , this . _permissionsPrompt , false ) ;
Services . obs . addObserver ( this , this . _quotaPrompt , false ) ;
2010-12-16 17:53:16 +00:00
Services . obs . addObserver ( this , this . _quotaCancel , false ) ;
2010-09-09 22:15:40 +00:00
} ,
uninit :
function IndexedDBPromptHelper _uninit ( ) {
2013-04-06 18:46:35 +00:00
Services . obs . removeObserver ( this , this . _permissionsPrompt ) ;
Services . obs . removeObserver ( this , this . _quotaPrompt ) ;
Services . obs . removeObserver ( this , this . _quotaCancel ) ;
2010-09-09 22:15:40 +00:00
} ,
observe :
function IndexedDBPromptHelper _observe ( subject , topic , data ) {
if ( topic != this . _permissionsPrompt &&
2010-12-16 17:53:16 +00:00
topic != this . _quotaPrompt &&
topic != this . _quotaCancel ) {
2010-09-09 22:15:40 +00:00
throw new Error ( "Unexpected topic!" ) ;
}
var requestor = subject . QueryInterface ( Ci . nsIInterfaceRequestor ) ;
var contentWindow = requestor . getInterface ( Ci . nsIDOMWindow ) ;
var contentDocument = contentWindow . document ;
var browserWindow =
OfflineApps . _getBrowserWindowForContentWindow ( contentWindow ) ;
2011-08-25 06:14:55 +00:00
if ( browserWindow != window ) {
2010-09-09 22:15:40 +00:00
// Must belong to some other window.
return ;
}
2011-08-25 06:14:55 +00:00
var browser =
OfflineApps . _getBrowserForContentWindow ( browserWindow , contentWindow ) ;
2010-09-09 22:15:40 +00:00
var host = contentDocument . documentURIObject . asciiHost ;
var message ;
var responseTopic ;
if ( topic == this . _permissionsPrompt ) {
message = gNavigatorBundle . getFormattedString ( "offlineApps.available" ,
[ host ] ) ;
responseTopic = this . _permissionsResponse ;
}
else if ( topic == this . _quotaPrompt ) {
message = gNavigatorBundle . getFormattedString ( "indexedDB.usage" ,
[ host , data ] ) ;
responseTopic = this . _quotaResponse ;
}
2010-12-16 17:53:16 +00:00
else if ( topic == this . _quotaCancel ) {
responseTopic = this . _quotaResponse ;
}
const hiddenTimeoutDuration = 30000 ; // 30 seconds
2013-02-02 17:49:35 +00:00
const firstTimeoutDuration = 300000 ; // 5 minutes
2010-12-16 17:53:16 +00:00
var timeoutId ;
2010-10-19 17:58:36 +00:00
2010-09-09 22:15:40 +00:00
var observer = requestor . getInterface ( Ci . nsIObserver ) ;
var mainAction = {
label : gNavigatorBundle . getString ( "offlineApps.allow" ) ,
accessKey : gNavigatorBundle . getString ( "offlineApps.allowAccessKey" ) ,
callback : function ( ) {
2010-12-16 17:53:16 +00:00
clearTimeout ( timeoutId ) ;
2010-09-09 22:15:40 +00:00
observer . observe ( null , responseTopic ,
Ci . nsIPermissionManager . ALLOW _ACTION ) ;
}
} ;
var secondaryActions = [
{
label : gNavigatorBundle . getString ( "offlineApps.never" ) ,
accessKey : gNavigatorBundle . getString ( "offlineApps.neverAccessKey" ) ,
callback : function ( ) {
2010-12-16 17:53:16 +00:00
clearTimeout ( timeoutId ) ;
2010-09-09 22:15:40 +00:00
observer . observe ( null , responseTopic ,
Ci . nsIPermissionManager . DENY _ACTION ) ;
}
}
] ;
2010-12-16 17:53:16 +00:00
// This will be set to the result of PopupNotifications.show() below, or to
// the result of PopupNotifications.getNotification() if this is a
// quotaCancel notification.
var notification ;
function timeoutNotification ( ) {
// Remove the notification.
if ( notification ) {
notification . remove ( ) ;
}
// Clear all of our timeout stuff. We may be called directly, not just
// when the timeout actually elapses.
clearTimeout ( timeoutId ) ;
// And tell the page that the popup timed out.
observer . observe ( null , responseTopic ,
Ci . nsIPermissionManager . UNKNOWN _ACTION ) ;
}
var options = {
eventCallback : function ( state ) {
// Don't do anything if the timeout has not been set yet.
if ( ! timeoutId ) {
return ;
}
// If the popup is being dismissed start the short timeout.
if ( state == "dismissed" ) {
clearTimeout ( timeoutId ) ;
timeoutId = setTimeout ( timeoutNotification , hiddenTimeoutDuration ) ;
return ;
}
// If the popup is being re-shown then clear the timeout allowing
// unlimited waiting.
if ( state == "shown" ) {
clearTimeout ( timeoutId ) ;
}
}
} ;
if ( topic == this . _quotaCancel ) {
notification = PopupNotifications . getNotification ( this . _quotaPrompt ,
browser ) ;
timeoutNotification ( ) ;
return ;
}
notification = PopupNotifications . show ( browser , topic , message ,
this . _notificationIcon , mainAction ,
secondaryActions , options ) ;
2010-09-09 22:15:40 +00:00
2010-12-16 17:53:16 +00:00
// Set the timeoutId after the popup has been created, and use the long
// timeout value. If the user doesn't notice the popup after this amount of
// time then it is most likely not visible and we want to alert the page.
timeoutId = setTimeout ( timeoutNotification , firstTimeoutDuration ) ;
2010-09-09 22:15:40 +00:00
}
} ;
2004-02-19 21:52:31 +00:00
function WindowIsClosing ( )
{
2010-10-11 03:04:14 +00:00
if ( TabView . isVisible ( ) ) {
TabView . hide ( ) ;
return false ;
}
2012-08-21 16:56:07 +00:00
if ( ! closeWindow ( false , warnAboutClosingWindow ) )
2009-01-22 07:54:26 +00:00
return false ;
2004-02-19 21:52:31 +00:00
2014-02-05 02:17:16 +00:00
// Bug 967873 - Proxy nsDocumentViewer::PermitUnload to the child process
if ( gMultiProcessBrowser )
return true ;
2012-08-21 16:56:07 +00:00
for ( let browser of gBrowser . browsers ) {
let ds = browser . docShell ;
2004-02-19 21:52:31 +00:00
if ( ds . contentViewer && ! ds . contentViewer . permitUnload ( ) )
2012-08-21 16:56:07 +00:00
return false ;
2004-02-19 21:52:31 +00:00
}
2012-08-21 16:56:07 +00:00
return true ;
2004-02-19 21:52:31 +00:00
}
2004-03-07 04:42:17 +00:00
2009-07-31 04:57:57 +00:00
/ * *
* Checks if this is the last full * browser * window around . If it is , this will
* be communicated like quitting . Otherwise , we warn about closing multiple tabs .
* @ returns true if closing can proceed , false if it got cancelled .
* /
function warnAboutClosingWindow ( ) {
2013-06-23 09:03:00 +00:00
// Popups aren't considered full browser windows; we also ignore private windows.
let isPBWindow = PrivateBrowsingUtils . isWindowPrivate ( window ) &&
! PrivateBrowsingUtils . permanentPrivateBrowsing ;
2012-07-05 08:30:59 +00:00
if ( ! isPBWindow && ! toolbar . visible )
2013-05-29 14:07:26 +00:00
return gBrowser . warnAboutClosingTabs ( gBrowser . closingTabsEnum . ALL ) ;
2009-07-31 04:57:57 +00:00
// Figure out if there's at least one other browser window around.
2010-01-28 18:31:45 +00:00
let e = Services . wm . getEnumerator ( "navigator:browser" ) ;
2012-07-05 08:30:59 +00:00
let otherPBWindowExists = false ;
2013-02-27 18:06:46 +00:00
let nonPopupPresent = false ;
2010-08-13 12:40:19 +00:00
while ( e . hasMoreElements ( ) ) {
2009-07-31 04:57:57 +00:00
let win = e . getNext ( ) ;
2013-09-13 21:29:51 +00:00
if ( ! win . closed && win != window ) {
2012-10-05 23:25:52 +00:00
if ( isPBWindow && PrivateBrowsingUtils . isWindowPrivate ( win ) )
2012-07-05 08:30:59 +00:00
otherPBWindowExists = true ;
if ( win . toolbar . visible )
2013-02-27 18:06:46 +00:00
nonPopupPresent = true ;
2012-07-05 08:30:59 +00:00
// If the current window is not in private browsing mode we don't need to
// look for other pb windows, we can leave the loop when finding the
// first non-popup window. If however the current window is in private
// browsing mode then we need at least one other pb and one non-popup
// window to break out early.
2013-02-27 18:06:46 +00:00
if ( ( ! isPBWindow || otherPBWindowExists ) && nonPopupPresent )
2012-07-05 08:30:59 +00:00
break ;
}
}
if ( isPBWindow && ! otherPBWindowExists ) {
let exitingCanceled = Cc [ "@mozilla.org/supports-PRBool;1" ] .
createInstance ( Ci . nsISupportsPRBool ) ;
exitingCanceled . data = false ;
Services . obs . notifyObservers ( exitingCanceled ,
"last-pb-context-exiting" ,
null ) ;
if ( exitingCanceled . data )
return false ;
2009-07-31 04:57:57 +00:00
}
2013-02-27 18:06:46 +00:00
2013-04-04 14:14:27 +00:00
if ( nonPopupPresent ) {
2013-05-29 14:07:26 +00:00
return isPBWindow || gBrowser . warnAboutClosingTabs ( gBrowser . closingTabsEnum . ALL ) ;
2013-04-04 14:14:27 +00:00
}
2009-07-31 04:57:57 +00:00
2010-01-28 18:31:45 +00:00
let os = Services . obs ;
2009-07-31 04:57:57 +00:00
let closingCanceled = Cc [ "@mozilla.org/supports-PRBool;1" ] .
createInstance ( Ci . nsISupportsPRBool ) ;
os . notifyObservers ( closingCanceled ,
2010-01-28 18:31:45 +00:00
"browser-lastwindow-close-requested" , null ) ;
2009-07-31 04:57:57 +00:00
if ( closingCanceled . data )
return false ;
os . notifyObservers ( null , "browser-lastwindow-close-granted" , null ) ;
# ifdef XP _MACOSX
2009-08-19 09:38:09 +00:00
// OS X doesn't quit the application when the last window is closed, but keeps
// the session alive. Hence don't prompt users to save tabs, but warn about
// closing multiple tabs.
2013-05-29 14:07:26 +00:00
return isPBWindow || gBrowser . warnAboutClosingTabs ( gBrowser . closingTabsEnum . ALL ) ;
2009-07-31 04:57:57 +00:00
# else
2009-08-19 06:46:08 +00:00
return true ;
2009-08-19 09:38:09 +00:00
# endif
2009-07-31 04:57:57 +00:00
}
2004-03-07 04:42:17 +00:00
var MailIntegration = {
2007-03-07 22:25:24 +00:00
sendLinkForWindow : function ( aWindow ) {
this . sendMessage ( aWindow . location . href ,
aWindow . document . title ) ;
2004-03-07 04:42:17 +00:00
} ,
2006-01-16 22:52:03 +00:00
sendMessage : function ( aBody , aSubject ) {
2004-03-07 04:42:17 +00:00
// generate a mailto url based on the url and the url's title
2006-01-16 22:52:03 +00:00
var mailtoUrl = "mailto:" ;
if ( aBody ) {
mailtoUrl += "?body=" + encodeURIComponent ( aBody ) ;
mailtoUrl += "&subject=" + encodeURIComponent ( aSubject ) ;
}
2004-03-07 04:42:17 +00:00
2009-07-29 05:55:03 +00:00
var uri = makeURI ( mailtoUrl ) ;
2004-03-07 04:42:17 +00:00
2006-01-16 22:52:03 +00:00
// now pass this uri to the operating system
2005-06-14 10:15:58 +00:00
this . _launchExternalUrl ( uri ) ;
2004-03-07 04:42:17 +00:00
} ,
2006-01-16 22:52:03 +00:00
// a generic method which can be used to pass arbitrary urls to the operating
// system.
2004-03-07 04:42:17 +00:00
// aURL --> a nsIURI which represents the url to launch
2006-01-16 22:52:03 +00:00
_launchExternalUrl : function ( aURL ) {
var extProtocolSvc =
2010-01-28 18:31:45 +00:00
Cc [ "@mozilla.org/uriloader/external-protocol-service;1" ]
. getService ( Ci . nsIExternalProtocolService ) ;
2004-03-07 04:42:17 +00:00
if ( extProtocolSvc )
extProtocolSvc . loadUrl ( aURL ) ;
}
2004-03-08 14:27:43 +00:00
} ;
2004-04-10 05:04:20 +00:00
2010-06-15 18:40:05 +00:00
function BrowserOpenAddonsMgr ( aView ) {
2011-02-12 09:02:48 +00:00
if ( aView ) {
let emWindow ;
let browserWindow ;
2012-11-26 16:18:25 +00:00
var receivePong = function receivePong ( aSubject , aTopic , aData ) {
2011-02-12 09:02:48 +00:00
let browserWin = aSubject . QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIWebNavigation )
. QueryInterface ( Ci . nsIDocShellTreeItem )
. rootTreeItem
. QueryInterface ( Ci . nsIInterfaceRequestor )
. getInterface ( Ci . nsIDOMWindow ) ;
if ( ! emWindow || browserWin == window /* favor the current window */ ) {
emWindow = aSubject ;
browserWindow = browserWin ;
}
}
Services . obs . addObserver ( receivePong , "EM-pong" , false ) ;
Services . obs . notifyObservers ( null , "EM-ping" , "" ) ;
Services . obs . removeObserver ( receivePong , "EM-pong" ) ;
if ( emWindow ) {
emWindow . loadView ( aView ) ;
browserWindow . gBrowser . selectedTab =
browserWindow . gBrowser . _getTabForContentWindow ( emWindow ) ;
emWindow . focus ( ) ;
return ;
}
}
var newLoad = ! switchToTabHavingURI ( "about:addons" , true ) ;
if ( aView ) {
// This must be a new load, else the ping/pong would have
// found the window above.
2012-04-16 22:35:34 +00:00
Services . obs . addObserver ( function observer ( aSubject , aTopic , aData ) {
Services . obs . removeObserver ( observer , aTopic ) ;
2011-02-12 09:02:48 +00:00
aSubject . loadView ( aView ) ;
} , "EM-loaded" , false ) ;
}
2004-04-10 05:04:20 +00:00
}
2013-07-01 13:24:32 +00:00
function GetSearchFieldBookmarkData ( node ) {
2008-04-08 18:41:04 +00:00
var charset = node . ownerDocument . characterSet ;
2013-07-01 13:24:32 +00:00
var formBaseURI = makeURI ( node . form . baseURI ,
charset ) ;
2005-09-28 22:42:44 +00:00
var formURI = makeURI ( node . form . getAttribute ( "action" ) ,
2008-04-08 18:41:04 +00:00
charset ,
2013-07-01 13:24:32 +00:00
formBaseURI ) ;
2005-09-28 22:42:44 +00:00
var spec = formURI . spec ;
2010-03-24 21:22:04 +00:00
var isURLEncoded =
2005-09-28 22:42:44 +00:00
( node . form . method . toUpperCase ( ) == "POST"
&& ( node . form . enctype == "application/x-www-form-urlencoded" ||
node . form . enctype == "" ) ) ;
2009-05-11 09:06:02 +00:00
var title = gNavigatorBundle . getFormattedString ( "addKeywordTitleAutoFill" ,
[ node . ownerDocument . title ] ) ;
var description = PlacesUIUtils . getDescriptionFromDocument ( node . ownerDocument ) ;
2005-09-28 22:42:44 +00:00
var formData = [ ] ;
2009-10-03 16:41:44 +00:00
function escapeNameValuePair ( aName , aValue , aIsFormUrlEncoded ) {
if ( aIsFormUrlEncoded )
return escape ( aName + "=" + aValue ) ;
else
return escape ( aName ) + "=" + escape ( aValue ) ;
}
2012-08-21 16:56:07 +00:00
for ( let el of node . form . elements ) {
2005-09-28 22:42:44 +00:00
if ( ! el . type ) // happens with fieldsets
continue ;
if ( el == node ) {
formData . push ( ( isURLEncoded ) ? escapeNameValuePair ( el . name , "%s" , true ) :
// Don't escape "%s", just append
escapeNameValuePair ( el . name , "" , false ) + "%s" ) ;
continue ;
2004-04-20 09:45:12 +00:00
}
2005-06-14 10:15:58 +00:00
2012-08-21 16:56:07 +00:00
let type = el . type . toLowerCase ( ) ;
2010-03-24 21:22:04 +00:00
2010-05-12 07:17:07 +00:00
if ( ( ( el instanceof HTMLInputElement && el . mozIsTextField ( true ) ) ||
type == "hidden" || type == "textarea" ) ||
2005-09-28 22:42:44 +00:00
( ( type == "checkbox" || type == "radio" ) && el . checked ) ) {
formData . push ( escapeNameValuePair ( el . name , el . value , isURLEncoded ) ) ;
} else if ( el instanceof HTMLSelectElement && el . selectedIndex >= 0 ) {
for ( var j = 0 ; j < el . options . length ; j ++ ) {
if ( el . options [ j ] . selected )
formData . push ( escapeNameValuePair ( el . name , el . options [ j ] . value ,
isURLEncoded ) ) ;
}
2004-04-20 09:45:12 +00:00
}
2004-04-10 05:04:20 +00:00
}
2005-09-28 22:42:44 +00:00
var postData ;
if ( isURLEncoded )
postData = formData . join ( "&" ) ;
else
spec += "?" + formData . join ( "&" ) ;
2013-07-01 13:24:32 +00:00
return {
spec : spec ,
title : title ,
description : description ,
postData : postData ,
charSet : charset
} ;
}
function AddKeywordForSearchField ( ) {
bookmarkData = GetSearchFieldBookmarkData ( document . popupNode ) ;
2011-10-27 09:11:43 +00:00
PlacesUIUtils . showBookmarkDialog ( { action : "add"
, type : "bookmark"
2013-07-01 13:24:32 +00:00
, uri : makeURI ( bookmarkData . spec )
, title : bookmarkData . title
, description : bookmarkData . description
2011-10-27 09:11:43 +00:00
, keyword : ""
2013-07-01 13:24:32 +00:00
, postData : bookmarkData . postData
, charSet : bookmarkData . charset
2011-10-27 09:11:43 +00:00
, hiddenRows : [ "location"
2011-11-15 19:42:27 +00:00
, "description"
, "tags"
, "loadInSidebar" ]
2011-11-11 21:39:26 +00:00
} , window ) ;
2004-04-10 05:04:20 +00:00
}
2005-08-08 15:52:59 +00:00
function SwitchDocumentDirection ( aWindow ) {
2013-04-14 12:37:48 +00:00
// document.dir can also be "auto", in which case it won't change
if ( aWindow . document . dir == "ltr" || aWindow . document . dir == "" ) {
aWindow . document . dir = "rtl" ;
} else if ( aWindow . document . dir == "rtl" ) {
aWindow . document . dir = "ltr" ;
}
2004-11-30 08:23:02 +00:00
for ( var run = 0 ; run < aWindow . frames . length ; run ++ )
2005-08-08 15:52:59 +00:00
SwitchDocumentDirection ( aWindow . frames [ run ] ) ;
2004-11-30 08:23:02 +00:00
}
2005-08-09 04:53:19 +00:00
function convertFromUnicode ( charset , str )
2005-08-22 23:44:55 +00:00
{
2005-08-09 04:53:19 +00:00
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 ) {
2010-03-24 21:22:04 +00:00
return null ;
2004-11-30 08:23:02 +00:00
}
2005-08-22 23:44:55 +00:00
}
2006-07-06 00:57:36 +00:00
/ * *
* Re - open a closed tab .
* @ param aIndex
2013-08-27 22:52:28 +00:00
* The index of the tab ( via SessionStore . getClosedTabData )
2008-09-28 06:38:09 +00:00
* @ returns a reference to the reopened tab .
2006-07-06 00:57:36 +00:00
* /
function undoCloseTab ( aIndex ) {
2006-07-22 02:17:45 +00:00
// wallpaper patch to prevent an unnecessary blank tab (bug 343895)
var blankTabToRemove = null ;
2013-03-28 00:54:59 +00:00
if ( gBrowser . tabs . length == 1 && isTabEmpty ( gBrowser . selectedTab ) )
2008-07-30 20:28:29 +00:00
blankTabToRemove = gBrowser . selectedTab ;
2006-07-22 02:17:45 +00:00
2013-12-13 21:55:49 +00:00
var tab = null ;
if ( SessionStore . getClosedTabCount ( window ) > ( aIndex || 0 ) ) {
2011-02-03 01:43:32 +00:00
TabView . prepareUndoCloseTab ( blankTabToRemove ) ;
2013-12-13 21:55:49 +00:00
tab = SessionStore . undoCloseTab ( window , aIndex || 0 ) ;
2011-01-27 18:15:18 +00:00
TabView . afterUndoCloseTab ( ) ;
2013-12-13 21:55:49 +00:00
if ( blankTabToRemove )
2008-09-28 06:38:09 +00:00
gBrowser . removeTab ( blankTabToRemove ) ;
}
2010-03-24 21:22:04 +00:00
2008-09-28 06:38:09 +00:00
return tab ;
2006-07-06 00:57:36 +00:00
}
2006-08-18 06:25:25 +00:00
2009-04-23 06:50:30 +00:00
/ * *
* Re - open a closed window .
* @ param aIndex
2013-08-27 22:52:28 +00:00
* The index of the window ( via SessionStore . getClosedWindowData )
2009-04-23 06:50:30 +00:00
* @ returns a reference to the reopened window .
* /
function undoCloseWindow ( aIndex ) {
2009-07-29 08:49:59 +00:00
let window = null ;
2013-08-27 22:52:28 +00:00
if ( SessionStore . getClosedWindowCount ( ) > ( aIndex || 0 ) )
window = SessionStore . undoCloseWindow ( aIndex || 0 ) ;
2009-04-23 06:50:30 +00:00
2009-07-29 08:49:59 +00:00
return window ;
2009-04-23 06:50:30 +00:00
}
2010-06-15 21:25:36 +00:00
/ *
* Determines if a tab is "empty" , usually used in the context of determining
* if it ' s ok to close the tab .
* /
function isTabEmpty ( aTab ) {
2012-03-29 09:36:34 +00:00
if ( aTab . hasAttribute ( "busy" ) )
return false ;
2010-06-15 21:25:36 +00:00
let browser = aTab . linkedBrowser ;
2012-03-29 09:36:34 +00:00
if ( ! isBlankPageURL ( browser . currentURI . spec ) )
return false ;
2013-04-23 02:47:52 +00:00
// Bug 863515 - Make content.opener checks work in electrolysis.
if ( ! gMultiProcessBrowser && browser . contentWindow . opener )
2012-03-29 09:36:34 +00:00
return false ;
if ( browser . sessionHistory && browser . sessionHistory . count >= 2 )
return false ;
return true ;
2010-06-15 21:25:36 +00:00
}
2010-08-02 23:37:56 +00:00
# ifdef MOZ _SERVICES _SYNC
function BrowserOpenSyncTabs ( ) {
switchToTabHavingURI ( "about:sync-tabs" , true ) ;
}
# endif
2006-08-18 06:25:25 +00:00
/ * *
* Format a URL
* eg :
2009-12-03 06:45:16 +00:00
* echo formatURL ( "https://addons.mozilla.org/%LOCALE%/%APP%/%VERSION%/" ) ;
* > https : //addons.mozilla.org/en-US/firefox/3.0a1/
2006-08-18 06:25:25 +00:00
*
2006-09-08 06:56:14 +00:00
* Currently supported built - ins are LOCALE , APP , and any value from nsIXULAppInfo , uppercased .
2006-08-18 06:25:25 +00:00
* /
2006-09-08 06:56:14 +00:00
function formatURL ( aFormat , aIsPref ) {
var formatter = Cc [ "@mozilla.org/toolkit/URLFormatterService;1" ] . getService ( Ci . nsIURLFormatter ) ;
return aIsPref ? formatter . formatURLPref ( aFormat ) : formatter . formatURL ( aFormat ) ;
2006-08-18 06:25:25 +00:00
}
2007-01-21 23:31:39 +00:00
2007-09-27 03:54:55 +00:00
/ * *
2008-09-02 09:11:22 +00:00
* Utility object to handle manipulations of the identity indicators in the UI
2007-09-27 03:54:55 +00:00
* /
2008-09-02 09:11:22 +00:00
var gIdentityHandler = {
2007-09-27 03:54:55 +00:00
// Mode strings used to control CSS display
2013-07-03 22:14:12 +00:00
IDENTITY _MODE _IDENTIFIED : "verifiedIdentity" , // High-quality identity information
IDENTITY _MODE _DOMAIN _VERIFIED : "verifiedDomain" , // Minimal SSL CA-signed domain verification
IDENTITY _MODE _UNKNOWN : "unknownIdentity" , // No trusted identity information
IDENTITY _MODE _MIXED _DISPLAY _LOADED : "unknownIdentity mixedContent mixedDisplayContent" , // SSL with unauthenticated display content
IDENTITY _MODE _MIXED _ACTIVE _LOADED : "unknownIdentity mixedContent mixedActiveContent" , // SSL with unauthenticated active (and perhaps also display) content
2013-09-09 22:55:49 +00:00
IDENTITY _MODE _MIXED _DISPLAY _LOADED _ACTIVE _BLOCKED : "unknownIdentity mixedContent mixedDisplayContentLoadedActiveBlocked" , // SSL with unauthenticated display content; unauthenticated active content is blocked.
2013-07-03 22:14:12 +00:00
IDENTITY _MODE _CHROMEUI : "chromeUI" , // Part of the product's UI
2007-09-27 03:54:55 +00:00
2008-03-07 14:54:41 +00:00
// Cache the most recent SSLStatus and Location seen in checkIdentity
2007-09-27 03:54:55 +00:00
_lastStatus : null ,
2013-07-10 02:45:07 +00:00
_lastUri : null ,
2010-11-24 20:29:56 +00:00
_mode : "unknownIdentity" ,
2007-09-27 03:54:55 +00:00
2008-09-02 09:11:22 +00:00
// smart getters
2009-09-11 17:28:55 +00:00
get _encryptionLabel ( ) {
delete this . _encryptionLabel ;
this . _encryptionLabel = { } ;
this . _encryptionLabel [ this . IDENTITY _MODE _DOMAIN _VERIFIED ] =
2013-07-03 22:14:12 +00:00
gNavigatorBundle . getString ( "identity.encrypted2" ) ;
2009-09-11 17:28:55 +00:00
this . _encryptionLabel [ this . IDENTITY _MODE _IDENTIFIED ] =
2013-07-03 22:14:12 +00:00
gNavigatorBundle . getString ( "identity.encrypted2" ) ;
2009-09-11 17:28:55 +00:00
this . _encryptionLabel [ this . IDENTITY _MODE _UNKNOWN ] =
gNavigatorBundle . getString ( "identity.unencrypted" ) ;
2013-07-03 22:14:12 +00:00
this . _encryptionLabel [ this . IDENTITY _MODE _MIXED _DISPLAY _LOADED ] =
gNavigatorBundle . getString ( "identity.mixed_display_loaded" ) ;
this . _encryptionLabel [ this . IDENTITY _MODE _MIXED _ACTIVE _LOADED ] =
2013-07-31 17:43:38 +00:00
gNavigatorBundle . getString ( "identity.mixed_active_loaded2" ) ;
2013-07-03 22:14:12 +00:00
this . _encryptionLabel [ this . IDENTITY _MODE _MIXED _DISPLAY _LOADED _ACTIVE _BLOCKED ] =
2013-09-15 06:36:22 +00:00
gNavigatorBundle . getString ( "identity.mixed_display_loaded" ) ;
2009-09-11 17:28:55 +00:00
return this . _encryptionLabel ;
2008-09-02 09:11:22 +00:00
} ,
get _identityPopup ( ) {
delete this . _identityPopup ;
return this . _identityPopup = document . getElementById ( "identity-popup" ) ;
} ,
get _identityBox ( ) {
delete this . _identityBox ;
return this . _identityBox = document . getElementById ( "identity-box" ) ;
} ,
get _identityPopupContentBox ( ) {
delete this . _identityPopupContentBox ;
return this . _identityPopupContentBox =
document . getElementById ( "identity-popup-content-box" ) ;
} ,
2013-06-29 03:22:41 +00:00
get _identityPopupChromeLabel ( ) {
delete this . _identityPopupChromeLabel ;
return this . _identityPopupChromeLabel =
document . getElementById ( "identity-popup-chromeLabel" ) ;
} ,
2008-09-02 09:11:22 +00:00
get _identityPopupContentHost ( ) {
delete this . _identityPopupContentHost ;
return this . _identityPopupContentHost =
document . getElementById ( "identity-popup-content-host" ) ;
} ,
get _identityPopupContentOwner ( ) {
delete this . _identityPopupContentOwner ;
return this . _identityPopupContentOwner =
document . getElementById ( "identity-popup-content-owner" ) ;
} ,
get _identityPopupContentSupp ( ) {
delete this . _identityPopupContentSupp ;
return this . _identityPopupContentSupp =
document . getElementById ( "identity-popup-content-supplemental" ) ;
} ,
get _identityPopupContentVerif ( ) {
delete this . _identityPopupContentVerif ;
return this . _identityPopupContentVerif =
document . getElementById ( "identity-popup-content-verifier" ) ;
} ,
get _identityPopupEncLabel ( ) {
delete this . _identityPopupEncLabel ;
return this . _identityPopupEncLabel =
document . getElementById ( "identity-popup-encryption-label" ) ;
} ,
get _identityIconLabel ( ) {
delete this . _identityIconLabel ;
return this . _identityIconLabel = document . getElementById ( "identity-icon-label" ) ;
} ,
2009-07-13 22:10:04 +00:00
get _overrideService ( ) {
delete this . _overrideService ;
return this . _overrideService = Cc [ "@mozilla.org/security/certoverride;1" ]
. getService ( Ci . nsICertOverrideService ) ;
} ,
2010-02-21 22:05:05 +00:00
get _identityIconCountryLabel ( ) {
delete this . _identityIconCountryLabel ;
return this . _identityIconCountryLabel = document . getElementById ( "identity-icon-country-label" ) ;
} ,
2012-04-23 19:35:35 +00:00
get _identityIcon ( ) {
delete this . _identityIcon ;
return this . _identityIcon = document . getElementById ( "page-proxy-favicon" ) ;
} ,
2013-07-02 00:42:48 +00:00
get _permissionsContainer ( ) {
delete this . _permissionsContainer ;
return this . _permissionsContainer = document . getElementById ( "identity-popup-permissions" ) ;
} ,
get _permissionList ( ) {
delete this . _permissionList ;
return this . _permissionList = document . getElementById ( "identity-popup-permission-list" ) ;
} ,
2008-09-02 09:11:22 +00:00
2007-11-19 14:02:17 +00:00
/ * *
2008-09-02 09:11:22 +00:00
* Rebuild cache of the elements that may or may not exist depending
* on whether there ' s a location bar .
2007-11-19 14:02:17 +00:00
* /
_cacheElements : function ( ) {
2008-09-02 09:11:22 +00:00
delete this . _identityBox ;
delete this . _identityIconLabel ;
2010-02-21 22:05:05 +00:00
delete this . _identityIconCountryLabel ;
2012-04-23 19:35:35 +00:00
delete this . _identityIcon ;
2013-07-02 00:42:48 +00:00
delete this . _permissionsContainer ;
delete this . _permissionList ;
2007-11-19 14:02:17 +00:00
this . _identityBox = document . getElementById ( "identity-box" ) ;
this . _identityIconLabel = document . getElementById ( "identity-icon-label" ) ;
2010-02-21 22:05:05 +00:00
this . _identityIconCountryLabel = document . getElementById ( "identity-icon-country-label" ) ;
2012-04-23 19:35:35 +00:00
this . _identityIcon = document . getElementById ( "page-proxy-favicon" ) ;
2013-07-02 00:42:48 +00:00
this . _permissionsContainer = document . getElementById ( "identity-popup-permissions" ) ;
this . _permissionList = document . getElementById ( "identity-popup-permission-list" ) ;
2007-11-19 14:02:17 +00:00
} ,
2013-10-09 13:31:33 +00:00
/ * *
* Handler for commands on the help button in the "identity-popup" panel .
* /
handleHelpCommand : function ( event ) {
openHelpLink ( "secure-connection" ) ;
this . _identityPopup . hidePopup ( ) ;
} ,
2007-09-27 03:54:55 +00:00
/ * *
2008-02-06 18:12:54 +00:00
* Handler for mouseclicks on the "More Information" button in the
* "identity-popup" panel .
2007-09-27 03:54:55 +00:00
* /
handleMoreInfoClick : function ( event ) {
2008-02-06 18:12:54 +00:00
displaySecurityInfo ( ) ;
event . stopPropagation ( ) ;
2013-07-02 00:42:48 +00:00
this . _identityPopup . hidePopup ( ) ;
2007-09-27 03:54:55 +00:00
} ,
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
/ * *
* Helper to parse out the important parts of _lastStatus ( of the SSL cert in
* particular ) for use in constructing identity UI strings
* /
getIdentityData : function ( ) {
var result = { } ;
var status = this . _lastStatus . QueryInterface ( Components . interfaces . nsISSLStatus ) ;
var cert = status . serverCert ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Human readable name of Subject
result . subjectOrg = cert . organization ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// SubjectName fields, broken up for individual access
if ( cert . subjectName ) {
result . subjectNameFields = { } ;
cert . subjectName . split ( "," ) . forEach ( function ( v ) {
var field = v . split ( "=" ) ;
this [ field [ 0 ] ] = field [ 1 ] ;
} , result . subjectNameFields ) ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Call out city, state, and country specifically
result . city = result . subjectNameFields . L ;
result . state = result . subjectNameFields . ST ;
result . country = result . subjectNameFields . C ;
}
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Human readable name of Certificate Authority
result . caOrg = cert . issuerOrganization || cert . issuerCommonName ;
2008-01-30 04:21:53 +00:00
result . cert = cert ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
return result ;
} ,
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
/ * *
* Determine the identity of the page being displayed by examining its SSL cert
* ( if available ) and , if necessary , update the UI to reflect this . Intended to
2007-10-22 03:30:23 +00:00
* be called by onSecurityChange
2010-03-24 21:22:04 +00:00
*
2007-09-27 03:54:55 +00:00
* @ param PRUint32 state
2013-07-10 02:45:07 +00:00
* @ param nsIURI uri The address for which the UI should be updated .
2007-09-27 03:54:55 +00:00
* /
2013-07-10 02:45:07 +00:00
checkIdentity : function ( state , uri ) {
2007-09-27 03:54:55 +00:00
var currentStatus = gBrowser . securityUI
. QueryInterface ( Components . interfaces . nsISSLStatusProvider )
. SSLStatus ;
this . _lastStatus = currentStatus ;
2013-07-10 02:45:07 +00:00
this . _lastUri = uri ;
2009-09-11 17:28:55 +00:00
let nsIWebProgressListener = Ci . nsIWebProgressListener ;
2013-07-10 02:45:07 +00:00
// For some URIs like data: we can't get a host and so can't do
2013-11-19 16:11:25 +00:00
// anything useful here.
2013-07-10 02:45:07 +00:00
let unknown = false ;
try {
uri . host ;
} catch ( e ) { unknown = true ; }
2013-11-19 16:11:25 +00:00
// Chrome URIs however get special treatment. Some chrome URIs are
// whitelisted to provide a positive security signal to the user.
2014-03-06 02:56:20 +00:00
let whitelist = /^about:(accounts|addons|app-manager|config|crashes|customizing|healthreport|home|newaddon|permissions|preferences|privatebrowsing|sessionrestore|support|welcomeback)/i ;
let isChromeUI = uri . schemeIs ( "about" ) && whitelist . test ( uri . spec ) ;
if ( isChromeUI ) {
2010-11-24 20:29:56 +00:00
this . setMode ( this . IDENTITY _MODE _CHROMEUI ) ;
2013-07-10 02:45:07 +00:00
} else if ( unknown ) {
this . setMode ( this . IDENTITY _MODE _UNKNOWN ) ;
2013-01-29 19:51:17 +00:00
} else if ( state & nsIWebProgressListener . STATE _IDENTITY _EV _TOPLEVEL ) {
2007-09-27 03:54:55 +00:00
this . setMode ( this . IDENTITY _MODE _IDENTIFIED ) ;
2013-01-29 19:51:17 +00:00
} else if ( state & nsIWebProgressListener . STATE _IS _SECURE ) {
2007-09-27 03:54:55 +00:00
this . setMode ( this . IDENTITY _MODE _DOMAIN _VERIFIED ) ;
2013-01-29 19:51:17 +00:00
} else if ( state & nsIWebProgressListener . STATE _IS _BROKEN ) {
2013-02-17 04:08:53 +00:00
if ( ( state & nsIWebProgressListener . STATE _LOADED _MIXED _ACTIVE _CONTENT ) &&
gPrefService . getBoolPref ( "security.mixed_content.block_active_content" ) ) {
2013-07-03 22:14:12 +00:00
this . setMode ( this . IDENTITY _MODE _MIXED _ACTIVE _LOADED ) ;
} else if ( ( state & nsIWebProgressListener . STATE _BLOCKED _MIXED _ACTIVE _CONTENT ) &&
gPrefService . getBoolPref ( "security.mixed_content.block_active_content" ) ) {
this . setMode ( this . IDENTITY _MODE _MIXED _DISPLAY _LOADED _ACTIVE _BLOCKED ) ;
2013-01-29 19:51:17 +00:00
} else {
2013-07-03 22:14:12 +00:00
this . setMode ( this . IDENTITY _MODE _MIXED _DISPLAY _LOADED ) ;
2013-01-29 19:51:17 +00:00
}
} else {
2007-09-27 03:54:55 +00:00
this . setMode ( this . IDENTITY _MODE _UNKNOWN ) ;
2013-01-29 19:51:17 +00:00
}
2013-01-30 08:04:28 +00:00
// Ensure the doorhanger is shown when mixed active content is blocked.
if ( state & nsIWebProgressListener . STATE _BLOCKED _MIXED _ACTIVE _CONTENT )
this . showMixedContentDoorhanger ( ) ;
} ,
/ * *
* Display the Mixed Content Blocker doohanger , providing an option
* to the user to override mixed content blocking
* /
showMixedContentDoorhanger : function ( ) {
// If we've already got an active notification, bail out to avoid showing it repeatedly.
if ( PopupNotifications . getNotification ( "mixed-content-blocked" , gBrowser . selectedBrowser ) )
return ;
let brandBundle = document . getElementById ( "bundle_brand" ) ;
let brandShortName = brandBundle . getString ( "brandShortName" ) ;
let messageString = gNavigatorBundle . getFormattedString ( "mixedContentBlocked.message" , [ brandShortName ] ) ;
let action = {
label : gNavigatorBundle . getString ( "mixedContentBlocked.keepBlockingButton.label" ) ,
accessKey : gNavigatorBundle . getString ( "mixedContentBlocked.keepBlockingButton.accesskey" ) ,
callback : function ( ) { /* NOP */ }
} ;
let secondaryActions = [
{
label : gNavigatorBundle . getString ( "mixedContentBlocked.unblock.label" ) ,
accessKey : gNavigatorBundle . getString ( "mixedContentBlocked.unblock.accesskey" ) ,
callback : function ( ) {
2013-09-05 23:18:04 +00:00
// Use telemetry to measure how often unblocking happens
const kMIXED _CONTENT _UNBLOCK _EVENT = 2 ;
let histogram =
Services . telemetry . getHistogramById ( "MIXED_CONTENT_UNBLOCK_COUNTER" ) ;
histogram . add ( kMIXED _CONTENT _UNBLOCK _EVENT ) ;
2013-01-30 08:04:28 +00:00
// Reload the page with the content unblocked
BrowserReloadWithFlags ( nsIWebNavigation . LOAD _FLAGS _ALLOW _MIXED _CONTENT ) ;
}
}
] ;
let options = {
dismissed : true ,
2014-02-19 03:05:34 +00:00
learnMoreURL : Services . urlFormatter . formatURLPref ( "app.support.baseURL" ) + "mixed-content" ,
2013-01-30 08:04:28 +00:00
} ;
PopupNotifications . show ( gBrowser . selectedBrowser , "mixed-content-blocked" ,
messageString , "mixed-content-blocked-notification-icon" ,
action , secondaryActions , options ) ;
2007-09-27 03:54:55 +00:00
} ,
2010-03-24 21:22:04 +00:00
2008-03-07 14:54:41 +00:00
/ * *
* Return the eTLD + 1 version of the current hostname
* /
getEffectiveHost : function ( ) {
2010-08-27 15:12:02 +00:00
if ( ! this . _IDNService )
this . _IDNService = Cc [ "@mozilla.org/network/idn-service;1" ]
. getService ( Ci . nsIIDNService ) ;
2008-03-07 14:54:41 +00:00
try {
2010-08-27 15:12:02 +00:00
let baseDomain =
2013-07-10 02:45:07 +00:00
Services . eTLD . getBaseDomainFromHost ( this . _lastUri . host ) ;
2010-08-27 15:12:02 +00:00
return this . _IDNService . convertToDisplayIDN ( baseDomain , { } ) ;
2008-03-07 14:54:41 +00:00
} catch ( e ) {
2013-07-10 02:45:07 +00:00
// If something goes wrong (e.g. host is an IP address) just fail back
2008-03-07 14:54:41 +00:00
// to the full domain.
2013-07-10 02:45:07 +00:00
return this . _lastUri . host ;
2008-03-07 14:54:41 +00:00
}
} ,
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
/ * *
* Update the UI to reflect the specified mode , which should be one of the
* IDENTITY _MODE _ * constants .
* /
setMode : function ( newMode ) {
2007-11-19 14:02:17 +00:00
if ( ! this . _identityBox ) {
// No identity box means the identity box is not visible, in which
// case there's nothing to do.
return ;
}
2013-07-02 00:42:48 +00:00
this . _identityPopup . className = newMode ;
2007-11-19 14:02:17 +00:00
this . _identityBox . className = newMode ;
2007-09-27 03:54:55 +00:00
this . setIdentityMessages ( newMode ) ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Update the popup too, if it's open
if ( this . _identityPopup . state == "open" )
this . setPopupMessages ( newMode ) ;
2010-11-24 20:29:56 +00:00
this . _mode = newMode ;
2007-09-27 03:54:55 +00:00
} ,
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
/ * *
* Set up the messages for the primary identity UI based on the specified mode ,
* and the details of the SSL cert , where applicable
*
* @ param newMode The newly set identity mode . Should be one of the IDENTITY _MODE _ * constants .
* /
setIdentityMessages : function ( newMode ) {
2012-05-04 18:37:20 +00:00
let icon _label = "" ;
let tooltip = "" ;
let icon _country _label = "" ;
let icon _labels _dir = "ltr" ;
switch ( newMode ) {
case this . IDENTITY _MODE _DOMAIN _VERIFIED : {
let iData = this . getIdentityData ( ) ;
2010-03-24 21:22:04 +00:00
2008-01-30 04:21:53 +00:00
// Verifier is either the CA Org, for a normal cert, or a special string
// for certs that are trusted because of a security exception.
2012-05-04 18:37:20 +00:00
tooltip = gNavigatorBundle . getFormattedString ( "identity.identified.verifier" ,
[ iData . caOrg ] ) ;
2010-03-24 21:22:04 +00:00
2013-07-10 02:45:07 +00:00
// This can't throw, because URI's with a host that throw don't end up in this case.
let host = this . _lastUri . host ;
let port = 443 ;
try {
if ( this . _lastUri . port > 0 )
port = this . _lastUri . port ;
} catch ( e ) { }
if ( this . _overrideService . hasMatchingOverride ( host , port , iData . cert , { } , { } ) )
2009-07-13 22:10:04 +00:00
tooltip = gNavigatorBundle . getString ( "identity.identified.verified_by_you" ) ;
2013-07-10 02:45:07 +00:00
2012-05-04 18:37:20 +00:00
break ; }
case this . IDENTITY _MODE _IDENTIFIED : {
2007-09-27 03:54:55 +00:00
// If it's identified, then we can populate the dialog with credentials
2012-05-04 18:37:20 +00:00
let iData = this . getIdentityData ( ) ;
2009-07-13 22:10:04 +00:00
tooltip = gNavigatorBundle . getFormattedString ( "identity.identified.verifier" ,
[ iData . caOrg ] ) ;
2010-02-21 22:05:05 +00:00
icon _label = iData . subjectOrg ;
2007-09-27 03:54:55 +00:00
if ( iData . country )
2010-02-21 22:05:05 +00:00
icon _country _label = "(" + iData . country + ")" ;
2012-05-04 18:37:20 +00:00
2010-02-21 22:05:05 +00:00
// If the organization name starts with an RTL character, then
// swap the positions of the organization and country code labels.
// The Unicode ranges reflect the definition of the UCS2_CHAR_IS_BIDI
// macro in intl/unicharutil/util/nsBidiUtils.h. When bug 218823 gets
// fixed, this test should be replaced by one adhering to the
// Unicode Bidirectional Algorithm proper (at the paragraph level).
icon _labels _dir = /^[\u0590-\u08ff\ufb1d-\ufdff\ufe70-\ufefc]/ . test ( icon _label ) ?
"rtl" : "ltr" ;
2012-05-04 18:37:20 +00:00
break ; }
case this . IDENTITY _MODE _CHROMEUI :
2013-06-29 03:22:41 +00:00
let brandBundle = document . getElementById ( "bundle_brand" ) ;
icon _label = brandBundle . getString ( "brandShortName" ) ;
2012-05-04 18:37:20 +00:00
break ;
default :
2009-07-13 22:10:04 +00:00
tooltip = gNavigatorBundle . getString ( "identity.unknown.tooltip" ) ;
2007-09-27 03:54:55 +00:00
}
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Push the appropriate strings out to the UI
this . _identityBox . tooltipText = tooltip ;
this . _identityIconLabel . value = icon _label ;
2010-02-21 22:05:05 +00:00
this . _identityIconCountryLabel . value = icon _country _label ;
// Set cropping and direction
this . _identityIconLabel . crop = icon _country _label ? "end" : "center" ;
this . _identityIconLabel . parentNode . style . direction = icon _labels _dir ;
// Hide completely if the organization label is empty
2010-07-27 14:54:05 +00:00
this . _identityIconLabel . parentNode . collapsed = icon _label ? false : true ;
2007-09-27 03:54:55 +00:00
} ,
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
/ * *
* Set up the title and content messages for the identity message popup ,
* based on the specified mode , and the details of the SSL cert , where
* applicable
*
* @ param newMode The newly set identity mode . Should be one of the IDENTITY _MODE _ * constants .
* /
setPopupMessages : function ( newMode ) {
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
this . _identityPopup . className = newMode ;
this . _identityPopupContentBox . className = newMode ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Set the static strings up front
2009-09-11 17:28:55 +00:00
this . _identityPopupEncLabel . textContent = this . _encryptionLabel [ newMode ] ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Initialize the optional strings to empty values
2012-05-04 18:37:20 +00:00
let supplemental = "" ;
let verifier = "" ;
let host = "" ;
let owner = "" ;
2010-03-24 21:22:04 +00:00
2012-05-04 18:37:20 +00:00
switch ( newMode ) {
case this . IDENTITY _MODE _DOMAIN _VERIFIED :
host = this . getEffectiveHost ( ) ;
owner = gNavigatorBundle . getString ( "identity.ownerUnknown2" ) ;
2008-01-30 04:21:53 +00:00
verifier = this . _identityBox . tooltipText ;
2012-05-04 18:37:20 +00:00
break ;
case this . IDENTITY _MODE _IDENTIFIED : {
2007-09-27 03:54:55 +00:00
// If it's identified, then we can populate the dialog with credentials
2012-05-04 18:37:20 +00:00
let iData = this . getIdentityData ( ) ;
2008-03-07 14:54:41 +00:00
host = this . getEffectiveHost ( ) ;
2010-03-24 21:22:04 +00:00
owner = iData . subjectOrg ;
2008-01-30 04:21:53 +00:00
verifier = this . _identityBox . tooltipText ;
2007-09-27 03:54:55 +00:00
// Build an appropriate supplemental block out of whatever location data we have
if ( iData . city )
2010-03-24 21:22:04 +00:00
supplemental += iData . city + "\n" ;
2007-09-27 03:54:55 +00:00
if ( iData . state && iData . country )
2009-07-13 22:10:04 +00:00
supplemental += gNavigatorBundle . getFormattedString ( "identity.identified.state_and_country" ,
[ iData . state , iData . country ] ) ;
2007-09-27 03:54:55 +00:00
else if ( iData . state ) // State only
supplemental += iData . state ;
else if ( iData . country ) // Country only
supplemental += iData . country ;
2012-05-04 18:37:20 +00:00
break ; }
2013-06-29 03:22:41 +00:00
case this . IDENTITY _MODE _CHROMEUI : {
let brandBundle = document . getElementById ( "bundle_brand" ) ;
let brandShortName = brandBundle . getString ( "brandShortName" ) ;
this . _identityPopupChromeLabel . textContent = gNavigatorBundle . getFormattedString ( "identity.chrome" ,
[ brandShortName ] ) ;
break ; }
2007-09-27 03:54:55 +00:00
}
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Push the appropriate strings out to the UI
2008-01-30 04:21:53 +00:00
this . _identityPopupContentHost . textContent = host ;
this . _identityPopupContentOwner . textContent = owner ;
2007-09-27 03:54:55 +00:00
this . _identityPopupContentSupp . textContent = supplemental ;
this . _identityPopupContentVerif . textContent = verifier ;
} ,
2008-01-23 23:49:10 +00:00
2007-09-27 03:54:55 +00:00
/ * *
2010-03-24 21:22:04 +00:00
* Click handler for the identity - box element in primary chrome .
2007-09-27 03:54:55 +00:00
* /
2008-01-23 23:49:10 +00:00
handleIdentityButtonEvent : function ( event ) {
2007-11-06 18:48:58 +00:00
event . stopPropagation ( ) ;
2010-03-24 21:22:04 +00:00
2008-01-23 23:49:10 +00:00
if ( ( event . type == "click" && event . button != 0 ) ||
( event . type == "keypress" && event . charCode != KeyEvent . DOM _VK _SPACE &&
2013-02-22 11:57:31 +00:00
event . keyCode != KeyEvent . DOM _VK _RETURN ) ) {
2008-01-23 23:49:10 +00:00
return ; // Left click, space or enter only
2013-02-22 11:57:31 +00:00
}
2007-11-06 18:48:58 +00:00
2013-06-29 03:22:41 +00:00
// Don't allow left click, space or enter if the location has been modified.
if ( gURLBar . getAttribute ( "pageproxystate" ) != "valid" ) {
2010-11-24 20:29:56 +00:00
return ;
2013-02-22 11:57:31 +00:00
}
2010-11-24 20:29:56 +00:00
2007-09-27 03:54:55 +00:00
// Make sure that the display:none style we set in xul is removed now that
// the popup is actually needed
this . _identityPopup . hidden = false ;
2010-03-24 21:22:04 +00:00
2007-09-27 03:54:55 +00:00
// Update the popup strings
this . setPopupMessages ( this . _identityBox . className ) ;
2010-03-24 21:22:04 +00:00
2013-07-02 00:42:48 +00:00
this . updateSitePermissions ( ) ;
2009-03-02 20:01:03 +00:00
// Add the "open" attribute to the identity box for styling
this . _identityBox . setAttribute ( "open" , "true" ) ;
var self = this ;
2012-04-16 22:35:34 +00:00
this . _identityPopup . addEventListener ( "popuphidden" , function onPopupHidden ( e ) {
e . currentTarget . removeEventListener ( "popuphidden" , onPopupHidden , false ) ;
2009-03-02 20:01:03 +00:00
self . _identityBox . removeAttribute ( "open" ) ;
} , false ) ;
2007-09-27 03:54:55 +00:00
// Now open the popup, anchored off the primary chrome element
2012-04-23 19:35:35 +00:00
this . _identityPopup . openPopup ( this . _identityIcon , "bottomcenter topleft" ) ;
2010-09-08 15:10:46 +00:00
} ,
2012-02-02 11:06:42 +00:00
onPopupShown : function ( event ) {
document . getElementById ( 'identity-popup-more-info-button' ) . focus ( ) ;
2013-07-02 00:42:48 +00:00
this . _identityPopup . addEventListener ( "blur" , this , true ) ;
this . _identityPopup . addEventListener ( "popuphidden" , this ) ;
2012-02-02 11:06:42 +00:00
} ,
2010-09-08 15:10:46 +00:00
onDragStart : function ( event ) {
if ( gURLBar . getAttribute ( "pageproxystate" ) != "valid" )
return ;
var value = content . location . href ;
var urlString = value + "\n" + content . document . title ;
var htmlString = "<a href=\"" + value + "\">" + value + "</a>" ;
var dt = event . dataTransfer ;
dt . setData ( "text/x-moz-url" , urlString ) ;
dt . setData ( "text/uri-list" , value ) ;
dt . setData ( "text/plain" , value ) ;
dt . setData ( "text/html" , htmlString ) ;
2011-03-18 21:21:02 +00:00
dt . setDragImage ( gProxyFavIcon , 16 , 16 ) ;
2013-07-02 00:42:48 +00:00
} ,
handleEvent : function ( event ) {
switch ( event . type ) {
case "blur" :
// Focus hasn't moved yet, need to wait until after the blur event.
setTimeout ( ( ) => {
if ( document . activeElement &&
document . activeElement . compareDocumentPosition ( this . _identityPopup ) &
Node . DOCUMENT _POSITION _CONTAINS )
return ;
this . _identityPopup . hidePopup ( ) ;
} , 0 ) ;
break ;
case "popuphidden" :
this . _identityPopup . removeEventListener ( "blur" , this , true ) ;
this . _identityPopup . removeEventListener ( "popuphidden" , this ) ;
break ;
}
} ,
updateSitePermissions : function ( ) {
while ( this . _permissionList . hasChildNodes ( ) )
this . _permissionList . removeChild ( this . _permissionList . lastChild ) ;
let uri = gBrowser . currentURI ;
for ( let permission of SitePermissions . listPermissions ( ) ) {
let state = SitePermissions . get ( uri , permission ) ;
if ( state == SitePermissions . UNKNOWN )
continue ;
let item = this . _createPermissionItem ( permission , state ) ;
this . _permissionList . appendChild ( item ) ;
}
this . _permissionsContainer . hidden = ! this . _permissionList . hasChildNodes ( ) ;
} ,
2013-08-29 13:59:32 +00:00
setPermission : function ( aPermission , aState ) {
if ( aState == SitePermissions . getDefault ( aPermission ) )
SitePermissions . remove ( gBrowser . currentURI , aPermission ) ;
else
SitePermissions . set ( gBrowser . currentURI , aPermission , aState ) ;
} ,
2013-07-02 00:42:48 +00:00
_createPermissionItem : function ( aPermission , aState ) {
let menulist = document . createElement ( "menulist" ) ;
let menupopup = document . createElement ( "menupopup" ) ;
for ( let state of SitePermissions . getAvailableStates ( aPermission ) ) {
let menuitem = document . createElement ( "menuitem" ) ;
menuitem . setAttribute ( "value" , state ) ;
2013-07-16 07:59:34 +00:00
menuitem . setAttribute ( "label" , SitePermissions . getStateLabel ( aPermission , state ) ) ;
2013-07-02 00:42:48 +00:00
menupopup . appendChild ( menuitem ) ;
}
menulist . appendChild ( menupopup ) ;
menulist . setAttribute ( "value" , aState ) ;
2013-08-29 13:59:32 +00:00
menulist . setAttribute ( "oncommand" , "gIdentityHandler.setPermission('" +
2013-07-02 00:42:48 +00:00
aPermission + "', this.value)" ) ;
menulist . setAttribute ( "id" , "identity-popup-permission:" + aPermission ) ;
let label = document . createElement ( "label" ) ;
label . setAttribute ( "flex" , "1" ) ;
label . setAttribute ( "control" , menulist . getAttribute ( "id" ) ) ;
label . setAttribute ( "value" , SitePermissions . getPermissionLabel ( aPermission ) ) ;
let container = document . createElement ( "hbox" ) ;
container . setAttribute ( "align" , "center" ) ;
container . appendChild ( label ) ;
container . appendChild ( menulist ) ;
return container ;
2007-09-27 03:54:55 +00:00
}
} ;
2008-08-11 23:31:57 +00:00
function getNotificationBox ( aWindow ) {
var foundBrowser = gBrowser . getBrowserForDocument ( aWindow . document ) ;
if ( foundBrowser )
return gBrowser . getNotificationBox ( foundBrowser )
return null ;
} ;
2010-11-20 05:23:25 +00:00
function getTabModalPromptBox ( aWindow ) {
var foundBrowser = gBrowser . getBrowserForDocument ( aWindow . document ) ;
if ( foundBrowser )
2010-11-22 10:38:02 +00:00
return gBrowser . getTabModalPromptBox ( foundBrowser ) ;
2010-11-20 05:23:25 +00:00
return null ;
} ;
2008-07-30 20:34:08 +00:00
/* DEPRECATED */
function getBrowser ( ) gBrowser ;
function getNavToolbox ( ) gNavToolbox ;
2008-11-03 23:22:22 +00:00
2012-10-08 03:30:32 +00:00
let gPrivateBrowsingUI = {
init : function PBUI _init ( ) {
// Do nothing for normal windows
if ( ! PrivateBrowsingUtils . isWindowPrivate ( window ) ) {
return ;
}
// Disable the Clear Recent History... menu item when in PB mode
// temporary fix until bug 463607 is fixed
document . getElementById ( "Tools:Sanitize" ) . setAttribute ( "disabled" , "true" ) ;
if ( window . location . href == getBrowserURL ( ) ) {
2013-03-13 19:15:05 +00:00
// Adjust the window's title
2012-10-08 03:30:32 +00:00
let docElement = document . documentElement ;
2013-03-24 10:15:53 +00:00
if ( ! PrivateBrowsingUtils . permanentPrivateBrowsing ) {
docElement . setAttribute ( "title" ,
docElement . getAttribute ( "title_privatebrowsing" ) ) ;
docElement . setAttribute ( "titlemodifier" ,
docElement . getAttribute ( "titlemodifier_privatebrowsing" ) ) ;
}
2013-01-07 18:24:08 +00:00
docElement . setAttribute ( "privatebrowsingmode" ,
PrivateBrowsingUtils . permanentPrivateBrowsing ? "permanent" : "temporary" ) ;
2012-10-08 03:30:32 +00:00
gBrowser . updateTitlebar ( ) ;
2013-03-13 19:15:05 +00:00
if ( PrivateBrowsingUtils . permanentPrivateBrowsing ) {
// Adjust the New Window menu entries
[
{ normal : "menu_newNavigator" , private : "menu_newPrivateWindow" } ,
] . forEach ( function ( menu ) {
let newWindow = document . getElementById ( menu . normal ) ;
let newPrivateWindow = document . getElementById ( menu . private ) ;
if ( newWindow && newPrivateWindow ) {
newPrivateWindow . hidden = true ;
newWindow . label = newPrivateWindow . label ;
newWindow . accessKey = newPrivateWindow . accessKey ;
newWindow . command = newPrivateWindow . command ;
}
} ) ;
}
2012-10-08 03:30:32 +00:00
}
2012-11-30 07:40:47 +00:00
2013-04-23 06:00:38 +00:00
if ( gURLBar &&
! PrivateBrowsingUtils . permanentPrivateBrowsing ) {
// Disable switch to tab autocompletion for private windows
// (not for "Always use private browsing" mode)
2012-11-30 07:40:47 +00:00
gURLBar . setAttribute ( "autocompletesearchparam" , "" ) ;
}
2012-10-08 03:30:32 +00:00
}
} ;
2014-02-11 17:01:08 +00:00
let gRemoteTabsUI = {
init : function ( ) {
if ( window . location . href != getBrowserURL ( ) ) {
return ;
}
let remoteTabs = gPrefService . getBoolPref ( "browser.tabs.remote" ) ;
let autostart = gPrefService . getBoolPref ( "browser.tabs.remote.autostart" ) ;
let newRemoteWindow = document . getElementById ( "menu_newRemoteWindow" ) ;
let newNonRemoteWindow = document . getElementById ( "menu_newNonRemoteWindow" ) ;
if ( ! remoteTabs ) {
newRemoteWindow . hidden = true ;
newNonRemoteWindow . hidden = true ;
return ;
}
newRemoteWindow . hidden = autostart ;
newNonRemoteWindow . hidden = ! autostart ;
}
} ;
2010-03-26 21:59:02 +00:00
2010-04-29 17:17:06 +00:00
/ * *
* Switch to a tab that has a given URI , and focusses its browser window .
* If a matching tab is in this window , it will be switched to . Otherwise , other
* windows will be searched .
*
* @ param aURI
* URI to search for
* @ param aOpenNew
2011-02-22 19:02:22 +00:00
* True to open a new tab and switch to it , if no existing tab is found .
* If no suitable window is found , a new one will be opened .
2014-03-04 15:24:00 +00:00
* @ param aOpenParams
* If switching to this URI results in us opening a tab , aOpenParams
* will be the parameter object that gets passed to openUILinkIn . Please
* see the documentation for openUILinkIn to see what parameters can be
* passed via this object .
2011-02-12 09:02:48 +00:00
* @ return True if an existing tab was found , false otherwise
2010-04-29 17:17:06 +00:00
* /
2014-03-04 15:24:00 +00:00
function switchToTabHavingURI ( aURI , aOpenNew , aOpenParams ) {
2011-02-22 19:02:22 +00:00
// This will switch to the tab in aWindow having aURI, if present.
2010-03-26 21:59:02 +00:00
function switchIfURIInWindow ( aWindow ) {
2012-11-30 07:40:47 +00:00
// Only switch to the tab if neither the source and desination window are
2013-04-23 06:00:38 +00:00
// private and they are not in permanent private borwsing mode
if ( ( PrivateBrowsingUtils . isWindowPrivate ( window ) ||
PrivateBrowsingUtils . isWindowPrivate ( aWindow ) ) &&
! PrivateBrowsingUtils . permanentPrivateBrowsing ) {
2012-11-30 07:40:47 +00:00
return false ;
}
2010-03-26 21:59:02 +00:00
let browsers = aWindow . gBrowser . browsers ;
for ( let i = 0 ; i < browsers . length ; i ++ ) {
let browser = browsers [ i ] ;
if ( browser . currentURI . equals ( aURI ) ) {
2010-06-15 21:25:36 +00:00
// Focus the matching window & tab
2010-03-26 21:59:02 +00:00
aWindow . focus ( ) ;
aWindow . gBrowser . tabContainer . selectedIndex = i ;
return true ;
}
}
return false ;
}
// This can be passed either nsIURI or a string.
if ( ! ( aURI instanceof Ci . nsIURI ) )
2011-02-22 19:02:22 +00:00
aURI = Services . io . newURI ( aURI , null , null ) ;
let isBrowserWindow = ! ! window . gBrowser ;
2010-03-26 21:59:02 +00:00
// Prioritise this window.
2011-02-22 19:02:22 +00:00
if ( isBrowserWindow && switchIfURIInWindow ( window ) )
2010-03-26 21:59:02 +00:00
return true ;
let winEnum = Services . wm . getEnumerator ( "navigator:browser" ) ;
while ( winEnum . hasMoreElements ( ) ) {
let browserWin = winEnum . getNext ( ) ;
// Skip closed (but not yet destroyed) windows,
// and the current window (which was checked earlier).
if ( browserWin . closed || browserWin == window )
continue ;
if ( switchIfURIInWindow ( browserWin ) )
return true ;
}
2010-04-29 17:17:06 +00:00
2010-03-26 21:59:02 +00:00
// No opened tab has that url.
2010-04-29 17:17:06 +00:00
if ( aOpenNew ) {
2011-02-22 19:02:22 +00:00
if ( isBrowserWindow && isTabEmpty ( gBrowser . selectedTab ) )
2014-03-04 15:24:00 +00:00
openUILinkIn ( aURI . spec , "current" , aOpenParams ) ;
2010-08-05 07:11:25 +00:00
else
2014-03-04 15:24:00 +00:00
openUILinkIn ( aURI . spec , "tab" , aOpenParams ) ;
2010-04-29 17:17:06 +00:00
}
2010-03-26 21:59:02 +00:00
return false ;
}
2010-03-25 22:02:19 +00:00
2013-10-22 06:20:15 +00:00
let RestoreLastSessionObserver = {
init : function ( ) {
if ( SessionStore . canRestoreLastSession &&
! PrivateBrowsingUtils . isWindowPrivate ( window ) ) {
Services . obs . addObserver ( this , "sessionstore-last-session-cleared" , true ) ;
goSetCommandEnabled ( "Browser:RestoreLastSession" , true ) ;
}
} ,
observe : function ( ) {
// The last session can only be restored once so there's
// no way we need to re-enable our menu item.
Services . obs . removeObserver ( this , "sessionstore-last-session-cleared" ) ;
goSetCommandEnabled ( "Browser:RestoreLastSession" , false ) ;
} ,
QueryInterface : XPCOMUtils . generateQI ( [ Ci . nsIObserver ,
Ci . nsISupportsWeakReference ] )
} ;
2010-09-10 17:57:28 +00:00
function restoreLastSession ( ) {
2013-08-27 22:52:28 +00:00
SessionStore . restoreLastSession ( ) ;
2010-09-10 17:57:28 +00:00
}
2010-03-25 22:02:19 +00:00
var TabContextMenu = {
contextTab : null ,
updateContextMenu : function updateContextMenu ( aPopupMenu ) {
2012-01-18 05:48:22 +00:00
this . contextTab = aPopupMenu . triggerNode . localName == "tab" ?
aPopupMenu . triggerNode : gBrowser . selectedTab ;
2011-05-13 02:17:04 +00:00
let disabled = gBrowser . tabs . length == 1 ;
2010-07-15 08:11:16 +00:00
// Enable the "Close Tab" menuitem when the window doesn't close with the last tab.
document . getElementById ( "context_closeTab" ) . disabled =
disabled && gBrowser . tabContainer . _closeWindowWithLastTab ;
2010-03-25 22:02:19 +00:00
var menuItems = aPopupMenu . getElementsByAttribute ( "tbattr" , "tabbrowser-multiple" ) ;
2012-08-21 16:56:07 +00:00
for ( let menuItem of menuItems )
menuItem . disabled = disabled ;
2010-03-25 22:02:19 +00:00
2011-05-13 02:17:04 +00:00
disabled = gBrowser . visibleTabs . length == 1 ;
menuItems = aPopupMenu . getElementsByAttribute ( "tbattr" , "tabbrowser-multiple-visible" ) ;
2012-08-21 16:56:07 +00:00
for ( let menuItem of menuItems )
menuItem . disabled = disabled ;
2011-05-13 02:17:04 +00:00
2010-03-25 22:02:19 +00:00
// Session store
2013-12-13 21:55:49 +00:00
document . getElementById ( "context_undoCloseTab" ) . disabled =
SessionStore . getClosedTabCount ( window ) == 0 ;
2010-07-29 21:36:42 +00:00
2010-07-05 18:40:15 +00:00
// Only one of pin/unpin should be visible
document . getElementById ( "context_pinTab" ) . hidden = this . contextTab . pinned ;
document . getElementById ( "context_unpinTab" ) . hidden = ! this . contextTab . pinned ;
2010-07-22 15:51:55 +00:00
2013-05-29 14:07:26 +00:00
// Disable "Close Tabs to the Right" if there are no tabs
// following it and hide it when the user rightclicked on a pinned
// tab.
document . getElementById ( "context_closeTabsToTheEnd" ) . disabled =
gBrowser . getTabsToTheEndFrom ( this . contextTab ) . length == 0 ;
document . getElementById ( "context_closeTabsToTheEnd" ) . hidden = this . contextTab . pinned ;
2010-07-22 15:51:55 +00:00
// Disable "Close other Tabs" if there is only one unpinned tab and
// hide it when the user rightclicked on a pinned tab.
2010-07-29 23:39:57 +00:00
let unpinnedTabs = gBrowser . visibleTabs . length - gBrowser . _numPinnedTabs ;
2010-07-22 15:51:55 +00:00
document . getElementById ( "context_closeOtherTabs" ) . disabled = unpinnedTabs <= 1 ;
document . getElementById ( "context_closeOtherTabs" ) . hidden = this . contextTab . pinned ;
2010-09-21 09:55:48 +00:00
2011-01-28 16:46:49 +00:00
// Hide "Bookmark All Tabs" for a pinned tab. Update its state if visible.
let bookmarkAllTabs = document . getElementById ( "context_bookmarkAllTabs" ) ;
bookmarkAllTabs . hidden = this . contextTab . pinned ;
if ( ! bookmarkAllTabs . hidden )
PlacesCommandHook . updateBookmarkAllTabsCommand ( ) ;
2011-01-18 12:49:04 +00:00
// Hide "Move to Group" if it's a pinned tab.
2011-02-04 09:16:23 +00:00
document . getElementById ( "context_tabViewMenu" ) . hidden =
2011-02-16 16:06:54 +00:00
( this . contextTab . pinned || ! TabView . firstUseExperienced ) ;
2010-03-25 22:02:19 +00:00
}
2010-05-19 16:57:16 +00:00
} ;
2010-06-22 16:51:50 +00:00
2012-11-30 08:07:59 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "gDevTools" ,
"resource:///modules/devtools/gDevTools.jsm" ) ;
2012-12-13 13:03:55 +00:00
XPCOMUtils . defineLazyModuleGetter ( this , "gDevToolsBrowser" ,
2012-11-30 08:07:59 +00:00
"resource:///modules/devtools/gDevTools.jsm" ) ;
2013-08-03 10:29:48 +00:00
Object . defineProperty ( this , "HUDService" , {
get : function HUDService _getter ( ) {
let devtools = Cu . import ( "resource://gre/modules/devtools/Loader.jsm" , { } ) . devtools ;
return devtools . require ( "devtools/webconsole/hudservice" ) ;
} ,
configurable : true ,
enumerable : true
} ) ;
2010-08-12 10:24:29 +00:00
2012-05-08 21:47:19 +00:00
// Prompt user to restart the browser in safe mode
2010-09-22 02:36:53 +00:00
function safeModeRestart ( )
{
2012-05-08 21:47:19 +00:00
// prompt the user to confirm
2010-09-22 02:36:53 +00:00
let promptTitle = gNavigatorBundle . getString ( "safeModeRestartPromptTitle" ) ;
2012-05-08 21:47:19 +00:00
let promptMessage =
2010-09-22 02:36:53 +00:00
gNavigatorBundle . getString ( "safeModeRestartPromptMessage" ) ;
2011-03-24 12:50:12 +00:00
let restartText = gNavigatorBundle . getString ( "safeModeRestartButton" ) ;
let buttonFlags = ( Services . prompt . BUTTON _POS _0 *
Services . prompt . BUTTON _TITLE _IS _STRING ) +
( Services . prompt . BUTTON _POS _1 *
Services . prompt . BUTTON _TITLE _CANCEL ) +
Services . prompt . BUTTON _POS _0 _DEFAULT ;
let rv = Services . prompt . confirmEx ( window , promptTitle , promptMessage ,
buttonFlags , restartText , null , null ,
null , { } ) ;
2013-10-15 18:52:08 +00:00
if ( rv != 0 )
return ;
let cancelQuit = Cc [ "@mozilla.org/supports-PRBool;1" ]
. createInstance ( Ci . nsISupportsPRBool ) ;
Services . obs . notifyObservers ( cancelQuit , "quit-application-requested" , "restart" ) ;
if ( ! cancelQuit . data ) {
2012-12-20 20:34:06 +00:00
Services . startup . restartInSafeMode ( Ci . nsIAppStartup . eAttemptQuit ) ;
2010-09-22 02:36:53 +00:00
}
2010-09-23 00:11:19 +00:00
}
/ * d u p l i c a t e T a b I n d u p l i c a t e s t a b i n a p l a c e s p e c i f i e d b y t h e p a r a m e t e r | w h e r e | .
2010-09-10 19:57:18 +00:00
*
* | where | can be :
* "tab" new tab
* "tabshifted" same as "tab" but in background if default is to select new
* tabs , and vice versa
* "window" new window
*
2011-01-10 19:01:47 +00:00
* delta is the offset to the history entry that you want to load .
2010-09-10 19:57:18 +00:00
* /
2011-01-10 19:01:47 +00:00
function duplicateTabIn ( aTab , where , delta ) {
2013-08-27 22:52:28 +00:00
let newTab = SessionStore . duplicateTab ( window , aTab , delta ) ;
2010-09-10 19:57:18 +00:00
switch ( where ) {
case "window" :
gBrowser . hideTab ( newTab ) ;
gBrowser . replaceTabWithWindow ( newTab ) ;
break ;
case "tabshifted" :
2011-12-20 00:17:08 +00:00
// A background tab has been opened, nothing else to do here.
break ;
2010-09-10 19:57:18 +00:00
case "tab" :
2011-12-20 00:17:08 +00:00
gBrowser . selectedTab = newTab ;
2010-09-10 19:57:18 +00:00
break ;
}
}
2010-11-16 13:19:50 +00:00
2011-05-09 14:51:52 +00:00
var Scratchpad = {
openScratchpad : function SP _openScratchpad ( ) {
2011-11-02 19:32:55 +00:00
return this . ScratchpadManager . openScratchpad ( ) ;
}
2011-11-02 19:26:59 +00:00
} ;
2011-11-02 19:14:30 +00:00
2011-11-02 19:32:55 +00:00
XPCOMUtils . defineLazyGetter ( Scratchpad , "ScratchpadManager" , function ( ) {
let tmp = { } ;
Cu . import ( "resource:///modules/devtools/scratchpad-manager.jsm" , tmp ) ;
return tmp . ScratchpadManager ;
} ) ;
2012-06-01 12:53:58 +00:00
var ResponsiveUI = {
toggle : function RUI _toggle ( ) {
this . ResponsiveUIManager . toggle ( window , gBrowser . selectedTab ) ;
}
} ;
XPCOMUtils . defineLazyGetter ( ResponsiveUI , "ResponsiveUIManager" , function ( ) {
let tmp = { } ;
Cu . import ( "resource:///modules/devtools/responsivedesign.jsm" , tmp ) ;
return tmp . ResponsiveUIManager ;
} ) ;
2011-01-17 14:35:32 +00:00
XPCOMUtils . defineLazyGetter ( window , "gShowPageResizers" , function ( ) {
# ifdef XP _WIN
// Only show resizers on Windows 2000 and XP
2012-12-20 20:34:06 +00:00
return parseFloat ( Services . sysinfo . getProperty ( "version" ) ) < 6 ;
2011-01-17 14:35:32 +00:00
# else
return false ;
# endif
} ) ;
2012-01-12 21:24:44 +00:00
var MousePosTracker = {
2014-03-10 23:05:29 +00:00
_listeners : new Set ( ) ,
2012-01-12 21:24:44 +00:00
_x : 0 ,
_y : 0 ,
get _windowUtils ( ) {
delete this . _windowUtils ;
return this . _windowUtils = window . getInterface ( Ci . nsIDOMWindowUtils ) ;
} ,
addListener : function ( listener ) {
2014-03-10 23:05:29 +00:00
if ( this . _listeners . has ( listener ) )
2012-01-12 21:24:44 +00:00
return ;
listener . _hover = false ;
2014-03-10 23:05:29 +00:00
this . _listeners . add ( listener ) ;
2012-01-12 21:24:44 +00:00
this . _callListener ( listener ) ;
} ,
removeListener : function ( listener ) {
2014-03-10 23:05:29 +00:00
this . _listeners . delete ( listener ) ;
2012-01-12 21:24:44 +00:00
} ,
handleEvent : function ( event ) {
2012-09-29 11:35:19 +00:00
var fullZoom = this . _windowUtils . fullZoom ;
this . _x = event . screenX / fullZoom - window . mozInnerScreenX ;
this . _y = event . screenY / fullZoom - window . mozInnerScreenY ;
2012-01-12 21:24:44 +00:00
this . _listeners . forEach ( function ( listener ) {
try {
this . _callListener ( listener ) ;
} catch ( e ) {
Cu . reportError ( e ) ;
}
} , this ) ;
} ,
_callListener : function ( listener ) {
let rect = listener . getMouseTargetRect ( ) ;
let hover = this . _x >= rect . left &&
this . _x <= rect . right &&
this . _y >= rect . top &&
this . _y <= rect . bottom ;
if ( hover == listener . _hover )
return ;
listener . _hover = hover ;
if ( hover ) {
if ( listener . onMouseEnter )
listener . onMouseEnter ( ) ;
} else {
if ( listener . onMouseLeave )
listener . onMouseLeave ( ) ;
}
}
} ;
2012-01-25 12:42:53 +00:00
2011-12-24 04:12:11 +00:00
function focusNextFrame ( event ) {
2012-12-20 20:34:06 +00:00
let fm = Services . focus ;
2011-12-24 04:12:11 +00:00
let dir = event . shiftKey ? fm . MOVEFOCUS _BACKWARDDOC : fm . MOVEFOCUS _FORWARDDOC ;
let element = fm . moveFocus ( window , null , dir , fm . FLAG _BYKEY ) ;
if ( element . ownerDocument == document )
focusAndSelectUrlBar ( ) ;
}
2013-08-02 20:02:22 +00:00
let BrowserChromeTest = {
_cb : null ,
_ready : false ,
markAsReady : function ( ) {
this . _ready = true ;
if ( this . _cb ) {
this . _cb ( ) ;
this . _cb = null ;
}
} ,
runWhenReady : function ( cb ) {
if ( this . _ready )
cb ( ) ;
else
this . _cb = cb ;
}
} ;
2014-02-11 18:21:58 +00:00
function BrowserOpenNewTabOrWindow ( event ) {
if ( event . shiftKey ) {
OpenBrowserWindow ( ) ;
} else {
BrowserOpenTab ( ) ;
}
}