[mq]: BETA_35_END.patch draft
authorR Kent James <kent@caspia.com>
Tue, 10 Feb 2015 15:45:03 -0800
changeset 28182 2c0483d22c9ad5ac828d24a9104bfd213e8d8ff3
parent 28169 341f30c6108648cbdf69e1e385a1e01d3c0eb647
child 28183 bbad9e4f4ac095bb948e577f528954119a0af40d
push id2180
push userkent@caspia.com
push dateTue, 10 Feb 2015 23:45:51 +0000
treeherdertry-comm-central@c12f2032db30 [default view] [failures only]
[mq]: BETA_35_END.patch
aclocal.m4
build/macosx/universal/mozconfig.common
build/unix/uniq.pl
build/win32/mozconfig.vs2013-win64
calendar/base/backend/icaljs/calICSService.js
calendar/base/content/agenda-listbox.js
calendar/base/content/calendar-base-view.xml
calendar/base/content/calendar-calendars-list.xul
calendar/base/content/calendar-item-editing.js
calendar/base/content/calendar-management.js
calendar/base/content/calendar-month-view.xml
calendar/base/content/calendar-multiday-view.xml
calendar/base/content/calendar-ui-utils.js
calendar/base/content/dialogs/calendar-event-dialog.js
calendar/base/content/dialogs/calendar-event-dialog.xul
calendar/base/jar.mn
calendar/base/modules/calAuthUtils.jsm
calendar/base/modules/calPrintUtils.jsm
calendar/base/modules/calProviderUtils.jsm
calendar/base/modules/calUtils.jsm
calendar/base/modules/calViewUtils.jsm
calendar/base/modules/moz.build
calendar/base/src/calDeletedItems.js
calendar/base/src/calProtocolHandler.js
calendar/base/src/calRecurrenceDate.js
calendar/base/themes/windows/dialogs/images/calendar-event-dialog-toolbar-inverted.png
calendar/base/themes/windows/images/tasks-actions-inverted.png
calendar/base/themes/windows/win-aero/calendar-event-dialog.css
calendar/base/themes/windows/win-aero/calendar.css
calendar/base/themes/windows/win-aero/lightning-toolbar.css
calendar/lightning/Makefile.in
calendar/lightning/components/calItipProtocolHandler.js
calendar/lightning/lightning-packager.mk
calendar/locales/all-locales
calendar/locales/en-US/chrome/calendar/calendar.dtd
calendar/locales/en-US/chrome/calendar/calendar.properties
calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.dtd
calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.properties
calendar/providers/caldav/calDavCalendar.js
calendar/providers/gdata/components/calGoogleUtils.js
calendar/providers/storage/calStorageUpgrade.jsm
calendar/test/mozmill/testAlarmDefaultValue.js
calendar/test/unit/head_consts.js
calendar/test/unit/test_alarmservice.js
calendar/test/unit/test_freebusy_service.js
calendar/test/unit/test_ics_service.js
calendar/test/unit/test_search_service.js
calendar/test/unit/test_view_utils.js
calendar/test/unit/xpcshell.ini
chat/chat-prefs.js
chat/components/public/imIAccount.idl
chat/components/public/imIContactsService.idl
chat/components/public/imILogger.idl
chat/components/public/imITagsService.idl
chat/components/public/prplIConversation.idl
chat/components/src/imAccounts.js
chat/components/src/imCommands.js
chat/components/src/imContacts.js
chat/components/src/imConversations.js
chat/components/src/imCore.js
chat/components/src/smileProtocolHandler.js
chat/content/convbrowser.xml
chat/locales/en-US/irc.properties
chat/modules/imContentSink.jsm
chat/modules/imThemes.jsm
chat/modules/jsProtoHelper.jsm
chat/modules/test/test_filtering.js
chat/nss-purple.def
chat/protocols/irc/irc.js
chat/protocols/irc/ircBase.jsm
chat/protocols/irc/ircCAP.jsm
chat/protocols/irc/ircCTCP.jsm
chat/protocols/irc/ircISUPPORT.jsm
chat/protocols/irc/ircNonStandard.jsm
chat/protocols/irc/ircSASL.jsm
chat/protocols/irc/ircServices.jsm
chat/protocols/irc/ircUtils.jsm
chat/protocols/irc/test/test_ircMessage.js
chat/protocols/xmpp/xmpp-xml.jsm
chat/protocols/yahoo/moz.build
chat/protocols/yahoo/test/test_yahooAccount.js
chat/protocols/yahoo/test/test_yahooLoginHelper.js
chat/protocols/yahoo/test/test_yahoopacket.js
chat/themes/conv.css
client.py
config/baseconfig.mk
config/config.mk
config/recurse.mk
config/rules.mk
editor/ui/dialogs/content/EdInsertMath.js
editor/ui/dialogs/content/EdReplace.xul
editor/ui/texzilla/content/TeXZilla.js
im/app/Makefile.in
im/app/application.ini
im/app/instantbird.exe.manifest
im/app/macbuild/Contents/Info.plist.in
im/app/macbuild/Contents/MacOS-files.in
im/app/moz.build
im/app/nsMain.cpp
im/app/profile/all-instantbird.js
im/components/ibConvStatsService.js
im/components/ibIConvStatsService.idl
im/components/mintrayr/content/mintrayr.xul
im/config/mozconfigs/linux/mozconfig
im/config/mozconfigs/macosx/mozconfig
im/config/mozconfigs/win32/mozconfig
im/confvars.sh
im/content/aboutDialog.xul
im/content/aboutPanel.xml
im/content/accounts.js
im/content/accounts.xul
im/content/blist.js
im/content/blist.xul
im/content/conversation.xml
im/content/credits.xhtml
im/content/debugLog.html
im/content/debugLogPanel.xml
im/content/instantbird.css
im/content/instantbird.js
im/content/instantbird.xul
im/content/jar.mn
im/content/menus-mac.xul
im/content/menus.xul.inc
im/content/tabbrowser.css
im/content/tabbrowser.xml
im/installer/Makefile.in
im/installer/package-manifest.in
im/locales/en-US/chrome/instantbird/accounts.dtd
im/locales/en-US/chrome/instantbird/core.properties
im/modules/ibCore.jsm
im/test/xpcshell.ini
im/themes/blist-aero.css
im/themes/conversation.css
im/themes/debugLog.css
im/themes/debugLogPanel.css
im/themes/instantbird-aero.css
im/themes/instantbird.css
im/themes/jar.mn
im/themes/tabbrowser-gnomestripe/tabbrowser.css
im/themes/tabbrowser-pinstripe/tabbrowser.css
im/themes/tabbrowser-winstripe/tabbrowser.css
ldap/Makefile.in
ldap/xpcom/src/nsLDAPInternal.h
ldap/xpcom/src/nsLDAPProtocolHandler.js
mail/app/moz.build
mail/app/profile/all-thunderbird.js
mail/app/thunderbird.exe.manifest
mail/base/content/aboutDialog.js
mail/base/content/commandglue.js
mail/base/content/editContactOverlay.js
mail/base/content/folderPane.js
mail/base/content/mail3PaneWindowCommands.js
mail/base/content/mailCore.js
mail/base/content/mailWindowOverlay.xul
mail/base/content/messageDisplay.js
mail/base/content/msgHdrViewOverlay.js
mail/base/content/msgHdrViewOverlay.xul
mail/base/content/msgMail3PaneWindow.js
mail/base/content/multimessageview.js
mail/base/content/nsContextMenu.js
mail/base/content/plugins.js
mail/base/content/specialTabs.js
mail/base/content/tabmail.xml
mail/base/modules/Windows8WindowFrameColor.jsm
mail/base/modules/attachmentChecker.js
mail/base/modules/distribution.js
mail/base/modules/mailInstrumentation.js
mail/base/modules/mailMigrator.js
mail/components/addrbook/content/abCommon.js
mail/components/addrbook/content/abContactsPanel.js
mail/components/addrbook/content/abContactsPanel.xul
mail/components/addrbook/content/addressbook.js
mail/components/addrbook/content/addressbook.xul
mail/components/cloudfile/content/Hightail/fileExceedsLimit.js
mail/components/cloudfile/content/Hightail/fileExceedsLimit.xul
mail/components/cloudfile/content/Hightail/fileExceedsQuota.js
mail/components/cloudfile/content/Hightail/fileExceedsQuota.xul
mail/components/cloudfile/content/addAccountDialog.js
mail/components/cloudfile/jar.mn
mail/components/cloudfile/nsHightail.js
mail/components/compose/content/MsgComposeCommands.js
mail/components/compose/content/messengercompose.xul
mail/components/devtools/content/dbg-messenger-overlay.js
mail/components/im/content/imAccounts.js
mail/components/im/content/imconversation.xml
mail/components/im/modules/chatHandler.jsm
mail/components/im/modules/index_im.js
mail/components/im/themes/chat.css
mail/components/newmailaccount/content/uriListener.js
mail/components/preferences/advanced.xul
mail/components/preferences/applications.js
mail/components/preferences/applications.xul
mail/components/preferences/chat.xul
mail/components/preferences/compose.xul
mail/components/preferences/display.js
mail/components/preferences/display.xul
mail/components/preferences/fonts.js
mail/components/preferences/fonts.xul
mail/components/preferences/general.xul
mail/components/preferences/jar.mn
mail/components/preferences/preferences.js
mail/components/preferences/privacy.js
mail/components/preferences/privacy.xul
mail/components/preferences/receipts.js
mail/components/preferences/receipts.xul
mail/components/preferences/security.xul
mail/components/search/wsenable/WSEnable.exe.manifest
mail/components/shell/nsMailGNOMEIntegration.cpp
mail/config/mozconfigs/win32/debug
mail/config/mozconfigs/win32/l10n-mozconfig
mail/config/mozconfigs/win32/nightly
mail/config/mozconfigs/win32/release
mail/config/mozconfigs/win64/debug
mail/config/mozconfigs/win64/l10n-mozconfig
mail/config/mozconfigs/win64/nightly
mail/config/tooltool-manifests/linux32/releng.manifest
mail/config/tooltool-manifests/linux64/releng.manifest
mail/config/tooltool-manifests/macosx64/releng.manifest
mail/config/tooltool-manifests/win32/releng.manifest
mail/config/version.txt
mail/configure.in
mail/confvars.sh
mail/extensions/smime/content/msgCompSMIMEOverlay.js
mail/installer/Makefile.in
mail/installer/package-manifest.in
mail/installer/removed-files.in
mail/installer/windows/nsis/installer.nsi
mail/installer/windows/nsis/shared.nsh
mail/installer/windows/nsis/uninstaller.nsi
mail/locales/en-US/chrome/messenger-newsblog/feed-subscriptions.dtd
mail/locales/en-US/chrome/messenger/charsetTitles.properties
mail/locales/en-US/chrome/messenger/cloudfile/Hightail/fileExceedsLimit.dtd
mail/locales/en-US/chrome/messenger/cloudfile/Hightail/fileExceedsQuota.dtd
mail/locales/en-US/chrome/messenger/msgHdrViewOverlay.dtd
mail/locales/en-US/chrome/messenger/multimessageview.properties
mail/locales/en-US/chrome/messenger/preferences/preferences.dtd
mail/locales/en-US/chrome/messenger/preferences/privacy.dtd
mail/locales/en-US/chrome/overrides/netError.dtd
mail/locales/en-US/searchplugins/amazondotcom.xml
mail/locales/en-US/searchplugins/aol-web-search.xml
mail/locales/en-US/searchplugins/bing.xml
mail/locales/en-US/searchplugins/eBay.xml
mail/locales/en-US/searchplugins/google.xml
mail/locales/en-US/searchplugins/twitter.xml
mail/locales/en-US/searchplugins/wikipedia.xml
mail/locales/en-US/searchplugins/yahoo.xml
mail/steel/steelApplication.js
mail/test/mozmill/addrbook/test-address-book.js
mail/test/mozmill/cloudfile/test-cloudfile-attachment-urls.js
mail/test/mozmill/composition/test-attachment-reminder.js
mail/test/mozmill/folder-display/test-columns.js
mail/test/mozmill/message-header/test-header-toolbar.js
mail/test/mozmill/migration-to-rdf-ui-2/test-migrate-to-rdf-ui-2.js
mail/test/mozmill/newmailaccount/test-newmailaccount.js
mail/test/mozmill/pref-window/test-donottrack-prefs.js
mail/test/mozmill/runtest.py
mail/test/mozmill/shared-modules/test-address-book-helpers.js
mail/test/mozmill/shared-modules/test-folder-display-helpers.js
mail/test/mozmill/tabmail/test-tabmail-dragndrop.js
mail/test/resources/jsbridge/jsbridge/extension/components/cmdarg.js
mail/test/resources/mozmill/mozmill/extension/resource/modules/utils.js
mail/test/resources/mozmill/mozmill/extension/resource/stdlib/httpd.js
mail/themes/linux/mail/chat.css
mail/themes/linux/mail/cloudfile/Hightail/fileExceedsLimit.css
mail/themes/linux/mail/compose/messengercompose.css
mail/themes/linux/mail/messageHeader.css
mail/themes/osx/jar.mn
mail/themes/osx/mail/addrbook/abContactsPanel.css
mail/themes/osx/mail/addrbook/addressbook.css
mail/themes/osx/mail/chat.css
mail/themes/osx/mail/cloudfile/Hightail/fileExceedsLimit.css
mail/themes/osx/mail/compose/messengercompose.css
mail/themes/osx/mail/icons/expander-closed-active.png
mail/themes/osx/mail/icons/expander-closed.png
mail/themes/osx/mail/icons/expander-open-active.png
mail/themes/osx/mail/icons/expander-open.png
mail/themes/osx/mail/mailWindow1.css
mail/themes/osx/mail/messageHeader.css
mail/themes/osx/mail/messenger.css
mail/themes/osx/mail/primaryToolbar.css
mail/themes/osx/mail/sanitizeDialog.css
mail/themes/osx/mail/tabmail.css
mail/themes/shared/mail/mailWindow1.css
mail/themes/windows/jar.mn
mail/themes/windows/mail/addrbook/addressbook-aero.css
mail/themes/windows/mail/chat-aero.css
mail/themes/windows/mail/chat.css
mail/themes/windows/mail/cloudfile/Hightail/fileExceedsLimit.css
mail/themes/windows/mail/compose/messengercompose-aero.css
mail/themes/windows/mail/compose/messengercompose.css
mail/themes/windows/mail/icons/download-inverted.png
mail/themes/windows/mail/icons/mail-toolbar-aero-inverted.png
mail/themes/windows/mail/messageHeader-aero.css
mail/themes/windows/mail/messageHeader.css
mail/themes/windows/mail/messenger.css
mailnews/addrbook/content/abMailListDialog.js
mailnews/addrbook/content/abResultsPane.js
mailnews/addrbook/src/nsAbAutoCompleteSearch.js
mailnews/addrbook/src/nsAddbookProtocolHandler.cpp
mailnews/addrbook/test/unit/test_nsAbAutoCompleteSearch6.js
mailnews/base/content/charsetList.css
mailnews/base/content/charsetList.xml
mailnews/base/content/folderProps.js
mailnews/base/content/folderProps.xul
mailnews/base/content/msgAccountCentral.js
mailnews/base/prefs/content/AccountManager.js
mailnews/base/prefs/content/accountUtils.js
mailnews/base/prefs/content/am-server-advanced.xul
mailnews/base/prefs/content/am-server.js
mailnews/base/prefs/content/am-server.xul
mailnews/base/public/MailNewsTypes.h
mailnews/base/public/nsIFolderListener.idl
mailnews/base/public/nsIMsgFolder.idl
mailnews/base/public/nsIMsgFolderCacheElement.idl
mailnews/base/public/nsIMsgHdr.idl
mailnews/base/public/nsMsgFolderFlags.idl
mailnews/base/search/src/nsMsgFilterList.cpp
mailnews/base/search/src/nsMsgSearchSession.cpp
mailnews/base/search/src/nsMsgSearchSession.h
mailnews/base/src/newMailNotificationService.js
mailnews/base/src/nsCidProtocolHandler.cpp
mailnews/base/src/nsMessenger.cpp
mailnews/base/src/nsMessengerOSXIntegration.mm
mailnews/base/src/nsMessengerUnixIntegration.cpp
mailnews/base/src/nsMessengerWinIntegration.cpp
mailnews/base/src/nsMsgAccountManager.cpp
mailnews/base/src/nsMsgAccountManagerDS.cpp
mailnews/base/src/nsMsgBiffManager.cpp
mailnews/base/src/nsMsgCopyService.cpp
mailnews/base/src/nsMsgDBView.cpp
mailnews/base/src/nsMsgFolderCacheElement.cpp
mailnews/base/src/nsMsgFolderDataSource.cpp
mailnews/base/src/nsMsgFolderDataSource.h
mailnews/base/src/nsMsgMailSession.cpp
mailnews/base/src/nsMsgPurgeService.cpp
mailnews/base/src/nsStatusBarBiffManager.cpp
mailnews/base/src/nsStatusBarBiffManager.h
mailnews/base/test/moz.build
mailnews/base/test/unit/test_autoconfigXML.js
mailnews/base/test/unit/test_jsTreeSelection.js
mailnews/base/test/unit/test_junkingWhenDisabled.js
mailnews/base/test/unit/test_nsMsgDBView.js
mailnews/base/test/unit/test_nsMsgDBView_headerValues.js
mailnews/base/test/unit/xpcshell.ini
mailnews/base/util/OAuth2.jsm
mailnews/base/util/jsTreeSelection.js
mailnews/base/util/msgDBCacheManager.js
mailnews/base/util/nsMsgDBFolder.cpp
mailnews/base/util/nsMsgDBFolder.h
mailnews/base/util/nsMsgUtils.cpp
mailnews/base/util/nsMsgUtils.h
mailnews/compose/public/nsIMsgCompose.idl
mailnews/compose/src/nsMsgAttachmentHandler.cpp
mailnews/compose/src/nsMsgCompose.cpp
mailnews/compose/src/nsMsgComposeService.cpp
mailnews/compose/src/nsMsgSendLater.cpp
mailnews/compose/src/nsSMTPProtocolHandler.js
mailnews/compose/src/nsSmtpProtocol.cpp
mailnews/compose/src/nsSmtpService.cpp
mailnews/compose/src/nsURLFetcher.cpp
mailnews/db/gloda/test/unit/resources/glodaTestHelper.js
mailnews/db/msgdb/public/nsMsgDatabase.h
mailnews/db/msgdb/src/nsMsgDatabase.cpp
mailnews/db/msgdb/src/nsMsgHdr.cpp
mailnews/db/msgdb/src/nsMsgOfflineImapOperation.cpp
mailnews/extensions/bayesian-spam-filter/src/nsBayesianFilter.cpp
mailnews/extensions/newsblog/content/Feed.js
mailnews/extensions/newsblog/content/FeedUtils.jsm
mailnews/extensions/newsblog/content/feed-parser.js
mailnews/extensions/newsblog/content/feed-subscriptions.js
mailnews/extensions/newsblog/content/feed-subscriptions.xul
mailnews/extensions/smime/src/nsMsgComposeSecure.cpp
mailnews/imap/src/nsAutoSyncManager.cpp
mailnews/imap/src/nsImapIncomingServer.cpp
mailnews/imap/src/nsImapMailFolder.cpp
mailnews/imap/src/nsImapMailFolder.h
mailnews/imap/src/nsImapProtocol.cpp
mailnews/imap/src/nsImapServerResponseParser.cpp
mailnews/imap/src/nsImapService.cpp
mailnews/imap/test/unit/test_dontStatNoSelect.js
mailnews/imap/test/unit/test_offlinePlayback.js
mailnews/import/applemail/src/nsAppleMailImport.cpp
mailnews/import/eudora/src/nsEudoraFilters.cpp
mailnews/import/eudora/src/nsEudoraImport.cpp
mailnews/import/oexpress/nsOEImport.cpp
mailnews/import/outlook/src/nsOutlookImport.cpp
mailnews/import/src/nsImportMail.cpp
mailnews/import/src/nsImportService.cpp
mailnews/import/text/src/nsTextImport.cpp
mailnews/import/vcard/src/nsVCardImport.cpp
mailnews/import/winlivemail/nsWMImport.cpp
mailnews/intl/charsetData.properties
mailnews/intl/charsetalias.properties
mailnews/intl/nsCharsetAlias.cpp
mailnews/jar.mn
mailnews/local/src/nsLocalMailFolder.cpp
mailnews/local/src/nsLocalMailFolder.h
mailnews/local/src/nsLocalUndoTxn.cpp
mailnews/local/src/nsMailboxProtocol.cpp
mailnews/local/src/nsMailboxService.cpp
mailnews/local/src/nsMovemailService.cpp
mailnews/local/src/nsParseMailbox.cpp
mailnews/local/src/nsParseMailbox.h
mailnews/local/src/nsPop3Protocol.cpp
mailnews/local/src/nsPop3Service.cpp
mailnews/local/src/nsPop3Sink.cpp
mailnews/local/test/unit/test_over4GBMailboxes.js
mailnews/mailnews.js
mailnews/mapi/mapiDll/Makefile.in
mailnews/mapi/mapiDll/moz.build
mailnews/mapi/mapihook/src/msgMapiHook.cpp
mailnews/mapi/mapihook/src/msgMapiImp.cpp
mailnews/mime/jsmime/jsmime.js
mailnews/mime/jsmime/test/head_xpcshell_glue.js
mailnews/mime/jsmime/test/mock_date.js
mailnews/mime/jsmime/test/test_header.js
mailnews/mime/jsmime/test/test_header_emitter.js
mailnews/mime/jsmime/test/test_structured_header_emitters.js
mailnews/mime/jsmime/test/test_structured_headers.js
mailnews/mime/moz.build
mailnews/mime/public/moz.build
mailnews/mime/public/msgIStructuredHeaders.idl
mailnews/mime/public/nsICMSMessage.idl
mailnews/mime/public/nsIMimeHeaders.idl
mailnews/mime/src/jsmime.jsm
mailnews/mime/src/mimeJSComponents.js
mailnews/mime/src/mimeParser.jsm
mailnews/mime/src/msgMime.manifest
mailnews/mime/src/nsCMS.cpp
mailnews/mime/test/unit/custom_header.js
mailnews/mime/test/unit/test_structured_headers.js
mailnews/mime/test/unit/xpcshell.ini
mailnews/news/src/nsNNTPNewsgroupList.cpp
mailnews/news/src/nsNNTPProtocol.cpp
mailnews/news/src/nsNewsFolder.cpp
mailnews/news/src/nsNewsFolder.h
mailnews/news/src/nsNntpIncomingServer.cpp
mailnews/news/src/nsNntpService.cpp
mailnews/news/test/unit/test_bug695309.js
mailnews/test/fakeserver/pop3d.js
mailnews/test/resources/IMAPpump.js
mailnews/test/resources/PromiseTestUtils.jsm
mailnews/test/resources/logHelper.js
mailnews/test/resources/passwordStorage.js
suite/app/moz.build
suite/branding/nightly/content/icon32.png
suite/branding/nightly/jar.mn
suite/browser/browser-prefs.js
suite/browser/navigator.js
suite/browser/pageinfo/pageInfo.js
suite/common/bindings/notification.xml
suite/common/bookmarks/bookmarksManager.js
suite/common/bookmarks/browser-places.js
suite/common/communicator.css
suite/common/contentAreaClick.js
suite/common/dataman/dataman.js
suite/common/downloads/tests/chrome/test_action_keys_respect_focus.xul
suite/common/downloads/tests/chrome/test_delete_key_cancels.xul
suite/common/downloads/tests/chrome/test_enter_dblclick_opens.xul
suite/common/downloads/tests/chrome/test_multi_select.xul
suite/common/downloads/tests/chrome/test_space_key_pauses_resumes.xul
suite/common/downloads/tests/chrome/test_space_key_retries.xul
suite/common/downloads/uploadProgress.js
suite/common/history/tree.xml
suite/common/history/treeView.js
suite/common/jar.mn
suite/common/nsContextMenu.js
suite/common/permissions/cookieViewer.js
suite/common/permissions/permissionsManager.js
suite/common/places/browserPlacesViews.js
suite/common/places/controller.js
suite/common/places/menu.xml
suite/common/places/tests/browser/browser_423515.js
suite/common/places/tree.xml
suite/common/places/treeView.js
suite/common/pref/pref-security.js
suite/common/pref/pref-security.xul
suite/common/printPreviewBindings.xml
suite/common/profile/profileSelection.js
suite/common/sidebar/sidebarOverlay.js
suite/common/src/PlacesUIUtils.jsm
suite/common/src/nsAbout.js
suite/common/src/nsGopherProtocolStubHandler.js
suite/common/src/nsSuiteGlue.js
suite/common/utilityOverlay.js
suite/config/version.txt
suite/confvars.sh
suite/feeds/src/FeedConverter.js
suite/feeds/src/FeedWriter.js
suite/feeds/src/SuiteFeeds.manifest
suite/installer/Makefile.in
suite/installer/package-manifest.in
suite/installer/removed-files.in
suite/locales/en-US/chrome/common/dataman/dataman.properties
suite/locales/en-US/chrome/common/help/privacy_help.xhtml
suite/locales/en-US/chrome/common/help/privsec_help.xhtml
suite/locales/en-US/chrome/common/notification.properties
suite/locales/en-US/chrome/common/places/places.properties
suite/locales/en-US/chrome/common/pref/pref-security.dtd
suite/locales/en-US/chrome/mailnews/charsetTitles.properties
suite/locales/en-US/chrome/mailnews/newsblog/feed-subscriptions.dtd
suite/locales/en-US/searchplugins/creativecommons.xml
suite/locales/en-US/searchplugins/list.txt
suite/mailnews/addrbook/abCommon.js
suite/mailnews/addrbook/abListOverlay.xul
suite/mailnews/addrbook/abSelectAddressesDialog.js
suite/mailnews/addrbook/abSelectAddressesDialog.xul
suite/mailnews/addrbook/addressbook.xul
suite/mailnews/compose/MsgComposeCommands.js
suite/mailnews/compose/addressingWidgetOverlay.js
suite/mailnews/mailWidgets.xml
suite/mailnews/msgMail3PaneWindow.js
suite/mailnews/prefs/pref-mailnews.js
suite/mailnews/tabmail.js
suite/mailnews/threadPane.js
suite/mailnews/widgetglue.js
suite/shell/src/nsMacShellService.cpp
suite/smile/test/Makefile.in
suite/smile/test/moz.build
suite/smile/test/smile.ini
suite/themes/classic/jar.mn
suite/themes/classic/mac/communicator/bookmarks/editBookmarkOverlay.css
suite/themes/classic/mac/communicator/bookmarks/expander-closed-active.png
suite/themes/classic/mac/communicator/bookmarks/expander-closed.png
suite/themes/classic/mac/communicator/bookmarks/expander-open-active.png
suite/themes/classic/mac/communicator/bookmarks/expander-open.png
suite/themes/modern/global/aboutSupport.css
suite/themes/modern/global/media/TopLevelImageDocument.css
suite/themes/modern/global/media/TopLevelVideoDocument.css
suite/themes/modern/global/media/checkerboard.png
suite/themes/modern/jar.mn
--- a/aclocal.m4
+++ b/aclocal.m4
@@ -1,14 +1,15 @@
 dnl
 dnl Local autoconf macros used with mozilla
 dnl The contents of this file are under the Public Domain.
 dnl
 
 builtin(include, mozilla/build/autoconf/toolchain.m4)dnl
+builtin(include, mozilla/build/autoconf/ccache.m4)dnl
 builtin(include, mozilla/build/autoconf/config.status.m4)dnl
 builtin(include, mozilla/build/autoconf/nspr.m4)dnl
 builtin(include, mozilla/build/autoconf/nss.m4)dnl
 builtin(include, mozilla/build/autoconf/pkg.m4)dnl
 builtin(include, mozilla/build/autoconf/codeset.m4)dnl
 builtin(include, mozilla/build/autoconf/altoptions.m4)dnl
 builtin(include, mozilla/build/autoconf/mozprog.m4)dnl
 builtin(include, mozilla/build/autoconf/acwinpaths.m4)dnl
--- a/build/macosx/universal/mozconfig.common
+++ b/build/macosx/universal/mozconfig.common
@@ -37,18 +37,17 @@ if test "$MOZ_BUILD_APP" = "i386" -o "$M
   CXX="$CXX -arch $TARGET_CPU"
 
   # These must be set for cross builds, and don't hurt straight builds.
   RANLIB=ranlib
   AR=ar
   AS=$CC
   LD=ld
   STRIP="strip"
-  OTOOL="otool"
 
   # Each per-CPU build should be entirely oblivious to the fact that a
   # universal binary will be produced.  The exception is packager.mk, which
   # needs to know to look for universal bits when building the .dmg.
   UNIVERSAL_BINARY=1
 
-  export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP OTOOL
+  export CC CXX HOST_CC HOST_CXX RANLIB AR AS LD STRIP
 fi
 fi
new file mode 100644
--- /dev/null
+++ b/build/unix/uniq.pl
@@ -0,0 +1,91 @@
+#!/usr/bin/env perl
+
+# 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/.
+
+##----------------------------##
+##---] CORE/CPAN INCLUDES [---##
+##----------------------------##
+use strict;
+use warnings;
+use Getopt::Long;
+
+##-------------------##
+##---]  EXPORTS  [---##
+##-------------------##
+our $VERSION = qw(1.1);
+
+##-------------------##
+##---]  GLOBALS  [---##
+##-------------------##
+my %argv;
+my $modver = $Getopt::Long::VERSION || 0;
+my $isOldGetopt = ($modver eq '2.25') ? 1 : 0;
+
+###########################################################################
+## Intent: Script init function
+###########################################################################
+sub init
+{
+    if ($isOldGetopt)
+    {
+	# mozilla.build/mingw perl in need of an upgrade
+	# emulate Getopt::Long switch|short:init
+	foreach (qw(debug regex sort))
+	{
+	    if (defined($argv{$_}))
+	    {
+		$argv{$_} ||= 1;
+	    }
+	}
+    }
+} # init
+
+##----------------##
+##---]  MAIN  [---##
+##----------------##
+my @args = ($isOldGetopt)
+    ? qw(debug|d regex|r sort|s)
+    : qw(debug|d:1 regex|r:1 sort|s:1)
+    ;
+
+unless(GetOptions(\%argv, @args))
+{
+    print "Usage: $0\n";
+    print "  --sort   Sort list elements early\n";
+    print "  --regex  Exclude subdirs by pattern\n";
+}
+
+init();
+my $debug = $argv{debug} || 0;
+
+my %seen;
+my @out;
+my @in = ($argv{sort}) ? sort @ARGV : @ARGV;
+
+foreach my $d (@in)
+{
+    next if ($seen{$d}++);
+
+    print "   arg is $d\n" if ($debug);
+
+    if ($argv{regex})
+    {
+        my $found = 0;
+        foreach my $dir (@out)
+	{
+	    my $dirM = quotemeta($dir);
+            $found++, last if ($d eq $dir || $d =~ m!^${dirM}\/!);
+        }
+	print "Adding $d\n" if ($debug && !$found);
+        push @out, $d if (!$found);
+    } else {
+	print "Adding: $d\n" if ($debug);
+        push(@out, $d);
+    }
+}
+
+print "@out\n"
+
+# EOF
deleted file mode 100644
--- a/build/win32/mozconfig.vs2013-win64
+++ /dev/null
@@ -1,28 +0,0 @@
-_VSPATH="/c/tools/vs2013"
-export WIN32_REDIST_DIR=${_VSPATH}/VC/redist/x86/Microsoft.VC120.CRT
-
-## moz tools location for 64-bit builders ##
-export MOZ_TOOLS=C:/mozilla-build/moztools
-
-## includes: win8.1 sdk includes, winrt headers for metro, msvc std library, directx sdk for d3d9 ##
-export INCLUDE=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/shared:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/um:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt/wrl:/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/include/winrt/wrl/wrappers:${_VSPATH}/vc/include:${_VSPATH}/vc/atlmfc/include:/c/tools/sdks/dx10/include
-
-## libs: win8.1 sdk x86 (32-bit) libs, msvc (32-bit) std library, msvc atl libs, directx sdk (32-bit) for d3d9  ##
-export LIBPATH=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
-export LIB=/c/Program\ Files\ \(x86\)/Windows\ Kits/8.1/Lib/winv6.3/um/x86:${_VSPATH}/vc/lib:${_VSPATH}/vc/atlmfc/lib:/c/tools/sdks/dx10/lib
-
-## paths: win8.1 sdk x86 (32-bit) tools, msvc (64-bit compiling 32-bit) build toolchain, moz tools  ##
-export PATH="/c/Program Files (x86)/Windows Kits/8.1/bin/x86:${_VSPATH}/Common7/IDE:${_VSPATH}/VC/BIN/amd64_x86:${_VSPATH}/VC/BIN/amd64:${_VSPATH}/Common7/Tools:${_VSPATH}/VC/VCPackages:/c/mozilla-build/moztools:${PATH}"
-
-## WindowsSDKDir ##
-export WINDOWSSDKDIR="/c/Program Files (x86)/Windows Kits/8.1/"
-
-. $topsrcdir/build/mozconfig.vs-common
-
-mk_export_correct_style LIB
-mk_export_correct_style LIBPATH
-mk_export_correct_style PATH
-mk_export_correct_style INCLUDE
-mk_export_correct_style WIN32_REDIST_DIR
-
-mk_add_options "export MOZ_TOOLS=$MOZ_TOOLS"
--- a/calendar/base/backend/icaljs/calICSService.js
+++ b/calendar/base/backend/icaljs/calICSService.js
@@ -25,33 +25,30 @@ calIcalProperty.prototype = {
 
     get icalString() this.innerObject.toICAL() + ICAL.newLineChar,
     get icalProperty() this.innerObject,
     set icalProperty(val) this.innerObject = val,
 
     get parent() this.innerObject.parent,
     toString: function() this.innerObject.toICAL(),
 
-    get value() this.innerObject.getValues().join(","),
-    set value(val) {
-        this.innerObject.setValue(val);
-        return val;
-    },
-
-    get valueAsIcalString() {
+    get value() {
         let type = this.innerObject.type;
         function stringifyValue(x) ICAL.stringify.value(x.toString(), type);
         return this.innerObject.getValues().map(stringifyValue).join(",");
     },
-    set valueAsIcalString(val) {
+    set value(val) {
         var icalval = ICAL.parse._parseValue(val, this.innerObject.type);
         this.innerObject.setValue(icalval);
         return val;
     },
 
+    get valueAsIcalString() this.value,
+    set valueAsIcalString(val) this.value = val,
+
     get valueAsDatetime() {
         let val = this.innerObject.getFirstValue();
         let isIcalTime = val && (typeof val == "object") &&
                          ("icalclass" in val) && val.icalclass == "icaltime";
         return (isIcalTime ? new calDateTime(val) : null);
     },
     set valueAsDatetime(val) unwrapSetter(ICAL.Time, val, function(val) {
         if (val && val.zone &&
--- a/calendar/base/content/agenda-listbox.js
+++ b/calendar/base/content/agenda-listbox.js
@@ -7,17 +7,17 @@ Components.utils.import("resource://gre/
 
 function Synthetic(aOpen, aDuration) {
     this.open = aOpen;
     this.duration = aDuration;
 }
 
 var agendaListbox = {
     agendaListboxControl: null,
-    mPendingRefreshJobs: null,
+    pendingRefresh: null,
     kDefaultTimezone: null,
     showsToday: false
 };
 
 /**
  * Initialize the agenda listbox, used on window load.
  */
 agendaListbox.init =
@@ -28,17 +28,16 @@ function initAgendaListbox() {
     var showTomorrowHeader = (document.getElementById("tomorrow-header-hidden").getAttribute("checked") == "true");
     var showSoonHeader = (document.getElementById("nextweek-header-hidden").getAttribute("checked") == "true");
     this.today = new Synthetic(showTodayHeader, 1);
     this.addPeriodListItem(this.today, "today-header");
     this.tomorrow = new Synthetic(showTomorrowHeader, 1);
     var soondays = Preferences.get("calendar.agendaListbox.soondays", 5);
     this.soon = new Synthetic(showSoonHeader, soondays);
     this.periods = [this.today, this.tomorrow, this.soon];
-    this.mPendingRefreshJobs = new Map();
 
     // Make sure the agenda listbox is unloaded
     var self = this;
     window.addEventListener("unload",
                             function unload_agendaListbox() {
                                 self.uninit();
                             },
                             false);
@@ -599,96 +598,45 @@ function setupContextMenu(popup) {
  *
  * @param aStart        (optional) The start date for the item query.
  * @param aEnd          (optional) The end date for the item query.
  * @param aCalendar     (optional) If specified, the single calendar from
  *                                   which the refresh will occur.
  */
 agendaListbox.refreshCalendarQuery =
 function refreshCalendarQuery(aStart, aEnd, aCalendar) {
-    let refreshJob = {
-        agendaListbox: this,
-        calendar: null,
-        calId: null,
-        operation: null,
-        cancelled: false,
-
-        onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) {
-            if (this.agendaListbox.mPendingRefreshJobs.has(this.calId)) {
-                this.agendaListbox.mPendingRefreshJobs.delete(this.calId);
-            }
-
-            if (!this.cancelled) {
-                setCurrentEvent();
-            }
-        },
-
-        onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-            if (this.cancelled || !Components.isSuccessCode(aStatus)) {
-                return;
-            }
-            for (let item of aItems) {
-                this.agendaListbox.addItem(item);
-            }
-        },
-
-        cancel: function() {
-            this.cancelled = true;
-            if (this.operation && this.operation.isPending) {
-                this.operation.cancel();
-                this.operation = null;
-            }
-        },
-
-        execute: function(aStart, aEnd, aCalendar) {
-            if (!(aStart || aEnd || aCalendar)) {
-                this.agendaListbox.removeListItems();
-            }
-
-            if (!aCalendar) {
-                aCalendar = this.agendaListbox.calendar;
-            }
-            if (!aStart) {
-                aStart = this.agendaListbox.getStart();
-            }
-            if (!aEnd) {
-                aEnd = this.agendaListbox.getEnd();
-            }
-            if (!(aStart || aEnd || aCalendar)) {
-                return;
-            }
-
-            if (aCalendar.type == "composite") {
-                // we're refreshing from the composite calendar, so we can cancel
-                // all other pending refresh jobs.
-                this.calId = "composite";
-                for (let job of this.agendaListbox.mPendingRefreshJobs.values()) {
-                    job.cancel();
-                }
-                this.agendaListbox.mPendingRefreshJobs.clear();
-            } else {
-                this.calId = aCalendar.id;
-                if (this.agendaListbox.mPendingRefreshJobs.has(this.calId)) {
-                    this.agendaListbox.mPendingRefreshJobs.get(this.calId).cancel();
-                    this.agendaListbox.mPendingRefreshJobs.delete(this.calId);
-                }
-            }
-            this.calendar = aCalendar;
-
-            let filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES |
-                         this.calendar.ITEM_FILTER_TYPE_EVENT;
-            let op = this.calendar.getItems(filter, 0, aStart, aEnd, this);
-            if (op && op.isPending) {
-                this.operation = op;
-                this.agendaListbox.mPendingRefreshJobs.set(this.calId, this);
-            }
+    let pendingRefresh = cal.wrapInstance(this.pendingRefresh, Components.interfaces.calIOperation);
+    if (this.pendingRefresh) {
+        if (pendingRefresh) {
+            this.pendingRefresh = null;
+            pendingRefresh.cancel(null);
+        } else {
+            return;
         }
-    };
-
-    refreshJob.execute(aStart, aEnd, aCalendar);
+    }
+    if (!(aStart || aEnd || aCalendar)) {
+        this.removeListItems();
+    }
+    if (!aStart) {
+        aStart = this.getStart();
+    }
+    if (!aEnd) {
+        aEnd = this.getEnd();
+    }
+    if (aStart && aEnd) {
+        var filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES |
+                     this.calendar.ITEM_FILTER_TYPE_EVENT;
+        this.pendingRefresh = true;
+        let refreshCalendar = aCalendar || this.calendar;
+        pendingRefresh = refreshCalendar.getItems(filter, 0, aStart, aEnd,
+                                                  this.calendarOpListener);
+        if (pendingRefresh && pendingRefresh.isPending) { // support for calIOperation
+            this.pendingRefresh = pendingRefresh;
+        }
+    }
 };
 
 /**
  * Sets up the calendar for the agenda listbox.
  */
 agendaListbox.setupCalendar =
 function setupCalendar() {
     this.init();
@@ -877,16 +825,39 @@ function getListItemByHashId(ahashId) {
  * The operation listener used for calendar queries.
  * Implements calIOperationListener.
  */
 agendaListbox.calendarOpListener = {
     agendaListbox : agendaListbox
 };
 
 /**
+ * Called when all items have been retrieved from the calendar.
+ * @see calIOperationListener
+ */
+agendaListbox.calendarOpListener.onOperationComplete =
+function listener_onOperationComplete(calendar, status, optype, id,
+                                      detail) {
+    // signal that the current operation finished.
+    this.agendaListbox.pendingRefresh = null;
+    setCurrentEvent();
+};
+
+/**
+ * Called when an item has been retrieved, adds all items to the agenda listbox.
+ * @see calIOperationListener
+ */
+agendaListbox.calendarOpListener.onGetResult =
+function listener_onGetResult(calendar, status, itemtype, detail, count, items) {
+    if (!Components.isSuccessCode(status))
+        return;
+    items.forEach(this.agendaListbox.addItem, this.agendaListbox);
+};
+
+/**
  * Calendar and composite observer, used to keep agenda listbox up to date.
  * @see calIObserver
  * @see calICompositeObserver
  */
 agendaListbox.calendarObserver = {
     agendaListbox: agendaListbox
 };
 
--- a/calendar/base/content/calendar-base-view.xml
+++ b/calendar/base/content/calendar-base-view.xml
@@ -14,17 +14,18 @@
     <resources>
       <stylesheet src="chrome://calendar/skin/calendar-alarms.css"/>
     </resources>
     <implementation>
       <field name="mWeekStartOffset">0</field>
       <field name="mRangeStartDate">null</field>;
       <field name="mRangeEndDate">null</field>;
       <field name="mWorkdaysOnly">false</field>
-      <field name="mPendingRefreshJobs">null</field>
+      <field name="mRefreshQueue">[]</field>
+      <field name="mRefreshPending">null</field>
       <field name="mCalendar">null</field>
       <field name="mController">null</field>
       <field name="mStartDate">null</field>
       <field name="mEndDate">null</field>
       <field name="mTasksInView">false</field>
       <field name="mShowCompleted">false</field>
       <field name="mDisplayDaysOff">true</field>
       <field name="mDaysOffArray">[0,6]</field>
@@ -36,33 +37,65 @@
       <field name="mDropShadowsLength">null</field>
       <field name="mShadowOffset">null</field>
       <field name="mDropShadows">null</field>
       <field name="mMagnifyAmount">0</field>
       <field name="mPixelScrollDelta">0</field>
       <field name="mViewStart">null</field>
       <field name="mViewEnd">null</field>
       <field name="mToggleStatus">0</field>
-      <field name="mLog">null</field>
       <field name="mToggleStatusFlag"><![CDATA[
       ({ WorkdaysOnly:  1,
          TasksInView:   2,
          ShowCompleted: 4,
       })
       ]]></field>
 
       <field name="mPrefObserver"><![CDATA[
       ({ calView: this,
          observe: function calViewPrefChange(subj, topic, pref) {
              this.calView.handlePreference(subj, topic, pref);
              return;
          }
       })
       ]]></field>
 
+      <field name="mOperationListener"><![CDATA[
+      ({
+          calView: this,
+
+          onOperationComplete:
+          function onOperationComplete(aCalendar, aStatus, aOperationType,
+                                       aId, aDetail) {
+              // Fire event
+              this.calView.fireEvent('viewloaded', aOperationType);
+
+              // signal that the current operation finished.
+              this.calView.mRefreshPending = null;
+
+              // immediately start the next job on the queue.
+              this.calView.popRefreshQueue();
+          },
+
+          onGetResult:
+          function onGetResult(aCalendar, aStatus, aItemType, aDetail,
+                               aCount, aItems) {
+              if (!Components.isSuccessCode(aStatus)) {
+                  return;
+              }
+              let items = aItems.filter(function(x) !cal.isToDo(x) ||
+                                        (x.entryDate || x.dueDate));
+
+              for each (let item in items) {
+                  this.calView.doAddItem(item);
+              }
+          }
+      })
+      ]]></field>
+
       <field name="mObserver"><![CDATA[
         // the calIObserver, calICompositeObserver, and calIAlarmServiceObserver
         ({
             QueryInterface: XPCOMUtils.generateQI([
                 Components.interfaces.calIObserver,
                 Components.interfaces.calIAlarmServiceObserver,
                 Components.interfaces.calICompositeObserver
             ]),
@@ -224,17 +257,16 @@
             }
         })
       ]]></field>
 
       <constructor><![CDATA[
         Components.utils.import("resource://gre/modules/Services.jsm");
         Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
         Components.utils.import("resource://gre/modules/Preferences.jsm");
-        Components.utils.import("resource:///modules/gloda/log4moz.js");
 
         const kWorkdaysCommand = "calendar_toggle_workdays_only_command";
         const kTasksInViewCommand = "calendar_toggle_tasks_in_view_command";
         const kShowCompleted = "calendar_toggle_show_completed_in_view_command";
         const kOrientation = "calendar_toggle_orientation_command";
 
         this.workdaysOnly = (document.getElementById(kWorkdaysCommand)
                                 .getAttribute("checked") == "true");
@@ -253,18 +285,16 @@
         this.setAttribute("type", this.type);
         this.mResizeHandler = function resizeHandler() {
             self.onResize(self); };
         this.viewBroadcaster.addEventListener(this.getAttribute("type") + "viewresized", this.mResizeHandler, true);
         // add a preference observer to monitor changes
         Services.prefs.addObserver("calendar.", this.mPrefObserver, false);
         this.weekStartOffset = Preferences.get("calendar.week.start", 0);
         this.updateDaysOffPrefs();
-        this.mPendingRefreshJobs = new Map();
-        this.mLog = Log4Moz.getConfiguredLogger("calBaseView");
       ]]></constructor>
 
       <destructor><![CDATA[
         Components.utils.import("resource://gre/modules/Services.jsm");
 
         if (this.mCalendar) {
             this.mCalendar.removeObserver(this.mObserver);
         }
@@ -384,16 +414,78 @@
       </method>
 
       <method name="getRangeDescription">
         <body><![CDATA[
             return getDateFormatter().formatInterval(this.rangeStartDate, this.rangeEndDate);
         ]]></body>
       </method>
 
+      <method name="popRefreshQueue">
+        <body><![CDATA[
+          let pendingRefresh = cal.wrapInstance(this.mRefreshPending, Components.interfaces.calIOperation);
+          if (this.mRefreshPending) {
+              if (pendingRefresh) {
+                  this.mRefreshPending = null;
+                  pendingRefresh.cancel(null);
+              } else {
+                  if(this.mRefreshQueue.length > 0) {
+                      this.relayout();
+                  }
+                  return;
+              }
+          }
+
+          let refreshJob = this.mRefreshQueue.pop();
+          if (!refreshJob) {
+            return;
+          }
+
+          if (!this.startDate || !this.endDate) {
+            return;
+          }
+
+          if (!this.mCalendar) {
+              return;
+          }
+
+          // start our items query; for a disjoint date range
+          // we get all the items, and just filter out the ones we don't
+          // care about in addItem
+
+          let filter = this.mCalendar.ITEM_FILTER_CLASS_OCCURRENCES;
+          if (this.mShowCompleted) {
+              filter |= this.mCalendar.ITEM_FILTER_COMPLETED_ALL;
+          } else {
+              filter |= this.mCalendar.ITEM_FILTER_COMPLETED_NO;
+          }
+
+          if(this.mTasksInView) {
+              filter |= this.mCalendar.ITEM_FILTER_TYPE_ALL;
+          } else {
+              filter |= this.mCalendar.ITEM_FILTER_TYPE_EVENT;
+          }
+
+          this.mRefreshPending = true;
+          let refreshCalendar = refreshJob.calendar;
+          if (!refreshCalendar) {
+              refreshCalendar = this.mCalendar;
+              this.relayout();
+          }
+          pendingRefresh = refreshCalendar.getItems(filter,
+                                                    0,
+                                                    this.startDate,
+                                                    this.queryEndDate,
+                                                    this.mOperationListener);
+          if (pendingRefresh && pendingRefresh.isPending) { // support for calIOperation
+              this.mRefreshPending = pendingRefresh;
+          }
+        ]]></body>
+      </method>
+
       <!-- This function guarantees that the
        labels are clipped in the instance that the overflow occurrs,
        avoiding horizontal scrollbars from showing up for a short period. -->
       <method name="adjustWeekdayLength">
         <parameter name="forceShortName"/>
         <body><![CDATA[
           let useShortNames = false;
           let labeldayboxkids = this.labeldaybox.childNodes;
@@ -429,127 +521,41 @@
         <body><![CDATA[
             return (this.nodeName == currentView().nodeName);
         ]]></body>
       </method>
 
       <method name="refresh">
         <body><![CDATA[
           if (this.isVisible()) {
-              this.addItemsFromCalendar(this.mCalendar);
+              var refreshJob = {};
+              this.mRefreshQueue.push(refreshJob);
+              this.popRefreshQueue();
           }
         ]]></body>
       </method>
 
       <!-- force refresh visible and invisible views.
            This method is added because when only a preference is toggled, the start
            and end date of views are unchanged, therefore those views behind the
            "scene" might stay the same upon switch to them. -->
       <method name="forceRefresh">
         <body><![CDATA[
-          this.addItemsFromCalendar(this.mCalendar);
+          let refreshJob = {};
+          this.mRefreshQueue.push(refreshJob);
+          this.popRefreshQueue();
         ]]></body>
       </method>
 
       <method name="addItemsFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
-          let refreshJob = {
-              calView: this,
-              calendar: null,
-              calId: null,
-              operation: null,
-              cancelled: false,
-
-              onOperationComplete: function(aCalendar, aStatus, aOperationType, aId, aDateTime) {
-                  this.calView.mLog.info("Refresh complete of calendar " + this.calId);
-                  if (this.calView.mPendingRefreshJobs.has(this.calId)) {
-                      this.calView.mPendingRefreshJobs.delete(this.calId);
-                  }
-
-                  if (!this.cancelled) {
-                      // Fire event
-                      this.calView.fireEvent('viewloaded', aOperationType);
-                  }
-              },
-
-              onGetResult: function(aCalendar, aStatus, aItemType, aDetail, aCount, aItems) {
-                  if (this.cancelled || !Components.isSuccessCode(aStatus)) {
-                      return;
-                  }
-
-                  for (let item of aItems) {
-                      if (!cal.isToDo(item) || item.entryDate || item.dueDate) {
-                          this.calView.doAddItem(item);
-                      }
-                  }
-              },
-
-              cancel: function() {
-                  this.calView.mLog.info("Refresh cancelled for calendar " + this.calId);
-                  this.cancelled = true;
-                  if (this.operation && this.operation.isPending) {
-                      this.operation.cancel();
-                      this.operation = null;
-                  }
-              },
-
-              execute: function(aCalendar) {
-                  if (!this.calView.startDate || !this.calView.endDate || !aCalendar) {
-                      return;
-                  }
-
-                  if (aCalendar.type == "composite") {
-                      // we're refreshing from the composite calendar, so we can cancel
-                      // all other pending refresh jobs.
-                      this.calView.mLog.info("Refreshing composite calendar, cancelling all pending refreshes");
-                      this.calId = "composite";
-                      for (let job of this.calView.mPendingRefreshJobs.values()) {
-                          job.cancel();
-                      }
-                      this.calView.mPendingRefreshJobs.clear();
-                      this.calView.relayout();
-                  } else {
-                      this.calId = aCalendar.id;
-                      if (this.calView.mPendingRefreshJobs.has(this.calId)) {
-                          this.calView.mPendingRefreshJobs.get(this.calId).cancel();
-                          this.calView.mPendingRefreshJobs.delete(this.calId);
-                      }
-                  }
-                  this.calendar = aCalendar;
-
-                  // start our items query; for a disjoint date range
-                  // we get all the items, and just filter out the ones we don't
-                  // care about in addItem
-                  let filter = this.calendar.ITEM_FILTER_CLASS_OCCURRENCES;
-                  if (this.calView.mShowCompleted) {
-                      filter |= this.calendar.ITEM_FILTER_COMPLETED_ALL;
-                  } else {
-                      filter |= this.calendar.ITEM_FILTER_COMPLETED_NO;
-                  }
-
-                  if (this.calView.mTasksInView) {
-                      filter |= this.calendar.ITEM_FILTER_TYPE_ALL;
-                  } else {
-                      filter |= this.calendar.ITEM_FILTER_TYPE_EVENT;
-                  }
-
-                  let op = this.calendar.getItems(filter,
-                                                  0,
-                                                  this.calView.startDate,
-                                                  this.calView.queryEndDate,
-                                                  this);
-                  if (op && op.isPending) {
-                      this.operation = op;
-                      this.calView.mPendingRefreshJobs.set(this.calId, this);
-                  }
-              }
-          };
-
-          refreshJob.execute(aCalendar);
+            let refreshJob = { calendar: aCalendar };
+            this.mRefreshQueue.push(refreshJob);
+            this.popRefreshQueue();
         ]]></body>
       </method>
 
       <method name="deleteItemsFromCalendar">
         <parameter name="aCalendar"/>
         <body><![CDATA[
             /* This method must be implemented in subclasses. */
             throw Components.results.NS_ERROR_NOT_IMPLEMENTED;
--- a/calendar/base/content/calendar-calendars-list.xul
+++ b/calendar/base/content/calendar-calendars-list.xul
@@ -9,27 +9,16 @@
 <!DOCTYPE overlay SYSTEM "chrome://calendar/locale/calendar.dtd">
 
 <overlay id="calendar-list-overlay"
          xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
 
   <popupset id="calendar-popupset">
     <menupopup id="list-calendars-context-menu"
                onpopupshowing="return calendarListSetupContextMenu(event);">
-      <menuitem id="list-calendars-context-togglevisible"
-                accesskey="&calendar.context.togglevisible.accesskey;"
-                oncommand="toggleCalendarVisible(document.getElementById('list-calendars-context-menu').contextCalendar);"/>
-      <menuitem id="list-calendars-context-showonly"
-                accesskey="&calendar.context.showonly.accesskey;"
-                oncommand="showOnlyCalendar(document.getElementById('list-calendars-context-menu').contextCalendar);"/>
-      <menuitem id="list-calendars-context-showall"
-                label="&calendar.context.showall.label;"
-                accesskey="&calendar.context.showall.accesskey;"
-                oncommand="showAllCalendars();"/>
-      <menuseparator id="list-calendars-context-showops-menuseparator"/>
       <menuitem id="list-calendars-context-new"
                 label="&calendar.context.newserver.label;"
                 accesskey="&calendar.context.newserver.accesskey;"
                 observes="calendar_new_calendar_command"/>
       <menuitem id="list-calendars-context-find"
                 label="&calendar.context.findcalendar.label;"
                 accesskey="&calendar.context.findcalendar.accesskey;"
                 oncommand="openCalendarSubscriptionsDialog();"/>
--- a/calendar/base/content/calendar-item-editing.js
+++ b/calendar/base/content/calendar-item-editing.js
@@ -133,17 +133,16 @@ function setDefaultItemValues(aItem, aCa
                     start.day += 7;
                     break;
                 case "offsetcurrent":
                     start = initDate.clone();
                     start.addDuration(startOffset);
                     break;
                 case "offsetnexthour":
                     start = initDate.clone();
-                    start.second = 0;
                     start.minute = 0;
                     start.hour++;
                     start.addDuration(startOffset);
                     break;
             }
 
             if (start) {
                 aItem.entryDate = start;
@@ -184,17 +183,16 @@ function setDefaultItemValues(aItem, aCa
                     due.day += 7;
                     break;
                 case "offsetcurrent":
                     due = start.clone();
                     due.addDuration(dueOffset);
                     break;
                 case "offsetnexthour":
                     due = start.clone();
-                    due.second = 0;
                     due.minute = 0;
                     due.hour++;
                     due.addDuration(dueOffset);
                     break;
             }
 
             if (aItem.entryDate && due && aItem.entryDate.compare(due) > 0) {
                 // due can't be earlier than start date.
--- a/calendar/base/content/calendar-management.js
+++ b/calendar/base/content/calendar-management.js
@@ -137,17 +137,16 @@ function calendarListTooltipShowing(even
  * @return              Returns true if the context menu should be shown.
  */
 function calendarListSetupContextMenu(event) {
     let col = {};
     let row = {};
     let calendar;
     let calendars = getCalendarManager().getCalendars({});
     let treeNode = document.getElementById("calendar-list-tree-widget");
-    let composite = getCompositeCalendar();
 
     if (document.popupNode.localName == "tree") {
         // Using VK_APPS to open the context menu will target the tree
         // itself. In that case we won't have a client point even for
         // opening the context menu. The "target" element should then be the
         // selected calendar.
         row.value =  treeNode.tree.currentIndex;
         col.value = treeNode.getColumn("calendarname-treecol");
@@ -173,99 +172,34 @@ function calendarListSetupContextMenu(ev
     if (calendar) {
         enableElement("list-calendars-context-edit");
         enableElement("list-calendars-context-publish");
         // Only enable the delete calendars item if there is more than one
         // calendar. We don't want to have the last calendar deleted.
         if (calendars.length > 1) {
             enableElement("list-calendars-context-delete");
         }
-
-        enableElement("list-calendars-context-togglevisible");
-        setElementValue("list-calendars-context-togglevisible", false, "collapsed");
-        let stringName = composite.getCalendarById(calendar.id) ? "hideCalendar" : "showCalendar";
-        setElementValue("list-calendars-context-togglevisible",
-                        cal.calGetString("calendar", stringName, [calendar.name]),
-                        "label");
-        enableElement("list-calendars-context-showonly");
-        setElementValue("list-calendars-context-showonly", false, "collapsed");
-        setElementValue("list-calendars-context-showonly",
-                        cal.calGetString("calendar", "showOnlyCalendar", [calendar.name]),
-                        "label");
     } else {
         disableElement("list-calendars-context-edit");
         disableElement("list-calendars-context-publish");
         disableElement("list-calendars-context-delete");
-        disableElement("list-calendars-context-togglevisible");
-        setElementValue("list-calendars-context-togglevisible", true, "collapsed");
-        disableElement("list-calendars-context-showonly");
-        setElementValue("list-calendars-context-showonly", true, "collapsed");
     }
     return true;
 }
 
 /**
  * Makes sure the passed calendar is visible to the user
  *
  * @param aCalendar   The calendar to make visible.
  */
 function ensureCalendarVisible(aCalendar) {
     // We use the main window's calendar list to ensure that the calendar is visible
     document.getElementById("calendar-list-tree-widget").ensureCalendarVisible(aCalendar);
 }
 
-/**
- * Hides the specified calendar if it is visible, or shows it if it is hidden.
- *
- * @param aCalendar   The calendar to show or hide
- */
-function toggleCalendarVisible(aCalendar) {
-    let composite = getCompositeCalendar();
-    if (composite.getCalendarById(aCalendar.id)) {
-        composite.removeCalendar(aCalendar);
-    } else {
-        composite.addCalendar(aCalendar);
-    }
-}
-
-/**
- * Shows all hidden calendars.
- */
-function showAllCalendars() {
-    let composite = getCompositeCalendar();
-    let cals = cal.getCalendarManager().getCalendars({});
-
-    composite.startBatch();
-    for (let calendar of cals) {
-        if (!composite.getCalendarById(calendar.id)) {
-            composite.addCalendar(calendar);
-        }
-    }
-    composite.endBatch();
-}
-
-/**
- * Shows only the specified calendar, and hides all others.
- *
- * @param aCalendar   The calendar to show as the only visible calendar
- */
-function showOnlyCalendar(aCalendar) {
-    let composite = getCompositeCalendar();
-    let cals = composite.getCalendars({}) || [];
-
-    composite.startBatch();
-    for (let calendar of cals) {
-        if (calendar.id != aCalendar.id) {
-            composite.removeCalendar(calendar);
-        }
-    }
-    composite.addCalendar(aCalendar);
-    composite.endBatch();
-}
-
 var compositeObserver = {
     QueryInterface: XPCOMUtils.generateQI([Components.interfaces.calIObserver,
                                            Components.interfaces.calICompositeObserver]),
 
     onStartBatch: function() {},
     onEndBatch: function () {},
     onAddItem: function() {},
     onModifyItem: function() {},
--- a/calendar/base/content/calendar-month-view.xml
+++ b/calendar/base/content/calendar-month-view.xml
@@ -220,24 +220,55 @@
 
       <method name="addItem">
         <parameter name="aItem"/>
         <body><![CDATA[
           if (aItem.hashId in this.mItemHash) {
             this.deleteItem(aItem);
           }
 
+          function dayboxItemComparator(a, b) {
+            let aIsEvent = cal.isEvent(a);
+            let aIsTodo = cal.isToDo(a);
+
+            let bIsEvent = cal.isEvent(b);
+            let bIsTodo = cal.isToDo(b);
+
+            // sort todos before events
+            if (aIsTodo && bIsEvent) return -1;
+            if (aIsEvent && bIsTodo) return 1;
+
+            if (aIsEvent && bIsEvent) {
+              // sort all day events before events with a duration
+              if (a.startDate.isDate && !b.startDate.isDate) return -1;
+              if (!a.startDate.isDate && b.startDate.isDate) return 1;
+
+              let cmp = a.startDate.compare(b.startDate);
+              if (cmp != 0)
+                return cmp;
+
+              cmp = a.endDate.compare(b.endDate);
+              if (cmp != 0)
+                return cmp;
+
+              cmp = (a.title > b.title) - (a.title < b.title);
+              return cmp;
+            }
+
+            return 0;
+          }
+
           let box = createXULElement("calendar-month-day-box-item");
           let context = this.getAttribute("item-context") ||
                         this.getAttribute("context");
           box.setAttribute("context", context);
           box.setAttribute("calendar-uri", aItem.calendar.uri.spec);
           box.setAttribute("calendar-id", aItem.calendar.id);
 
-          cal.binaryInsertNode(this, box, aItem, cal.view.compareItems, false);
+          cal.binaryInsertNode(this, box, aItem, dayboxItemComparator, false);
 
           box.calendarView = this.calendarView;
           box.item = aItem;
           box.parentBox = this;
           box.occurrence = aItem;
 
           this.mItemHash[aItem.hashId] = box;
           return box;
@@ -385,17 +416,16 @@
       </xul:vbox>
     </content>
 
     <implementation implements="calICalendarView">
 
       <!-- constructor -->
       <constructor><![CDATA[
           Components.utils.import("resource://gre/modules/Preferences.jsm");
-          Components.utils.import("resource://calendar/modules/calViewUtils.jsm");
 
           // Set the preference for the default start of the week
           this.weekStartOffset = Preferences.get("calendar.week.start", 0);
 
           for (var i = 0; i < 7; i++) {
               let hdr = createXULElement("calendar-day-label");
               this.labeldaybox.appendChild(hdr);
               hdr.weekDay = (i + this.mWeekStartOffset) % 7;
@@ -631,20 +661,18 @@
           }
           if (this.mWorkdaysOnly) {
               toggleStatus |= this.mToggleStatusFlag.WorkdaysOnly;
           }
           if (this.mShowCompleted) {
               toggleStatus |= this.mToggleStatusFlag.ShowCompleted;
           }
 
-          // Update the navigation bar only when changes are related to the current view.
-          if (this.isVisible()) {
-              cal.navigationBar.setDateRange(aStartDate, aEndDate);
-          }
+          // Update the navigation bar.
+          cal.navigationBar.setDateRange(aStartDate, aEndDate);
 
           // Check whether view range has been changed since last call to
           // relayout()
           if (!this.mViewStart || !this.mViewEnd ||
               this.mViewEnd.compare(viewEnd) != 0 ||
               this.mViewStart.compare(viewStart) != 0 ||
               this.mToggleStatus != toggleStatus) {
 
--- a/calendar/base/content/calendar-multiday-view.xml
+++ b/calendar/base/content/calendar-multiday-view.xml
@@ -1402,17 +1402,17 @@
           if (diffStart < SCROLLZONE) {
               insideScrollZone = SCROLLZONE - diffStart;
               scrollBy *= -1;
           } else if (diffEnd < SCROLLZONE) {
               insideScrollZone = SCROLLZONE - diffEnd;
           }
 
           if (insideScrollZone) {
-              let sbo = scrollbox.boxObject;
+              let sbo = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
               let timeout = MAXTIMEOUT - insideScrollZone * (MAXTIMEOUT - MINTIMEOUT) / SCROLLZONE;
               this.mMagicScrollTimer = setTimeout(function() {
                   sbo.scrollBy(orient == "horizontal" && scrollBy,
                                orient == "vertical" && scrollBy);
                   this.onEventSweepMouseMove(event);
               }.bind(this), timeout);
           }
         ]]></body>
@@ -2868,20 +2868,18 @@
           }
           if (this.mWorkdaysOnly) {
               toggleStatus |= this.mToggleStatusFlag.WorkdaysOnly;
           }
           if (this.mShowCompleted) {
               toggleStatus |= this.mToggleStatusFlag.ShowCompleted;
           }
 
-          // Update the navigation bar only when changes are related to the current view.
-          if (this.isVisible()) {
-              cal.navigationBar.setDateRange(viewStart, viewEnd);
-          }
+          // Update the navigation bar.
+          cal.navigationBar.setDateRange(viewStart, viewEnd);
 
           // Check whether view range has been changed since last call to
           // relayout()
           if (!this.mViewStart || !this.mViewEnd ||
               this.mViewEnd.compare(viewEnd) != 0 ||
               this.mViewStart.compare(viewStart) != 0 ||
               this.mToggleStatus != toggleStatus) {
 
@@ -3708,17 +3706,17 @@
         ]]></body>
       </method>
 
       <field name="mFirstVisibleMinute">0</field>
       <method name="scrollToMinute">
         <parameter name="aMinute"/>
         <body><![CDATA[
           let scrollbox = document.getAnonymousElementByAttribute(this, "anonid", "scrollbox");
-          let scrollBoxObject = scrollbox.boxObject;
+          let scrollBoxObject = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
           // 'aMinute' will be the first minute showed in the view, so it must
           // belong to the range 0 <-> (24*60 - minutes_showed_in_the_view) but
           // we consider 25 hours instead of 24 to let the view scroll until
           // showing events that start just before 0.00
           let maxFirstMin = 25 * 60 - Math.round(scrollBoxObject.height / this.mPixPerMin);
           aMinute = Math.min(maxFirstMin, Math.max(0, aMinute));
 
           if (scrollBoxObject && scrollbox.scrollHeight > 0) {
@@ -3828,17 +3826,17 @@
 
         // We are taking care of scrolling, so prevent the default
         // action in any case.
         event.preventDefault();
       ]]></handler>
 
       <handler event="scroll" phase="bubbling"><![CDATA[
         let scrollbox = document.getAnonymousElementByAttribute(this, "anonid", "scrollbox");
-        let scrollBoxObject = scrollbox.boxObject;
+        let scrollBoxObject = scrollbox.boxObject.QueryInterface(Components.interfaces.nsIScrollBoxObject);
         if (scrollBoxObject && scrollbox.scrollHeight > 0) {
             // We need to update the first visible minute, but only if the
             // scrollbox has been sized.
             let x = {}, y = {};
             scrollBoxObject.getPosition(x, y);
             if (scrollbox.getAttribute("orient") == "horizontal") {
                 this.mFirstVisibleMinute = Math.round(y.value/this.mPixPerMin);
             } else {
--- a/calendar/base/content/calendar-ui-utils.js
+++ b/calendar/base/content/calendar-ui-utils.js
@@ -13,39 +13,36 @@ Components.utils.import("resource://gre/
  *
  * @param aElement      ID of XUL element to set, or the element node itself
  * @param aNewValue     value to set property to ( if undefined no change is made )
  * @param aPropertyName OPTIONAL name of property to set, default is "value",
  *                        use "checked" for radios & checkboxes, "data" for
  *                        drop-downs
  */
 function setElementValue(aElement, aNewValue, aPropertyName) {
-    cal.ASSERT(aElement, "aElement");
+    ASSERT(aElement);
     var undefined;
 
     if (aNewValue !== undefined) {
         if (typeof(aElement) == "string") {
             aElement = document.getElementById(aElement);
-            cal.ASSERT(aElement, "aElement");
         }
 
-        if (!aElement) { return; }
-
         if (aNewValue === false) {
             try {
                 aElement.removeAttribute(aPropertyName);
             } catch (e) {
-                cal.ERROR("setElementValue: aElement.removeAttribute couldn't remove " +
+                dump("setFieldValue: aElement.removeAttribute couldn't remove " +
                 aPropertyName + " from " + (aElement && aElement.localName) + " e: " + e + "\n");
             }
         } else if (aPropertyName) {
             try {
                 aElement.setAttribute(aPropertyName, aNewValue);
             } catch (e) {
-                cal.ERROR("setElementValue: aElement.setAttribute couldn't set " +
+                dump("setFieldValue: aElement.setAttribute couldn't set " +
                 aPropertyName + " from " + (aElement && aElement.localName) + " to " + aNewValue +
                 " e: " + e + "\n");
             }
         } else {
             aElement.value = aNewValue;
         }
      }
  }
--- a/calendar/base/content/dialogs/calendar-event-dialog.js
+++ b/calendar/base/content/dialogs/calendar-event-dialog.js
@@ -1644,19 +1644,17 @@ function editPriority(target) {
 }
 
 /**
  * Update the dialog controls related to priority.
  */
 function updatePriority() {
     // Set up capabilities
     var hasPriority = capSupported("priority");
-    if (document.getElementById("button-priority")) {
-        setElementValue("button-priority", !hasPriority && "true", "disabled");
-    }
+    setElementValue("button-priority", !hasPriority && "true", "disabled");
     setElementValue("options-priority-menu", !hasPriority && "true", "disabled");
     setElementValue("status-priority", !hasPriority && "true", "collapsed");
 
     if (hasPriority) {
         var priorityLevel = "none";
         if (gPriority >= 1 && gPriority <= 4) {
             priorityLevel = "high";
         } else if (gPriority == 5) {
--- a/calendar/base/content/dialogs/calendar-event-dialog.xul
+++ b/calendar/base/content/dialogs/calendar-event-dialog.xul
@@ -50,20 +50,18 @@
     <script type="application/javascript"
             src="chrome://calendar/content/calUtils.js"/>
     <script type="application/javascript"
             src="chrome://calendar/content/calApplicationUtils.js"/>
     <script type="application/javascript"
             src="chrome://global/content/globalOverlay.js"/>
     <script type="application/javascript"
             src="chrome://global/content/printUtils.js"/>
-    <script type="application/javascript"
+    <script type="application/javascript" 
             src="chrome://calendar/content/calendar-statusbar.js"/>
-    <script type="application/javascript"
-            src="chrome://messenger/content/toolbarIconColor.js"/>
 
     <!-- Command updater -->
     <commandset id="globalEditMenuItems"
                 commandupdater="true"
                 events="focus"
                 oncommandupdate="goUpdateGlobalEditMenuItems()"/>
     <commandset id="selectEditMenuItems"
                 commandupdater="true"
--- a/calendar/base/jar.mn
+++ b/calendar/base/jar.mn
@@ -265,16 +265,14 @@ calendar.jar:
     ../skin/windows/calendar/win-classic/calendar-event-dialog.css          (themes/windows/win-classic/calendar-event-dialog.css)
     ../skin/windows/calendar/win-classic/lightning.css                      (themes/windows/win-classic/lightning.css)
     ../skin/windows/calendar/win-classic/lightning-toolbar.css              (themes/windows/win-classic/lightning-toolbar.css)
     ../skin/windows/calendar/win-aero/calendar.css                          (themes/windows/win-aero/calendar.css)
     ../skin/windows/calendar/win-aero/calendar-event-dialog.css             (themes/windows/win-aero/calendar-event-dialog.css)
     ../skin/windows/calendar/win-aero/lightning.css                         (themes/windows/win-aero/lightning.css)
     ../skin/windows/calendar/win-aero/lightning-toolbar.css                 (themes/windows/win-aero/lightning-toolbar.css)
     ../skin/windows/calendar/calendar-event-dialog-toolbar-aero.png         (themes/windows/dialogs/images/calendar-event-dialog-toolbar-aero.png)
-    ../skin/windows/calendar/calendar-event-dialog-toolbar-inverted.png     (themes/windows/dialogs/images/calendar-event-dialog-toolbar-inverted.png)
     ../skin/windows/calendar/calendar-occurrence-prompt-aero.png            (themes/windows/images/calendar-occurrence-prompt-aero.png)
     ../skin/windows/calendar/tasks-actions-aero.png                         (themes/windows/images/tasks-actions-aero.png)
-    ../skin/windows/calendar/tasks-actions-inverted.png                     (themes/windows/images/tasks-actions-inverted.png)
     ../skin/windows/calendar/toolbar-aero.png                               (themes/windows/images/toolbar-aero.png)
     ../skin/windows/calendar/toolbar-aero-inverted.png                      (themes/windows/images/toolbar-aero-inverted.png)
     ../skin/windows/calendar/toolbar-large-aero.png                         (themes/windows/images/toolbar-large-aero.png)
     ../skin/windows/calendar/toolbar-small-aero.png                         (themes/windows/images/toolbar-small-aero.png)
--- a/calendar/base/modules/calAuthUtils.jsm
+++ b/calendar/base/modules/calAuthUtils.jsm
@@ -10,18 +10,18 @@ Components.utils.import("resource://gre/
  * Authentication helper code
  */
 
 EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
 cal.auth = {
     /**
      * Auth prompt implementation - Uses password manager if at all possible.
      */
-    Prompt: function calPrompt() {
-        this.mWindow = cal.getCalendarWindow();
+    Prompt: function calPrompt(aProvider) {
+        this.mProvider = aProvider;
         this.mReturnedLogins = {};
     },
 
     /**
      * Tries to get the username/password combination of a specific calendar name
      * from the password manager or asks the user.
      *
      * @param   in aTitle           The dialog title.
@@ -248,17 +248,17 @@ cal.auth.Prompt.prototype = {
         let pw = this.getPasswordInfo(hostRealm);
         aAuthInfo.username = pw.username;
         if (pw && pw.found) {
             aAuthInfo.password = pw.password;
             return true;
         } else {
             let prompter2 = Components.classes["@mozilla.org/embedcomp/window-watcher;1"]
                                       .getService(Components.interfaces.nsIPromptFactory)
-                                      .getPrompt(this.mWindow, Components.interfaces.nsIAuthPrompt2);
+                                      .getPrompt(this.mProvider, Components.interfaces.nsIAuthPrompt2);
             return prompter2.promptAuth(aChannel, aLevel, aAuthInfo);
         }
     },
 
     /**
      * Asynchronously prompt the user for a username and password.
      * This has largely the same semantics as promptAuth(),
      * but must return immediately after calling and return the entered
@@ -309,30 +309,19 @@ cal.auth.Prompt.prototype = {
                 gAuthCache.retrieveAuthInfo(hostKey);
                 aCallback.onAuthCancelled(aContext, true);
             }
         };
 
         let hostKey = aChannel.URI.prePath + ":" + aAuthInfo.realm;
         gAuthCache.planForAuthInfo(hostKey);
 
-        function queuePrompt() {
-            let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
-                                          .getService(Components.interfaces.nsIMsgAsyncPrompter);
-            asyncprompter.queueAsyncAuthPrompt(hostKey, false, promptlistener);
-        }
-
-        self.mWindow = cal.getCalendarWindow();
-
-        // the prompt will fail if we are too early
-        if (self.mWindow.document.readyState != "complete") {
-            self.mWindow.addEventListener("load", queuePrompt, true);
-        } else {
-            queuePrompt();
-        }
+        let asyncprompter = Components.classes["@mozilla.org/messenger/msgAsyncPrompter;1"]
+                                      .getService(Components.interfaces.nsIMsgAsyncPrompter);
+        asyncprompter.queueAsyncAuthPrompt(hostKey, false, promptlistener);
     }
 };
 
 // Cache for authentication information since onAuthInformation in the prompt
 // listener is called without further information. If the password is not
 // saved, there is no way to retrieve it. We use ref counting to avoid keeping
 // the password in memory longer than needed.
 let gAuthCache = {
--- a/calendar/base/modules/calPrintUtils.jsm
+++ b/calendar/base/modules/calPrintUtils.jsm
@@ -1,15 +1,14 @@
 /* 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/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
-Components.utils.import("resource://calendar/modules/calViewUtils.jsm");
 
 EXPORTED_SYMBOLS = ["cal"]; // even though it's defined in calUtils.jsm, import needs this
 cal.print = {
     /**
      * Returns a simple key in the format YYYY-MM-DD for use in the table of
      * dates to day boxes
      *
      * @param dt    The date to translate
@@ -105,17 +104,17 @@ cal.print = {
         }
 
         // Fill in calendar color
         itemNode.querySelector(".calendar-color-box")
                 .setAttribute("calendar-id", cal.formatStringForCSSRule(item.calendar.id));
         cal.print.insertCalendarRules(document, item.calendar);
 
         // Add it to the day container in the right order
-        cal.binaryInsertNode(dayContainer, itemNode, item, cal.view.compareItems);
+        cal.binaryInsertNode(dayContainer, itemNode, item, comparePrintItems);
     },
 
     /**
      * Serializes the given item by setting marked nodes to the item's
      * content. Should be used for tasks with no start and due date. Has
      * some expectations about the DOM document (in CSS-selector-speak),
      * all following nodes MUST exist.
      *
@@ -165,8 +164,41 @@ cal.print = {
         if ((startDate && startDate.isDate) || (endDate && endDate.isDate)) {
             return "";
         }
 
         // Bug 359007: will result in wrong time label for events that span two or more days
         return cal.getDateFormatter().formatItemTimeInterval(aItem);
     }
 }
+
+/**
+ * Item comparator for inserting items into dayboxes.
+ *
+ * TODO This could possibly be replaced with a global item comparator so
+ * that it matches with the views and such.
+ *
+ * @param a     The first item
+ * @param b     The second item
+ * @return      The usual -1, 0, 1
+ */
+function comparePrintItems(a, b) {
+    if (!a) return -1;
+    if (!b) return 1;
+
+    // Sort tasks before events
+    if (cal.isEvent(a) && cal.isToDo(b)) {
+        return 1;
+    }
+    if (cal.isToDo(a) && cal.isEvent(b)) {
+        return -1;
+    }
+    if (cal.isEvent(a)) {
+        let startCompare = a.startDate.compare(b.startDate);
+        if (startCompare != 0) {
+            return startCompare;
+        }
+        return a.endDate.compare(b.endDate);
+    }
+    let dateA = a.entryDate || a.dueDate;
+    let dateB = b.entryDate || b.dueDate;
+    return dateA.compare(dateB);
+}
--- a/calendar/base/modules/calProviderUtils.jsm
+++ b/calendar/base/modules/calProviderUtils.jsm
@@ -112,27 +112,29 @@ cal.InterfaceRequestor_getInterface = fu
     try {
         // Try to query the this object for the requested interface but don't
         // throw if it fails since that borks the network code.
         return this.QueryInterface(aIID);
     } catch (e) {
         // Support Auth Prompt Interfaces
         if (aIID.equals(Components.interfaces.nsIAuthPrompt2)) {
             if (!this.calAuthPrompt) {
-                this.calAuthPrompt = new cal.auth.Prompt();
+                this.calAuthPrompt = new cal.auth.Prompt(this);
             }
             return this.calAuthPrompt;
         } else if (aIID.equals(Components.interfaces.nsIAuthPromptProvider) ||
                    aIID.equals(Components.interfaces.nsIPrompt)) {
             return Services.ww.getNewPrompter(null);
         } else if (aIID.equals(Components.interfaces.nsIBadCertListener2)) {
             if (!this.badCertHandler) {
                 this.badCertHandler = new cal.BadCertHandler(this);
             }
             return this.badCertHandler;
+        } else if (aIID.equals(Components.interfaces.nsIWebNavigation)) {
+            return new cal.LoadContext();
         } else {
             Components.returnCode = e;
         }
     }
     return null;
 };
 
 /**
@@ -178,16 +180,35 @@ cal.BadCertHandler.prototype = {
         timer.initWithCallback(timerCallback,
                                0,
                                Components.interfaces.nsITimer.TYPE_ONE_SHOT);
         return true;
     }
 };
 
 /**
+ * Implements an nsILoadContext that allows auth prompts to avoid using private
+ * browsing without a parent DOM window
+ */
+cal.LoadContext = function calLoadContext() {
+};
+cal.LoadContext.prototype = {
+    QueryInterface: XPCOMUtils.generateQI([Components.interfaces.nsISupports,
+                                           Components.interfaces.nsILoadContext]),
+    associatedWindow: null,
+    topWindow: null,
+    topFrameElement: null,
+    isAppOfType: function() false,
+    isContent: false,
+    usePrivateBrowsing: false,
+    isInBrowserElement: false,
+    appId: null
+};
+
+/**
  * Freebusy interval implementation. All parameters are optional.
  *
  * @param aCalId         The calendar id to set up with.
  * @param aFreeBusyType  The type from calIFreeBusyInterval.
  * @param aStart         The start of the interval.
  * @param aEnd           The end of the interval.
  * @return               The fresh calIFreeBusyInterval.
  */
--- a/calendar/base/modules/calUtils.jsm
+++ b/calendar/base/modules/calUtils.jsm
@@ -1,17 +1,17 @@
 /* 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/. */
 
 // New code must not load/import calUtils.js, but should use calUtils.jsm.
 
 var gCalThreadingEnabled;
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/Preferences.jsm");
 
 // Usually the backend loader gets loaded via profile-after-change, but in case
 // a calendar component hooks in earlier, its very likely it will use calUtils.
 // Getting the service here will load if its not already loaded
 Components.classes["@mozilla.org/calendar/backend-loader;1"].getService();
 
deleted file mode 100644
--- a/calendar/base/modules/calViewUtils.jsm
+++ /dev/null
@@ -1,46 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://calendar/modules/calUtils.jsm");
-
-EXPORTED_SYMBOLS = ["cal"];
-cal.view = {
-    /**
-      - * Item comparator for inserting items into dayboxes.
-      - *
-      - * @param a     The first item
-      - * @param b     The second item
-      - * @return      The usual -1, 0, 1
-      - */
-    compareItems: function(a, b) {
-        if (!a) return -1;
-        if (!b) return 1;
-
-        let aIsEvent = cal.isEvent(a);
-        let aIsTodo = cal.isToDo(a);
-
-        let bIsEvent = cal.isEvent(b);
-        let bIsTodo = cal.isToDo(b);
-
-        // sort todos before events
-        if (aIsTodo && bIsEvent) return -1;
-        if (aIsEvent && bIsTodo) return 1;
-
-        // todos are kept equal
-        if (aIsTodo && bIsTodo) return 0;
-
-        // sort all day events before events with a duration
-        if (a.startDate.isDate && !b.startDate.isDate) return -1;
-        if (!a.startDate.isDate && b.startDate.isDate) return 1;
-
-        let cmp = a.startDate.compare(b.startDate);
-        if (cmp != 0) return cmp;
-
-        cmp = a.endDate.compare(b.endDate);
-        if (cmp != 0) return cmp;
-
-        cmp = (a.title > b.title) - (a.title < b.title);
-        return cmp;
-    }
-}
--- a/calendar/base/modules/moz.build
+++ b/calendar/base/modules/moz.build
@@ -11,13 +11,12 @@ EXTRA_JS_MODULES += [
     'calHashedArray.jsm',
     'calItemUtils.jsm',
     'calIteratorUtils.jsm',
     'calItipUtils.jsm',
     'calPrintUtils.jsm',
     'calProviderUtils.jsm',
     'calRecurrenceUtils.jsm',
     'calUtils.jsm',
-    'calViewUtils.jsm',
     'calXMLUtils.jsm',
     'ical.js',
 ]
 
--- a/calendar/base/src/calDeletedItems.js
+++ b/calendar/base/src/calDeletedItems.js
@@ -1,15 +1,15 @@
 /* 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/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-Components.utils.import("resource://gre/modules/FileUtils.jsm");
+Components.utils.import("resource:///modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/FileUtils.jsm");
 
 /**
  * Handles remembering deleted items.
  *
  * This is (currently) not a real trashcan. Only ids and time deleted is stored.
  * Note also that the code doesn't strictly check the calendar of the item,
  * except when a calendar id is passed to getDeletedDate.
  */
--- a/calendar/base/src/calProtocolHandler.js
+++ b/calendar/base/src/calProtocolHandler.js
@@ -34,31 +34,26 @@ calProtocolHandler.prototype = {
         var uri = Components.classes["@mozilla.org/network/standard-url;1"].
                              createInstance(Components.interfaces.nsIStandardURL);
         uri.init(Components.interfaces.nsIStandardURL.URLTYPE_STANDARD, 
                  this.mHttpProtocol.defaultPort, aSpec, anOriginalCharset, aBaseURI);
         return uri;
     },
     
     newChannel: function cph_newChannel(aUri) {
-      return this.newChannel2(aUri, null);
-    },
-
-    newChannel2: function cph_newChannel2(aUri, aLoadInfo)
-    {
         // make sure to clone the uri, because we are about to change
         // it, and we don't want to change the original uri.
         var uri = aUri.clone();
         uri.scheme = this.mHttpProtocol.scheme;
 
         var channel = Services.io.newChannelFromURI(uri, null);
         channel.originalURI = aUri;
         return channel;
     },
-
+    
     // We are not overriding any special ports
     allowPort: function cph_allowPort(aPort, aScheme) false
 };
 
 const calProtocolHandlerWebcalClassID = Components.ID("{1153c73a-39be-46aa-9ba9-656d188865ca}");
 const calProtocolHandlerWebcalInterfaces = [Components.interfaces.nsIProtocolHandler];
 calProtocolHandlerWebcal.prototype = {
     __proto__: calProtocolHandler.prototype,
--- a/calendar/base/src/calRecurrenceDate.js
+++ b/calendar/base/src/calRecurrenceDate.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/XPCOMUtils.jsm");
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 
 function calRecurrenceDate() {
     this.wrappedJSObject = this;
 }
 
 const calRecurrenceDateClassID = Components.ID("{806b6423-3aaa-4b26-afa3-de60563e9cec}");
 const calRecurrenceDateInterfaces = [Components.interfaces.calIRecurrenceDate];
deleted file mode 100644
index 3cda773038c820a2429c050260a42d1000ed7e84..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index d13e1b1be5de52d9cd86df7dce66b93d72021057..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/calendar/base/themes/windows/win-aero/calendar-event-dialog.css
+++ b/calendar/base/themes/windows/win-aero/calendar-event-dialog.css
@@ -77,18 +77,8 @@ toolbar[iconsize="small"] #button-delete
 
 #button-freebusy {
   -moz-image-region: rect(1px 467px 17px 451px);
 }
 
 #button-timezones {
   -moz-image-region: rect(1px 485px 17px 469px);
 }
-
-toolbar[brighttext] .cal-event-toolbarbutton,
-toolbar[brighttext] #button-delete.cal-event-toolbarbutton,
-toolbar[brighttext] #button-delete.cal-event-toolbarbutton:hover,
-toolbar[brighttext] #button-delete.cal-event-toolbarbutton:hover:active,
-toolbar[brighttext][iconsize="small"] #button-delete.cal-event-toolbarbutton,
-toolbar[brighttext][iconsize="small"] #button-delete.cal-event-toolbarbutton:hover,
-toolbar[brighttext][iconsize="small"] #button-delete.cal-event-toolbarbutton:hover:active {
-  list-style-image: url(chrome://calendar/skin/calendar-event-dialog-toolbar-inverted.png);
-}
--- a/calendar/base/themes/windows/win-aero/calendar.css
+++ b/calendar/base/themes/windows/win-aero/calendar.css
@@ -28,26 +28,16 @@
   -moz-image-region: rect(1px 107px 17px 91px);
 }
 
 #task-addition-box > box > #calendar-add-task-button {
   list-style-image: url(chrome://calendar/skin/toolbar-aero.png);
   -moz-image-region: rect(1px 71px 17px 55px);
 }
 
-#task-actions-toolbar[brighttext] > #task-actions-category,
-#task-actions-toolbar[brighttext] > #task-actions-markcompleted,
-#task-actions-toolbar[brighttext] > #task-actions-priority {
-  list-style-image: url(chrome://calendar/skin/tasks-actions-inverted.png);
-}
-
-#task-actions-toolbar[brighttext] > #calendar-delete-task-button {
-  list-style-image: url(chrome://calendar/skin/toolbar-aero-inverted.png);
-}
-
 #calendar-add-task-button[disabled="true"] > .toolbarbutton-icon {
   opacity: 0.4;
 }
 
 #todaypane-new-event-button {
   list-style-image: url(chrome://calendar/skin/toolbar-aero.png) !important;
   -moz-image-region: rect(1px 35px 17px 19px) !important;
 }
--- a/calendar/base/themes/windows/win-aero/lightning-toolbar.css
+++ b/calendar/base/themes/windows/win-aero/lightning-toolbar.css
@@ -73,19 +73,17 @@
 #hdrExtractTaskButton {
   list-style-image: url(chrome://calendar/skin/toolbar-aero.png);
   -moz-image-region: rect(1px 71px 17px 55px);
 }
 
 #tabs-toolbar[brighttext] #extractTaskButton,
 #tabs-toolbar[brighttext] #extractEventButton,
 #mail-toolbox > toolbar[brighttext] #extractTaskButton,
-#mail-toolbox > toolbar[brighttext] #extractEventButton,
-#header-view-toolbox > toolbar[brighttext] #hdrExtractTaskButton,
-#header-view-toolbox > toolbar[brighttext] #hdrExtractEventButton {
+#mail-toolbox > toolbar[brighttext] #extractEventButton {
   list-style-image: url(chrome://calendar/skin/toolbar-aero-inverted.png) !important;
 }
 
 toolbar[brighttext] .button-appmenu {
   list-style-image: url(chrome://messenger/skin/icons/mail-toolbar-inverted.png);
 }
 
 @media (-moz-windows-glass) {
--- a/calendar/lightning/Makefile.in
+++ b/calendar/lightning/Makefile.in
@@ -82,17 +82,17 @@ endif
 # include config.mk here so myconfig or app-config can set DISABLE_LIGHTNING_INSTALL
 include $(topsrcdir)/config/config.mk
 
 # installing lightning in a thunderbird build causes problems on tinderboxes
 # (see bug 406441 and bug 440017), so we need to provide a hook for the
 # tinderboxen to disable that.
 ifndef DISABLE_LIGHTNING_INSTALL
 # install Lightning as a global extension in dist/bin/extensions/
-XPI_INSTALL_EXTENSION = $(XPI_EM_ID)
+INSTALL_EXTENSION_ID = $(XPI_EM_ID)
 endif
 
 DEFINES += -DTHUNDERBIRD_VERSION=$(THUNDERBIRD_VERSION) \
            -DTHUNDERBIRD_MAXVERSION=$(THUNDERBIRD_MAXVERSION) \
            -DAB_CD=$(AB_CD) \
            -DSEAMONKEY_VERSION=$(SEAMONKEY_VERSION) \
            -DSEAMONKEY_MAXVERSION=$(SEAMONKEY_MAXVERSION) \
            -DLIGHTNING_VERSION=$(LIGHTNING_VERSION) \
@@ -112,16 +112,23 @@ include $(srcdir)/lightning-packager.mk
 include $(srcdir)/lightning-tests.mk
 
 # For Lightning, we also need to preprocess the l10n prefs
 repack-process-extrafiles: lightning-extrafiles
 lightning-extrafiles: LOCALE_BASEDIR=$(call EXPAND_LOCALE_SRCDIR,calendar/locales)
 lightning-extrafiles:
 	$(call py_action,preprocessor,$(PREF_PPFLAGS) $(DEFINES) $(ACDEFINES) $(XULPPFLAGS) $(LOCALE_BASEDIR)/lightning-l10n.js  -o $(DIST)/$(UNIVERSAL_PATH)xpi-stage/$(L10N_XPI_NAME)/$(PREF_DIR)/lightning-l10n.js)
 
+ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
+# If the macbundle dist dir was already created, sync lightning here to avoid
+# the need to make -C objdir/mail/app each time
+libs::
+	[ -d $(DIST)/$(MOZ_MACBUNDLE_NAME) ] && rsync -aL $(FINAL_TARGET)/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/MacOS/extensions/$(XPI_EM_ID) || true
+endif
+
 ident:
 	@printf 'comm_revision '
 	@$(PYTHON) $(MOZILLA_SRCDIR)/config/printconfigsetting.py \
 	    $(FINAL_TARGET)/application.ini App SourceStamp
 	@printf 'moz_revision '
 	@$(PYTHON) $(MOZILLA_SRCDIR)/config/printconfigsetting.py \
 	    $(FINAL_TARGET)/application.ini Build SourceStamp
 	@printf 'buildid '
--- a/calendar/lightning/components/calItipProtocolHandler.js
+++ b/calendar/lightning/components/calItipProtocolHandler.js
@@ -78,21 +78,16 @@ ItipProtocolHandler.prototype = {
         let cls = Components.classes["@mozilla.org/network/standard-url;1"];
         let url = cls.createInstance(CI.nsIStandardURL);
         url.init(CI.nsIStandardURL.URLTYPE_STANDARD, 0, spec, charSet, baseURI);
         dump("Creating new URI for " + spec + "\n");
         return url.QueryInterface(CI.nsIURI);
     },
     
     newChannel: function (URI) {
-        return this.newChannel2(URI, null);
-    },
-
-    newChannel2: function(URI, aLoadInfo)
-    {
         dump("Creating new ItipChannel for " + URI + "\n");
         return new ItipChannel(URI);
     },
 };
 
 function ItipContentHandler() {
     this.wrappedJSObject = this;
 }
--- a/calendar/lightning/lightning-packager.mk
+++ b/calendar/lightning/lightning-packager.mk
@@ -172,26 +172,8 @@ upload-%: LTN_UPLOAD_CMD := $(patsubst $
 upload-%: stage_upload
 	POST_UPLOAD_CMD="$(LTN_UPLOAD_CMD)" \
 	  $(PYTHON) $(MOZILLA_DIR)/build/upload.py --base-path $(DIST) \
 	  "$(DIST)/$(MOZ_PKG_PLATFORM)/$(XPI_PKGNAME).xpi"
 
 stage_upload:
 	$(NSINSTALL) -D $(DIST)/$(MOZ_PKG_PLATFORM)
 	$(call install_cmd,$(IFLAGS1) $(XPI_STAGE_PATH)/$(XPI_PKGNAME).xpi $(DIST)/$(MOZ_PKG_PLATFORM))
-
-ifdef XPI_INSTALL_EXTENSION
-ifndef XPI_NAME
-$(error XPI_NAME must be set for XPI_INSTALL_EXTENSION)
-endif
-tools::
-	$(RM) -r '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(XPI_INSTALL_EXTENSION)'
-	$(NSINSTALL) -D '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(XPI_INSTALL_EXTENSION)'
-	$(call copy_dir,$(FINAL_TARGET),$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(XPI_INSTALL_EXTENSION))
-
-ifeq (cocoa,$(MOZ_WIDGET_TOOLKIT))
-# If the macbundle dist dir was already created, sync the xpi here to avoid
-# the need to make -C objdir/mail/app each time
-tools::
-	[ -d $(DIST)/$(MOZ_MACBUNDLE_NAME) ] && rsync -aL $(FINAL_TARGET)/ $(DIST)/$(MOZ_MACBUNDLE_NAME)/Contents/Resources/extensions/$(XPI_INSTALL_EXTENSION) || true
-endif
-
-endif
--- a/calendar/locales/all-locales
+++ b/calendar/locales/all-locales
@@ -28,17 +28,16 @@ ka
 ko
 lt
 nb-NO
 nl
 nn-NO
 pa-IN
 pl
 pt-PT
-pt-BR
 ro
 ru
 sk
 sl
 sq
 sv-SE
 tr
 uk
--- a/calendar/locales/en-US/chrome/calendar/calendar.dtd
+++ b/calendar/locales/en-US/chrome/calendar/calendar.dtd
@@ -238,26 +238,16 @@
 <!ENTITY calendar.context.synccalendars.accesskey      "S">
 <!ENTITY calendar.context.publish.label                "Publish Calendar…">
 <!ENTITY calendar.context.publish.accesskey            "b">
 <!ENTITY calendar.context.export.label                 "Export Calendar…">
 <!ENTITY calendar.context.export.accesskey             "E">
 <!ENTITY calendar.context.properties.label             "Properties">
 <!ENTITY calendar.context.properties.accesskey         "P">
 
-<!-- LOCALIZATION NOTE (calendar.context.togglevisible.accesskey)
-     This is the access key used for the showCalendar string -->
-<!ENTITY calendar.context.togglevisible.accesskey      "H">
-
-<!-- LOCALIZATION NOTE (calendar.context.showonly.accesskey)
-     This is the access key used for the showOnlyCalendar string -->
-<!ENTITY calendar.context.showonly.accesskey           "O">
-<!ENTITY calendar.context.showall.label                "Show All Calendars">
-<!ENTITY calendar.context.showall.accesskey            "A">
-
 <!ENTITY calendar.context.convertmenu.label              "Convert To">
 <!ENTITY calendar.context.convertmenu.accesskey.mail     "n">
 <!ENTITY calendar.context.convertmenu.accesskey.calendar "v">
 <!ENTITY calendar.context.convertmenu.event.label        "Event…">
 <!ENTITY calendar.context.convertmenu.event.accesskey    "E">
 <!ENTITY calendar.context.convertmenu.message.label      "Message…">
 <!ENTITY calendar.context.convertmenu.message.accesskey  "M">
 <!ENTITY calendar.context.convertmenu.task.label         "Task…">
--- a/calendar/locales/en-US/chrome/calendar/calendar.properties
+++ b/calendar/locales/en-US/chrome/calendar/calendar.properties
@@ -584,17 +584,8 @@ extractUsing=Using %1$S
 #    %2$S will be replaced with region like US in en-US
 extractUsingRegion=Using %1$S (%2$S)
 
 # LOCALIZATION NOTE (unit)
 # Used to determine the correct plural form of a unit
 unitMinutes=#1 minute;#1 minutes
 unitHours=#1 hour;#1 hours
 unitDays=#1 day;#1 days
-
-# LOCALIZATION NOTE (showCalendar)
-# Used in calendar list context menu
-#    %1$S will be replaced with the calendar name
-# uses the access key calendar.context.togglevisible.accesskey
-showCalendar=Show %1$S
-hideCalendar=Hide %1$S
-# uses the access key calendar.context.showonly.accesskey
-showOnlyCalendar=Show Only %1$S
--- a/calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.dtd
+++ b/calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.dtd
@@ -8,15 +8,9 @@
 <!ENTITY gdata.privacy.default.accesskey "D">
 
 <!ENTITY gdata.migration.title "Migrate read-only calendars">
 <!ENTITY gdata.migration.description "The Provider for Google Calendar has detected that you have existing calendars that are only capable of accessing Google Calendar in read-only mode. If you would like to upgrade any of these calendars, please select them below">
 <!ENTITY gdata.migration.upgrade.label "Upgrade">
 <!ENTITY gdata.migration.upgrade.accesskey "U">
 <!ENTITY gdata.migration.showagain.label "Always check ">
 
-<!ENTITY gdata.reminder.default "Default Reminder">
 <!ENTITY gdata.reminder.action.sms.label "Send a Text Message">
-
-<!ENTITY gdata.wizard.session.description "Please pick an existing session or enter your email address to create a new session. You only need one session per account.">
-<!ENTITY gdata.wizard.calendars.description "Please select the calendars and task lists you would like to subscribe to.">
-
-<!ENTITY gdata.wizard.nextstep.description "Please advance to the next step to set up your calendars.">
--- a/calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.properties
+++ b/calendar/locales/en-US/chrome/calendar/providers/gdata/gdata.properties
@@ -11,15 +11,10 @@
 # *FOR* Google Calendar and not *BY* Google. Also, it was explicitly stated,
 # that the phrase "Google Calendar" should be localized just as it is on the
 # localized versions of the Google Calendar UI.
 
 # Extension Manager strings
 extensions.{a62ef8ec-5fdc-40c2-873c-223b8a6925cc}.description=Allows bidirectional access to Google Calendar
 extensions.{a62ef8ec-5fdc-40c2-873c-223b8a6925cc}.name=Provider for Google Calendar
 
-# Events with only free/busy access don't have a title. Use this instead:
-busyTitle=Busy (%1$S)
-
-quotaExceeded=The quota for %1$S has been exceeded, please try again later.
-providerOutdated=This version of the provider has expired, please update to the latest version.
-
-reminderOutOfRange=Google Calendar only allows reminders up to 4 weeks before the event starts.
+# Dialog strings
+loginDialogTitle=Google Calendar Login
--- a/calendar/providers/caldav/calDavCalendar.js
+++ b/calendar/providers/caldav/calDavCalendar.js
@@ -663,23 +663,16 @@ calDavCalendar.prototype = {
 
 
                 // Translate the HTTP status code to a status and message for the listener
                 if (responseStatus == 201 || responseStatus == 204) {
                     // 201 = HTTP "Created"
                     // 204 = HTTP "No Content"
                     cal.LOG("CalDAV: Item added to " + thisCalendar.name + " successfully");
 
-                    let uriComponentParts = thisCalendar.makeUri().path.replace(/\/{2,}/g, "/").split("/").length;
-                    let targetParts = request.URI.path.split("/");
-                    targetParts.splice(0, uriComponentParts - 1);
-
-                    thisCalendar.mItemInfoCache[parentItem.id] = {
-                        locationPath: targetParts.join("/")
-                    };
                     // TODO: onOpComplete adds the item to the cache, probably after getUpdatedItem!
 
                     // Some CalDAV servers will modify items on PUT (add X-props,
                     // for instance) so we'd best re-fetch in order to know
                     // the current state of the item
                     // Observers will be notified in getUpdatedItem()
                     thisCalendar.getUpdatedItem(parentItem, aListener);
                     return;
@@ -1459,17 +1452,17 @@ calDavCalendar.prototype = {
 
     refresh: function caldav_refresh() {
         this.replayChangesOn(null);
     },
 
     firstInRealm: function caldav_firstInRealm() {
         var calendars = getCalendarManager().getCalendars({});
         for (var i = 0; i < calendars.length ; i++) {
-            if (calendars[i].type != "caldav" || calendars[i].getProperty("disabled")) {
+            if (calendars[i].type != "caldav") {
                 continue;
             }
             // XXX We should probably expose the inner calendar via an
             // interface, but for now use wrappedJSObject.
             var calendar = calendars[i].wrappedJSObject;
             if (calendar.mUncachedCalendar) {
                 calendar = calendar.mUncachedCalendar;
             }
--- a/calendar/providers/gdata/components/calGoogleUtils.js
+++ b/calendar/providers/gdata/components/calGoogleUtils.js
@@ -106,17 +106,17 @@ function getFormattedString(aBundleName,
  * @param   out aPassword       The password that belongs to the calendar.
  * @param   out aSavePassword   Should the password be saved?
  * @return  Could a password be retrieved?
  */
 function getCalendarCredentials(aCalendarName,
                                 aUsername,
                                 aPassword,
                                 aSavePassword) {
-    return cal.auth.getCredentials("Google Calendar",
+    return cal.auth.getCredentials(getFormattedString("gdata", "loginDialogTitle"),
                                    aCalendarName,
                                    aUsername,
                                    aPassword,
                                    aSavePassword);
 }
 
 /**
  * Gets the date and time that Google's http server last sent us. Note the
--- a/calendar/providers/storage/calStorageUpgrade.jsm
+++ b/calendar/providers/storage/calStorageUpgrade.jsm
@@ -61,17 +61,17 @@
  *     version (setDbVersionAndCommit also commits the transaction)
  * - If something fails, throw reportErrorAndRollback(db, e) to report the
  *     failure and roll back the transaction.
  *
  * If this documentation isn't sufficient to make upgrading understandable,
  * please file a bug.
  */
 
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource:///modules/Services.jsm");
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
 Components.utils.import("resource://calendar/modules/calStorageHelpers.jsm");
 
 // The current database version. Be sure to increment this when you create a new
 // updater.
 var DB_SCHEMA_VERSION = 22;
 
 var EXPORTED_SYMBOLS = ["DB_SCHEMA_VERSION", "getSql", "getAllSql", "getSqlTable", "upgradeDB", "backupDB"];
--- a/calendar/test/mozmill/testAlarmDefaultValue.js
+++ b/calendar/test/mozmill/testAlarmDefaultValue.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 /**
  * @title Test default alarm settings for events and tasks
  * @litmus 2510
  */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
-Components.utils.import("resource://gre/modules/PluralForm.jsm");
+Components.utils.import("resource:///modules/PluralForm.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm");
 
 var MODULE_NAME = "testAlarmDefaultValue";
 var RELATIVE_ROOT = "./shared-modules";
 var MODULE_REQUIRES = ["calendar-utils"];
 
 var calendarController;
 var calUtils = require("shared-modules/calendar-utils");
--- a/calendar/test/unit/head_consts.js
+++ b/calendar/test/unit/head_consts.js
@@ -209,19 +209,19 @@ function do_check_throws(func, result, s
 {
   if (!stack)
     stack = Components.stack.caller;
 
   try {
     func();
   } catch (exc) {
     if (exc.result == result || exc == result) {
-      let msg = stack.filename + " | [" + stack.name + " : " +
-           stack.lineNumber + "] " + exc.result + " == " + result + "\n";
-      do_report_result(true, msg, stack);
+      ++_passedChecks;
+      dump("TEST-PASS | " + stack.filename + " | [" + stack.name + " : " +
+           stack.lineNumber + "] " + exc.result + " == " + result + "\n");
       return;
     }
     do_throw("expected result " + result + ", caught " + (exc.result || exc), stack);
   }
 
   if (result) {
     do_throw("expected result " + result + ", none thrown", stack);
   }
--- a/calendar/test/unit/test_alarmservice.js
+++ b/calendar/test/unit/test_alarmservice.js
@@ -1,14 +1,14 @@
 /* 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/. */
 
 Components.utils.import("resource://calendar/modules/calUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource:///modules/Services.jsm");
 
 const EXPECT_NONE = 0;
 const EXPECT_FIRED = 1;
 const EXPECT_TIMER = 2;
 
 function do_check_xor(a, b) do_check_true((a && !b) || (!a && b));
 
 let alarmObserver = {
--- a/calendar/test/unit/test_freebusy_service.js
+++ b/calendar/test/unit/test_freebusy_service.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/XPCOMUtils.jsm");
 Components.utils.import("resource://calendar/modules/calProviderUtils.jsm");
 
 const cIFI = Components.interfaces.calIFreeBusyInterval;
 let freebusy = Components.classes["@mozilla.org/calendar/freebusy-service;1"]
                          .getService(Components.interfaces.calIFreeBusyService);
 
 function run_test() {
     test_found();
--- a/calendar/test/unit/test_ics_service.js
+++ b/calendar/test/unit/test_ics_service.js
@@ -101,55 +101,32 @@ function test_icsservice() {
     }
 
     // Test ::createIcalPropertyFromString
     checkProp(svc.createIcalPropertyFromString.bind(svc),
               "ATTACH;ENCODING=BASE64;FMTTYPE=text/calendar;FILENAME=test.ics:http://example.com/test.ics",
               { value: "http://example.com/test.ics", propertyName: "ATTACH" },
               { ENCODING: "BASE64", FMTTYPE: "text/calendar", FILENAME: "test.ics" });
 
-    checkProp(svc.createIcalPropertyFromString.bind(svc),
-              "DESCRIPTION:new\\nlines\\nare\\ngreat\\,eh?",
-              { value: "new\nlines\nare\ngreat,eh?",
-                valueAsIcalString: "new\\nlines\\nare\\ngreat\\,eh?" }, {});
-
     // Test ::createIcalProperty
     let attach2 = svc.createIcalProperty("ATTACH");
     do_check_eq(attach2.propertyName, "ATTACH");
     attach2.value = "http://example.com/";
     do_check_eq(attach2.icalString, "ATTACH:http://example.com/\r\n");
 }
 
 function test_icalproperty() {
     let svc = cal.getIcsService();
     let comp = svc.createIcalComponent("VEVENT");
     let prop = svc.createIcalProperty("PROP");
     prop.value = "VAL";
 
     comp.addProperty(prop);
     do_check_eq(prop.parent.toString(), comp.toString());
     do_check_eq(prop.valueAsDatetime, null);
-
-    prop = svc.createIcalProperty("PROP");
-    prop.value = "A\nB";
-    do_check_eq(prop.value, "A\nB");
-    do_check_eq(prop.valueAsIcalString, "A\\nB");
-    do_check_eq(prop.valueAsDatetime, null);
-
-    prop = svc.createIcalProperty("PROP");
-    prop.valueAsIcalString = "A\\nB";
-    do_check_eq(prop.value, "A\nB");
-    do_check_eq(prop.valueAsIcalString, "A\\nB");
-    do_check_eq(prop.valueAsDatetime, null);
-
-    prop = svc.createIcalProperty("PROP");
-    prop.value = "A\\nB";
-    do_check_eq(prop.value, "A\\nB");
-    do_check_eq(prop.valueAsIcalString, "A\\\\nB");
-    do_check_eq(prop.valueAsDatetime, null);
 }
 
 function test_icalcomponent() {
     let svc = cal.getIcsService();
     let event = svc.createIcalComponent("VEVENT");
     let todo = svc.createIcalComponent("VTODO");
     let alarm = svc.createIcalComponent("VALARM");
     event.addSubcomponent(alarm);
--- a/calendar/test/unit/test_search_service.js
+++ b/calendar/test/unit/test_search_service.js
@@ -1,13 +1,13 @@
 /* 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/. */
 
-Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+Components.utils.import("resource:///modules/XPCOMUtils.jsm");
 
 const HINT_EXACT_MATCH = Components.interfaces.calICalendarSearchProvider.HINT_EXACT_MATCH;
 let search = Components.classes["@mozilla.org/calendar/calendarsearch-service;1"]
                        .getService(Components.interfaces.calICalendarSearchService);
 
 function run_test() {
     test_found();
     test_failure();
deleted file mode 100644
--- a/calendar/test/unit/test_view_utils.js
+++ /dev/null
@@ -1,118 +0,0 @@
-/* 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/. */
-
-Components.utils.import("resource://calendar/modules/calViewUtils.jsm");
-
-function run_test() {
-    test_not_a_date();
-    test_compare_event_and_todo();
-    test_compare_startdate();
-    test_compare_enddate();
-    test_compare_alldayevent();
-    test_compare_title();
-    test_compare_todo();
-}
-
-function test_not_a_date() {
-    let item = cal.createEvent();
-
-    let result = cal.view.compareItems(null, item);
-    equal(result, -1);
-
-    result = cal.view.compareItems(item, null);
-    equal(result, 1);
-}
-
-function test_compare_event_and_todo() {
-    let a = cal.createEvent();
-    let b = cal.createTodo();
-
-    let result = cal.view.compareItems(a, b);
-    equal(result, 1);
-
-    result = cal.view.compareItems(b, a);
-    equal(result, -1);
-}
-
-function test_compare_startdate() {
-    let a = cal.createEvent();
-    a.startDate = createDate(1990, 0, 1, 1);
-    let b = cal.createEvent();
-    b.startDate = createDate(2000, 0, 1, 1);
-
-    let result = cal.view.compareItems(a, b);
-    equal(result, -1);
-
-    result = cal.view.compareItems(b, a);
-    equal(result, 1);
-
-    result = cal.view.compareItems(a, a);
-    equal(result, 0);
-}
-
-function test_compare_enddate() {
-    let a = cal.createEvent();
-    a.startDate = createDate(1990, 0, 1, 1);
-    a.endDate = createDate(1990, 0, 2, 1);
-    let b = cal.createEvent();
-    b.startDate = createDate(1990, 0, 1, 1);
-    b.endDate = createDate(1990, 0, 5, 1);
-
-    let result = cal.view.compareItems(a, b);
-    equal(result, -1);
-
-    result = cal.view.compareItems(b, a);
-    equal(result, 1);
-
-    result = cal.view.compareItems(a, a);
-    equal(result, 0);
-}
-
-function test_compare_alldayevent() {
-    let a = cal.createEvent();
-    a.startDate = createDate(1990, 0, 1);
-    let b = cal.createEvent();
-    b.startDate = createDate(1990, 0, 1, 1);
-
-    let result = cal.view.compareItems(a, b);
-    equal(result, -1);
-
-    result = cal.view.compareItems(b, a);
-    equal(result, 1);
-
-    result = cal.view.compareItems(a, a);
-    equal(result, 0);
-}
-
-function test_compare_title() {
-    let a = cal.createEvent();
-    a.startDate = createDate(1990, 0, 1);
-    a.title = "Abc";
-    let b = cal.createEvent();
-    b.startDate = createDate(1990, 0, 1);
-    b.title = "Xyz";
-
-    let result = cal.view.compareItems(a, b);
-    equal(result, -1);
-
-    result = cal.view.compareItems(b, a);
-    equal(result, 1);
-
-    result = cal.view.compareItems(a, a);
-    equal(result, 0);
-}
-
-function test_compare_todo() {
-    let a = cal.createTodo();
-    let b = cal.createTodo();
-
-    let cmp = cal.view.compareItems(a, b);
-    equal(cmp, 0);
-
-    cmp = cal.view.compareItems(b, a);
-    equal(cmp, 0);
-
-    cmp = cal.view.compareItems(a, a);
-    equal(cmp, 0);
-}
--- a/calendar/test/unit/xpcshell.ini
+++ b/calendar/test/unit/xpcshell.ini
@@ -34,10 +34,9 @@ run-sequentially = Avoid bustage.
 [test_rfc3339_parser.js]
 [test_search_service.js]
 [test_startup_service.js]
 [test_storage.js]
 [test_utils.js]
 [test_calmgr.js]
 [test_deleted_items.js]
 [test_extract.js]
-[test_view_utils.js]
 [test_webcal.js]
--- a/chat/chat-prefs.js
+++ b/chat/chat-prefs.js
@@ -31,20 +31,16 @@ pref("messenger.buddies.hiddenTags", "")
 //  0 ignores the invitations,
 // -1 rejects the invitations.
 pref("messenger.conversations.autoAcceptChatInvitations", 1);
 
 // Indicates whether the core should always close conversations closed
 // by the UI or if they can be put on hold instead.
 pref("messenger.conversations.alwaysClose", false);
 
-// Put conversations with contacts on hold by default (i.e. match the default
-// behavior for MUCs) as long as .alwaysClose is not true.
-pref("messenger.conversations.holdByDefault", false);
-
 pref("messenger.conversations.selections.magicCopyEnabled", true);
 pref("messenger.conversations.selections.ellipsis", "chrome://chat/locale/conversations.properties");
 pref("messenger.conversations.selections.systemMessagesTemplate", "chrome://chat/locale/conversations.properties");
 pref("messenger.conversations.selections.contentMessagesTemplate", "chrome://chat/locale/conversations.properties");
 pref("messenger.conversations.selections.actionMessagesTemplate", "chrome://chat/locale/conversations.properties");
 
 pref("messenger.conversations.textbox.autoResize", true);
 pref("messenger.conversations.textbox.defaultMaxLines", 5);
--- a/chat/components/public/imIAccount.idl
+++ b/chat/components/public/imIAccount.idl
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsISupports.idl"
 #include "prplIConversation.idl"
 #include "imIUserStatusInfo.idl"
 
 interface imITag;
 interface imIBuddy;
-interface prplIAccountBuddy;
+interface imIAccountBuddy;
 interface imIAccount;
 interface prplIAccount;
 interface prplIProtocol;
 interface purpleIProxyInfo;
 interface nsIScriptError;
 interface nsISSLStatus;
 
 /*
@@ -68,17 +68,17 @@ interface prplIRoomInfoCallback: nsISupp
                            in boolean aCompleted,
                            in unsigned long aCount);
 };
 
 
 /*
  * This interface should be implemented by the protocol plugin.
  */
-[scriptable, uuid(55331ab9-54e9-4cd3-bb19-a46da76898e5)]
+[scriptable, uuid(bc540cab-a6e9-4c2c-abff-e95d0d1370a1)]
 interface prplIAccount: nsISupports {
   readonly attribute imIAccount imAccount;
 
   // observe should only be called by the imIAccount
   // implementation to report user status changes that affect this account.
   void observe(in nsISupports aObj, in string aEvent,
                [optional] in wstring aData);
 
@@ -97,17 +97,17 @@ interface prplIAccount: nsISupports {
   void disconnect();
 
   prplIConversation createConversation(in AUTF8String aName);
 
   // Used when the user wants to add a buddy to the buddy list
   void addBuddy(in imITag aTag, in AUTF8String aName);
 
   // Used while loading the buddy list at startup.
-  prplIAccountBuddy loadBuddy(in imIBuddy aBuddy, in imITag aTag);
+  imIAccountBuddy loadBuddy(in imIBuddy aBuddy, in imITag aTag);
 
   /* Request more info on a buddy (typically a chat buddy).
    * The result (if any) will be provided by a user-info-received
    * notification dispatched through the observer service:
    *  - aSubject will be an nsISimpleEnumerator of prplITooltipInfo.
    *  - aData will be aBuddyName.
    */
   void requestBuddyInfo(in AUTF8String aBuddyName);
@@ -254,20 +254,17 @@ interface imIAccount: prplIAccount {
   /* Set when the account is trying to connect for the first time
      with the current parameters (removed after a successsful connection) */
   const short FIRST_CONNECTION_PENDING = 2;
   /* Set at startup when the previous state was pending */
   const short FIRST_CONNECTION_CRASHED = 4;
 
   attribute short firstConnectionState;
 
-  /* Passwords are stored in the toolkit Password Manager.
-   * Warning: Don't attempt to access passwords during startup before
-   * Services.login.initializationPromise has resolved.
-   */
+  // Passwords are stored in the toolkit Password Manager.
   attribute AUTF8String password;
 
   attribute AUTF8String alias;
 
   /* While an account is connecting, this attribute contains a message
      indicating the current step of the connection */
   readonly attribute AUTF8String connectionStateMsg;
 
--- a/chat/components/public/imIContactsService.idl
+++ b/chat/components/public/imIContactsService.idl
@@ -5,41 +5,41 @@
 #include "imIStatusInfo.idl"
 #include "imITagsService.idl"
 #include "nsISupports.idl"
 #include "nsIObserver.idl"
 #include "nsISimpleEnumerator.idl"
 
 interface imIContact;
 interface imIBuddy;
-interface prplIAccountBuddy;
+interface imIAccountBuddy;
 interface imIAccount;
 interface prplIProtocol;
 
-[scriptable, uuid(45ce33d9-d335-4cce-b904-44821987e048)]
+[scriptable, uuid(be0f7dd6-26ca-445c-a265-99cf9612ece8)]
 interface imIContactsService: nsISupports {
   void initContacts();
   void unInitContacts();
 
   imIContact getContactById(in long aId);
   // Get an array of all existing contacts.
   void getContacts([optional] out unsigned long contactCount,
                    [retval, array, size_is(contactCount)] out imIContact contacts);
   imIBuddy getBuddyById(in long aId);
   imIBuddy getBuddyByNameAndProtocol(in AUTF8String aNormalizedName,
                                      in prplIProtocol aPrpl);
-  prplIAccountBuddy getAccountBuddyByNameAndAccount(in AUTF8String aNormalizedName,
-                                                    in imIAccount aAccount);
+  imIAccountBuddy getAccountBuddyByNameAndAccount(in AUTF8String aNormalizedName,
+                                                  in imIAccount aAccount);
 
   // These 3 functions are called by the protocol plugins when
   // synchronizing the buddy list with the server stored list,
   // or after user operations have been performed.
-  void accountBuddyAdded(in prplIAccountBuddy aAccountBuddy);
-  void accountBuddyRemoved(in prplIAccountBuddy aAccountBuddy);
-  void accountBuddyMoved(in prplIAccountBuddy aAccountBuddy,
+  void accountBuddyAdded(in imIAccountBuddy aAccountBuddy);
+  void accountBuddyRemoved(in imIAccountBuddy aAccountBuddy);
+  void accountBuddyMoved(in imIAccountBuddy aAccountBuddy,
                          in imITag aOldTag, in imITag aNewTag);
 
   // These methods are called by the imIAccountsService implementation
   // to keep the accounts table in sync with accounts stored in the
   // preferences.
 
   // Called when an account is created or loaded to store the new
   // account or ensure it doesn't conflict with an existing account
@@ -49,30 +49,16 @@ interface imIContactsService: nsISupport
   void storeAccount(in unsigned long aId, in AUTF8String aUserName,
                     in AUTF8String aPrplId);
   // Check if an account id already exists in the database.
   boolean accountIdExists(in unsigned long aId);
   // Called when deleting an account to remove it from blist.sqlite.
   void forgetAccount(in unsigned long aId);
 };
 
-/*
- * An imIContact represents a person, e.g. our friend Alice. This person might
- * have multiple means of contacting them.
- *
- * Remember that an imIContact can have multiple buddies (imIBuddy instances),
- * each imIBuddy can have multiple account-buddies (prplIAccountBuddy instances)
- * referencing it. To be explicit, the difference is that an imIBuddy represents
- * a contact's account on a network, while a prplIAccountBuddy represents the
- * link between your account and your contact's account.
- *
- * Each of these implement imIStatusInfo: imIContact and imIBuddy should merge
- * the status info based on the information available in their instances of
- * imIBuddy and prplIAccountBuddy, respectively.
- */
 [scriptable, uuid(f585b0df-f6ad-40d5-9de4-c58b14af13e4)]
 interface imIContact: imIStatusInfo {
   // The id will be positive if the contact is real (stored in the
   // SQLite database) and negative if the instance is a dummy contact
   // holding only a single buddy without aliases or additional tags.
   readonly attribute long id;
   attribute AUTF8String alias;
 
@@ -141,53 +127,44 @@ interface imIContact: imIStatusInfo {
    *   contact-no-longer-dummy
    *     When a real contact is created to replace a dummy contact.
    *     The old (negative) id will be given in aData.
    *     See also the comment above the 'id' attribute.
    *   contact-icon-changed
    *
    * Observers will also receive all the (forwarded) notifications
    * from the linked buddies (imIBuddy instances) and their account
-   * buddies (prplIAccountBuddy instances).
+   * buddies (imIAccountBuddy instances).
    */
 
   // Exposed for add-on authors. All internal calls will come from the
   // imIContact implementation itself so it wasn't required to expose this.
   // This can be used to dispatch custom notifications to the
   // observers of the contact and its tags.
   // The notification will also be forwarded to the observer service.
   void notifyObservers(in nsISupports aObj, in string aEvent,
                        [optional] in wstring aData);
 };
 
-/*
- * An imIBuddy represents a person's account on a particular network. Note that
- * what a network is depends on the implementation of the prpl, e.g. for AIM
- * there is only a single network, but both GTalk and XMPP are the same network.
- *
- * E.g. Our contact Alice has two accounts on the Foo network: @lic4 and
- * alice88; and she has a single account on the Bar network: _alice_. This would
- * result in an imIBuddy instance for each of these: @lic4, alice88, and _alice_
- * that would all exist as part of the same imIContact.
- */
-[scriptable, uuid(c56520ba-d923-4b95-8416-ca6733c4a38e)]
+
+[scriptable, uuid(fea582a0-3839-4d80-bcab-0ff82ae8f97f)]
 interface imIBuddy: imIStatusInfo {
   readonly attribute long id;
   readonly attribute prplIProtocol protocol;
   readonly attribute AUTF8String userName; // may be formatted
   // A name that can be used to check for duplicates and is the basis
   // for the directory name for log storage.
   readonly attribute AUTF8String normalizedName;
   // The optional server alias is in displayName (inherited from imIStatusInfo)
   // displayName = serverAlias || userName.
 
   readonly attribute imIContact contact;
-  readonly attribute prplIAccountBuddy preferredAccountBuddy;
+  readonly attribute imIAccountBuddy preferredAccountBuddy;
   void getAccountBuddies([optional] out unsigned long accountBuddyCount,
-                         [retval, array, size_is(accountBuddyCount)] out prplIAccountBuddy accountBuddies);
+                         [retval, array, size_is(accountBuddyCount)] out imIAccountBuddy accountBuddies);
 
   // remove the buddy from the buddy list. If the contact becomes empty, it will be removed too.
   void remove();
 
   void addObserver(in nsIObserver aObserver);
   void removeObserver(in nsIObserver aObserver);
   /* Observers will be notified of changes related to the buddy.
    *  aSubject will point to the imIBuddy object.
@@ -201,69 +178,57 @@ interface imIBuddy: imIStatusInfo {
    *   buddy-display-name-changed
    *     when the serverAlias has changed.
    *     The old display name is provided in aData.
    *   buddy-preferred-account-changed
    *     The account that would be favored to start a conversation has changed.
    *   buddy-icon-changed
    *
    * Observers will also receive all the (forwarded) notifications
-   * from the linked account buddies (prplIAccountBuddy instances).
+   * from the linked account buddies (imIAccountBuddy instances).
    */
 
   // Exposed for add-on authors. All internal calls will come from the
   // imIBuddy implementation itself so it wasn't required to expose this.
   // This can be used to dispatch custom notifications to the
   // observers of the buddy, its contact and its tags.
   // The contact will forward the notifications to the observer service.
   void notifyObservers(in nsISupports aObj, in string aEvent,
                        [optional] in wstring aData);
 
-  // observe should only be called by the prplIAccountBuddy
+  // observe should only be called by the imIAccountBuddy
   // implementations to report changes.
   void observe(in nsISupports aObj, in string aEvent,
                [optional] in wstring aData);
 };
 
-/*
- * A prplIAccountBuddy represents the connection on a network between one of the
- * current user's accounts and a persons's account. E.g. if we're logged into
- * the Foo network as BobbyBoy91 and want to talk to Alice, there may be two
- * prplIAccountBuddy instances: @lic4 as seen by BobbyBoy91 or alice88 as seen
- * by BobbyBoy91. Additionally, if we also login as 8ob, there could be @lic4 as
- * seen by 8ob and alice88 as seen by 8ob; but these (now four)
- * prplIAccountBuddy instances would link to only TWO imIBuddy instances (one
- * each for @lic4 and alice88). Note that the above uses "may be" and "could"
- * because it depends on whether the contacts are on the contact list (and
- * therefore have imIContact / imIBuddy instances).
+/* imIAccountBuddy implementations can send notifications to their buddy:
  *
- * prplIAccountBuddy implementations send notifications to their buddy:
- *
- * For all of them, aSubject points to the prplIAccountBuddy object.
+ * For all of them, aSubject points to the imIAccountBuddy object.
  *
  * Supported notifications:
  *  account-buddy-availability-changed
  *    when either statusType or availabilityDetails has changed.
  *  account-buddy-signed-on
  *  account-buddy-signed-off
  *  account-buddy-status-changed
  *    when either statusType or statusText has changed.
  *  account-buddy-display-name-changed
  *    when the serverAlias has changed.
  *    The old display name is provided in aData.
  *  account-buddy-icon-changed
  *
  * All notifications (even unsupported ones) will be forwarded to the contact,
  * its tags and nsObserverService.
  */
-[scriptable, uuid(0c5021ac-7acd-4118-bf4f-c0dd9cb3ddef)]
-interface prplIAccountBuddy: imIStatusInfo {
+[scriptable, uuid(114d24ff-56a1-4fd6-9822-4992efb6e036)]
+interface imIAccountBuddy: imIStatusInfo {
   // The setter is for internal use only. buddy will be set by the
   // Contacts service when accountBuddyAdded is called on this
-  // instance of prplIAccountBuddy.
+  // instance of imIAccountBuddy.
            attribute imIBuddy buddy;
   readonly attribute imIAccount account;
   // Setting the tag will move the buddy to a different group on the
   // server-stored buddy list.
            attribute imITag tag;
   readonly attribute AUTF8String userName;
   // A name that can be used to check for duplicates and is the basis
   // for the directory name for log storage.
--- a/chat/components/public/imILogger.idl
+++ b/chat/components/public/imILogger.idl
@@ -2,39 +2,39 @@
  * 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/. */
 
 #include "nsISupports.idl"
 #include "nsISimpleEnumerator.idl"
 #include "nsIFile.idl"
 
 interface imIAccount;
-interface prplIAccountBuddy;
+interface imIAccountBuddy;
 interface imIBuddy;
 interface imIContact;
 interface imIMessage;
 interface prplIConversation;
 
-[scriptable, uuid(7771402c-ff55-41f5-86b4-59b93f9b0693)]
+[scriptable, uuid(5bc06f3b-33a1-412b-a4d8-4fc7ba4c962b)]
 interface imILogConversation: nsISupports {
   readonly attribute AUTF8String title;
   readonly attribute AUTF8String name;
   // Value in microseconds.
   readonly attribute PRTime startDate;
 
   // Simplified account implementation:
   //  - alias will always be empty
   //  - name (always the normalizedName)
   //  - statusInfo will return Services.core.globalUserStatus
   //  - protocol will only contain a "name" attribute, with the prpl's normalized name.
   // Other methods/attributes aren't implemented.
   readonly attribute imIAccount account;
 
   readonly attribute boolean isChat; // always false (compatibility with prplIConversation).
-  readonly attribute prplIAccountBuddy buddy; // always null (compatibility with prplIConvIM).
+  readonly attribute imIAccountBuddy buddy; // always null (compatibility with prplIConvIM).
 
   void getMessages([optional] out unsigned long messageCount,
                    [retval, array, size_is(messageCount)] out imIMessage messages);
 
   // Callers that process the messages asynchronously should use the enumerator
   // instead of the array version of the getMessages* methods to avoid paying
   // up front the cost of xpconnect wrapping all message objects.
   nsISimpleEnumerator getMessagesEnumerator([optional] out unsigned long messageCount);
@@ -54,33 +54,33 @@ interface imILog: nsISupports {
 [scriptable, function, uuid(2ab5f8ac-4b89-4954-9a4a-7c167f1e3b0d)]
 interface imIProcessLogsCallback: nsISupports {
   // The callback can return a promise. If it does, then it will not be called
   // on the next log until this promise resolves. If it throws (or rejects),
   // iteration will stop.
   jsval processLog(in AUTF8String aLogPath);
 };
 
-[scriptable, uuid(f8ac75ed-e9b5-432e-989b-f01fed2e5a3f)]
+[scriptable, uuid(b9d5701a-df53-4e0e-99b7-706e0118e075)]
 interface imILogger: nsISupports {
   // Returns a promise that resolves to an imILog instance.
   jsval getLogFromFile(in AUTF8String aFilePath, [optional] in boolean aGroupByDay);
   // Returns a promise that resolves to the log file path if a log writer
   // exists for the conversation, or null otherwise. The promise resolves
   // after any pending I/O operations on the file complete.
   jsval getLogPathForConversation(in prplIConversation aConversation);
 
   // Below methods return promises that resolve to nsISimpleEnumerator instances.
 
   // Get logs for a username that may not be in the contact list.
   jsval getLogsForAccountAndName(in imIAccount aAccount,
                                  in AUTF8String aNormalizedName,
                                  [optional] in boolean aGroupByDay);
 
-  jsval getLogsForAccountBuddy(in prplIAccountBuddy aAccountBuddy,
+  jsval getLogsForAccountBuddy(in imIAccountBuddy aAccountBuddy,
                                [optional] in boolean aGroupByDay);
   jsval getLogsForBuddy(in imIBuddy aBuddy,
                         [optional] in boolean aGroupByDay);
   jsval getLogsForContact(in imIContact aContact,
                           [optional] in boolean aGroupByDay);
 
   jsval getLogsForConversation(in prplIConversation aConversation,
                                [optional] in boolean aGroupByDay);
--- a/chat/components/public/imITagsService.idl
+++ b/chat/components/public/imITagsService.idl
@@ -19,17 +19,17 @@ interface imITag: nsISupports {
   void getContacts([optional] out unsigned long contactCount,
                    [retval, array, size_is(contactCount)] out imIContact contacts);
 
   void addObserver(in nsIObserver aObserver);
   void removeObserver(in nsIObserver aObserver);
   /* Observers will be notified of changes related to the contacts
    * that have the tag: contact-*, buddy-*, account-buddy-*
    * notifications forwarded respectively from the imIContact,
-   * imIBuddy and prplIAccountBuddy instances.
+   * imIBuddy and imIAccountBuddy instances.
    */
 
   // Exposed for add-on authors. All internal calls will come from the
   // imITag implementation itself so it wasn't required to expose this.
   // This can be used to dispatch custom notifications to the
   // observers of the tag.
   void notifyObservers(in nsISupports aObj, in string aEvent,
                        [optional] in wstring aData);
--- a/chat/components/public/prplIConversation.idl
+++ b/chat/components/public/prplIConversation.idl
@@ -2,17 +2,17 @@
  * 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/. */
 
 
 #include "nsISupports.idl"
 #include "nsISimpleEnumerator.idl"
 #include "nsIObserver.idl"
 
-interface prplIAccountBuddy;
+interface imIAccountBuddy;
 interface imIAccount;
 interface imIOutgoingMessage;
 interface nsIURI;
 interface nsIDOMDocument;
 interface prplIChatRoomFieldValues;
 
 /*
  * This is the XPCOM purple conversation component, a proxy for PurpleConversation.
@@ -69,21 +69,21 @@ interface prplIConversation: nsISupports
   /* Method to add or remove an observer */
   void addObserver(in nsIObserver aObserver);
   void removeObserver(in nsIObserver aObserver);
 
   /* Observers will be all receive new-text notifications.
      aSubject will contain the message (prplIMessage) */
 };
 
-[scriptable, uuid(c0b5b647-b0ec-4dc6-9e53-31a762a30a6e)]
+[scriptable, uuid(0c072a80-103a-4992-b249-8e442b5f0d46)]
 interface prplIConvIM: prplIConversation {
 
   /* The buddy at the remote end of the conversation */
-  readonly attribute prplIAccountBuddy buddy;
+  readonly attribute imIAccountBuddy buddy;
 
   /* The remote buddy is not currently typing */
   const short NOT_TYPING = 0;
 
   /* The remote buddy is currently typing */
   const short TYPING = 1;
 
   /* The remote buddy started typing, but has stopped typing */
--- a/chat/components/src/imAccounts.js
+++ b/chat/components/src/imAccounts.js
@@ -156,35 +156,33 @@ function imAccount(aKey, aName, aPrplId)
   // Send status change notifications to the account.
   this.observedStatusInfo = null; // (To execute the setter).
 
   // If we have never finished the first connection attempt for this account,
   // mark the account as having caused a crash.
   if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_PENDING)
     this.firstConnectionState = Ci.imIAccount.FIRST_CONNECTION_CRASHED;
 
-  Services.logins.initializationPromise.then(() => {
-    // Try to convert old passwords stored in the preferences.
-    // Don't try too hard if the user has canceled a master password prompt:
-    // we don't want to display several of theses prompts at startup.
-    if (gConvertingOldPasswords && !this.protocol.noPassword) {
-      try {
-        let password = this.prefBranch.getComplexValue(kPrefAccountPassword,
-                                                       Ci.nsISupportsString).data;
-        if (password && !this.password)
-          this.password = password;
-      } catch (e) { /* No password saved in the prefs for this account. */ }
-    }
+  // Try to convert old passwords stored in the preferences.
+  // Don't try too hard if the user has canceled a master password prompt:
+  // we don't want to display several of theses prompts at startup.
+  if (gConvertingOldPasswords && !this.protocol.noPassword) {
+    try {
+      let password = this.prefBranch.getComplexValue(kPrefAccountPassword,
+                                                     Ci.nsISupportsString).data;
+      if (password && !this.password)
+        this.password = password;
+    } catch (e) { /* No password saved in the prefs for this account. */ }
+  }
 
-    // Check for errors that should prevent connection attempts.
-    if (this._passwordRequired && !this.password)
-      this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
-    else if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED)
-      this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED;
-  });
+  // Check for errors that should prevent connection attempts.
+  if (this._passwordRequired && !this.password)
+    this._connectionErrorReason = Ci.imIAccount.ERROR_MISSING_PASSWORD;
+  else if (this.firstConnectionState == Ci.imIAccount.FIRST_CONNECTION_CRASHED)
+    this._connectionErrorReason = Ci.imIAccount.ERROR_CRASHED;
 }
 
 imAccount.prototype = {
   __proto__: ClassInfo(["imIAccount", "prplIAccount"], "im account object"),
 
   name: "",
   id: "",
   numericId: 0,
--- a/chat/components/src/imCommands.js
+++ b/chat/components/src/imCommands.js
@@ -29,20 +29,17 @@ CommandsService.prototype = {
     });
 
     this.registerCommand({
       name: "raw",
       get helpString() _("rawHelpString"),
       usageContext: Ci.imICommand.CMD_CONTEXT_ALL,
       priority: Ci.imICommand.CMD_PRIORITY_DEFAULT,
       run: function(aMsg, aConv) {
-        let conv = Services.conversations.getUIConversation(aConv);
-        if (!conv)
-          return false;
-        conv.sendMsg(aMsg);
+        aConv.sendMsg(aMsg);
         return true;
       }
     });
 
     this.registerCommand({
       // Reference the command service so we can use the internal properties
       // directly.
       cmdSrv: this,
--- a/chat/components/src/imContacts.js
+++ b/chat/components/src/imContacts.js
@@ -93,23 +93,24 @@ function getDBConnection()
 // we flush buddy list data to disk only once per event loop spin.
 var gDBConnWithPendingTransaction = null;
 this.__defineGetter__("DBConn", function() {
   if (gDBConnWithPendingTransaction)
     return gDBConnWithPendingTransaction;
 
   if (!gDBConnection) {
     gDBConnection = getDBConnection();
-    Services.obs.addObserver(function dbClose(aSubject, aTopic, aData) {
+    function dbClose(aSubject, aTopic, aData) {
       Services.obs.removeObserver(dbClose, aTopic);
       if (gDBConnection) {
         gDBConnection.asyncClose();
         gDBConnection = null;
       }
-    }, "profile-before-change", false);
+    }
+    Services.obs.addObserver(dbClose, "profile-before-change", false);
   }
   gDBConnWithPendingTransaction = gDBConnection;
   gDBConnection.beginTransaction();
   executeSoon(function() {
     gDBConnWithPendingTransaction.commitTransaction();
     gDBConnWithPendingTransaction = null;
   });
   return gDBConnection;
@@ -1130,17 +1131,17 @@ Buddy.prototype = {
     } catch (e) {
       Cu.reportError(e);
     }
   },
   _notifyObservers: function(aTopic, aData) {
     this.notifyObservers(this, "buddy-" + aTopic, aData);
   },
 
-  // This is called by the prplIAccountBuddy implementations.
+  // This is called by the imIAccountBuddy implementations.
   observe: function(aSubject, aTopic, aData) {
     // Forward the notification.
     this.notifyObservers(aSubject, aTopic, aData);
 
     switch (aTopic) {
       case "account-buddy-availability-changed":
         this._updatePreferredAccount(aSubject);
         break;
@@ -1301,17 +1302,17 @@ ContactsService.prototype = {
       statement.finalize();
     }
     otherContactsTag._initHiddenTags();
   },
   unInitContacts: function() {
     Tags = [];
     TagsById = { };
     // Avoid shutdown leaks caused by references to native components
-    // implementing prplIAccountBuddy.
+    // implementing imIAccountBuddy.
     for each (let buddy in BuddiesById)
       buddy.destroy();
     BuddiesById = { };
     ContactsById = { };
   },
 
   getContactById: function(aId) ContactsById[aId],
   // Get an array of all existing contacts.
@@ -1369,17 +1370,17 @@ ContactsService.prototype = {
         statement.execute();
         buddy =
           new Buddy(DBConn.lastInsertRowID, normalizedName, name, srvAlias, 0);
       } finally {
         statement.finalize();
       }
     }
 
-    // Initialize the 'buddy' field of the prplIAccountBuddy instance.
+    // Initialize the 'buddy' field of the imIAccountBuddy instance.
     aAccountBuddy.buddy = buddy;
 
     // Ensure we aren't storing a duplicate entry.
     let accountId = account.numericId;
     let tagId = aAccountBuddy.tag.id;
     if (buddy._hasAccountBuddy(accountId, tagId)) {
       Cu.reportError("Attempting to store a duplicate account buddy " +
                      normalizedName + ", account id = " + accountId +
--- a/chat/components/src/imConversations.js
+++ b/chat/components/src/imConversations.js
@@ -29,20 +29,17 @@ function imMessage(aPrplMessage) {
 }
 imMessage.prototype = {
   __proto__: ClassInfo(["imIMessage", "prplIMessage"], "IM Message"),
   cancelled: false,
   color: "",
   _displayMessage: null,
 
   get displayMessage() {
-    // Explicitly test for null so that blank messages don't fall back to
-    // the original. Especially problematic in encryption extensions like OTR.
-    return this._displayMessage !== null ?
-      this._displayMessage : this.prplMessage.originalMessage;
+    return this._displayMessage || this.prplMessage.originalMessage;
   },
   set displayMessage(aMsg) { this._displayMessage = aMsg; },
 
   get message() this.prplMessage.message,
   set message(aMsg) { this.prplMessage.message = aMsg; },
 
   // from prplIMessage
   get who() this.prplMessage.who,
@@ -201,18 +198,17 @@ UIConversation.prototype = {
     return this._messages;
   },
   checkClose: function() {
     if (!this._currentTargetId)
       return true; // already closed.
 
     if (!Services.prefs.getBoolPref("messenger.conversations.alwaysClose") &&
         (this.isChat && !this.left ||
-         !this.isChat && (this.unreadIncomingMessageCount != 0 ||
-                          Services.prefs.getBoolPref("messenger.conversations.holdByDefault"))))
+         !this.isChat && this.unreadIncomingMessageCount != 0))
       return false;
 
     this.close();
     return true;
   },
 
   observe: function(aSubject, aTopic, aData) {
     if (aTopic == "contact-no-longer-dummy") {
--- a/chat/components/src/imCore.js
+++ b/chat/components/src/imCore.js
@@ -263,23 +263,18 @@ CoreService.prototype = {
     });
 
     let accounts = Services.accounts;
     accounts.initAccounts();
     Services.contacts.initContacts();
     Services.conversations.initConversations();
     Services.obs.notifyObservers(this, "prpl-init", null);
 
-    // Wait with automatic connections until the password service
-    // is available.
-    if (accounts.autoLoginStatus == Ci.imIAccountsService.AUTOLOGIN_ENABLED) {
-      Services.logins.initializationPromise.then(() => {
-        Services.accounts.processAutoLogin();
-      });
-    }
+    if (accounts.autoLoginStatus == Ci.imIAccountsService.AUTOLOGIN_ENABLED)
+      accounts.processAutoLogin();
   },
   observe: function(aObject, aTopic, aData) {
     if (aTopic == kQuitApplicationGranted)
       this.quit();
   },
   quit: function() {
     if (!this._initialized)
       throw Cr.NS_ERROR_NOT_INITIALIZED;
--- a/chat/components/src/smileProtocolHandler.js
+++ b/chat/components/src/smileProtocolHandler.js
@@ -22,19 +22,16 @@ smileProtocolHandler.prototype = {
   newURI: function SPH_newURI(aSpec, aOriginCharset, aBaseURI) {
     let uri = Cc["@mozilla.org/network/simple-uri;1"].createInstance(Ci.nsIURI);
     uri.spec = aSpec;
     uri.QueryInterface(Ci.nsIMutable);
     uri.mutable = false;
     return uri;
   },
   newChannel: function SPH_newChannel(aURI) {
-    return this.newChannel2(aURI, null);
-  },
-  newChannel2: function SPH_newChannel2(aURI, aLoadInfo) {
     let smile = aURI.spec.replace(kSmileRegexp, "");
     let channel = Services.io.newChannel(getSmileRealURI(smile), null, null);
     channel.originalURI = aURI;
     return channel;
   },
   allowPort: function  SPH_allowPort(aPort, aScheme) false,
 
   classDescription: "Smile Protocol Handler",
--- a/chat/content/convbrowser.xml
+++ b/chat/content/convbrowser.xml
@@ -76,17 +76,17 @@
 
       <property name="currentURI"
                 onget="return this.webNavigation.currentURI;"
                 readonly="true"/>
 
       <field name="_docShell">null</field>
 
       <property name="docShell"
-                onget="return this._docShell || (this._docShell = this.boxObject.docShell);"
+                onget="return this._docShell || (this._docShell = this.boxObject.QueryInterface(Components.interfaces.nsIContainerBoxObject).docShell);"
                 readonly="true"/>
 
       <field name="_webNavigation">null</field>
 
       <property name="webNavigation"
                 onget="return this._webNavigation || (this._webNavigation = this.docShell.QueryInterface(Components.interfaces.nsIWebNavigation));"
                 readonly="true"/>
 
@@ -142,40 +142,16 @@
       <property name="contentDocument"
                 onget="return this.webNavigation.document;"
                 readonly="true"/>
 
       <property name="markupDocumentViewer"
                 onget="return this.docShell.contentViewer;"
                 readonly="true"/>
 
-      <property name="fullZoom">
-        <getter><![CDATA[
-          return this.markupDocumentViewer.fullZoom;
-        ]]></getter>
-        <setter><![CDATA[
-          this.markupDocumentViewer.fullZoom = val;
-        ]]></setter>
-      </property>
-
-      <property name="textZoom">
-        <getter><![CDATA[
-          return this.markupDocumentViewer.textZoom;
-        ]]></getter>
-        <setter><![CDATA[
-          this.markupDocumentViewer.textZoom = val;
-        ]]></setter>
-      </property>
-
-      <property name="isSyntheticDocument">
-        <getter><![CDATA[
-          return this.contentDocument.mozSyntheticDocument;
-        ]]></getter>
-      </property>
-
       <method name="enableMagicCopy">
         <body>
           <![CDATA[
           this.contentWindow.controllers.insertControllerAt(0, this);
           this.autoCopyEnabled = Services.clipboard.supportsSelectionClipboard() &&
             Services.prefs.getBoolPref("clipboard.autocopy");
           if (this.autoCopyEnabled) {
             this.contentWindow.getSelection()
--- a/chat/locales/en-US/irc.properties
+++ b/chat/locales/en-US/irc.properties
@@ -8,17 +8,16 @@
 #  configuring an IRC account.
 irc.usernameHint=nick
 
 # LOCALIZATION NOTE (connection.error.*):
 #   These will show in the account manager if the account is
 #   disconnected because of an error.
 connection.error.lost=Lost connection with server
 connection.error.timeOut=Connection timed out
-connection.error.invalidUsername=%S is not an allowed username
 connection.error.invalidPassword=Invalid server password
 connection.error.passwordRequired=Password required
 
 # LOCALIZATION NOTE (joinChat.*):
 #   These show up on the join chat menu. An underscore is for the access key.
 joinChat.channel=_Channel
 joinChat.password=_Password
 
@@ -96,17 +95,17 @@ message.usermode=Mode %1$S for %2$S set 
 message.channelmode=Channel mode %1$S set by %2$S.
 #    %S is the user's mode.
 message.yourmode=Your mode is %S.
 #    %1$S is the old nick and %2$S is the new nick.
 message.nick=%1$S is now known as %2$S.
 #    %S is your new nick.
 message.nick.you=You are now known as %S.
 #    Could not change the nickname. %S is the user's nick.
-message.nick.fail=Could not use the desired nickname. Your nick remains %S.
+message.nick.fail=Could not use the specified nickname. Your nick remains %S.
 #    The parameter is the message.parted.reason, if a part message is given.
 message.parted.you=You have left the room (Part%1$S).
 #    %1$S is the user's nick, %2$S is message.parted.reason, if a part message is given.
 message.parted=%1$S has left the room (Part%2$S).
 #    %S is the part message supplied by the user.
 message.parted.reason=: %S
 #    %1$S is the user's nick, %2$S is message.quit2 if a quit message is given.
 message.quit=%1$S has left the room (Quit%2$S).
--- a/chat/modules/imContentSink.jsm
+++ b/chat/modules/imContentSink.jsm
@@ -97,17 +97,17 @@ const kStandardMode = {
     'cite': true,
     'blockquote': true,
     'p': true
   },
 
   styles: {
     'font-style': true,
     'font-weight': true,
-    'text-decoration-line': true
+    '-moz-text-decoration-line': true
   }
 };
 
 // permissive mode allows about anything that isn't going to mess up the chat window
 const kPermissiveMode = {
   attrs: {
     'style': true
   },
@@ -145,19 +145,19 @@ const kPermissiveMode = {
   // FIXME: should be possible to use functions to filter values
   styles : {
     'color': true,
     'font': true,
     'font-family': true,
     'font-size': true,
     'font-style': true,
     'font-weight': true,
-    'text-decoration-color': true,
-    'text-decoration-style': true,
-    'text-decoration-line': true
+    '-moz-text-decoration-color': true,
+    '-moz-text-decoration-style': true,
+    '-moz-text-decoration-line': true
   }
 };
 
 const kModePref = "messenger.options.filterMode";
 const kModes = [kStrictMode, kStandardMode, kPermissiveMode];
 
 var gGlobalRuleset = null;
 
--- a/chat/modules/imThemes.jsm
+++ b/chat/modules/imThemes.jsm
@@ -376,18 +376,16 @@ const statusMessageReplacements = {
     if (aMsg.containsNick)
       msgClass.push("nick");
     if (aMsg.error)
       msgClass.push("error");
     if (aMsg.delayed)
       msgClass.push("delayed");
     if (aMsg.notification)
       msgClass.push("notification");
-    if (aMsg.noFormat)
-      msgClass.push("monospaced");
 
     return msgClass.join(" ");
   }
 };
 
 function formatSender(aName)
   "<span class=\"ib-sender\">" + TXTToHTML(aName) + "</span>";
 const messageReplacements = {
--- a/chat/modules/jsProtoHelper.jsm
+++ b/chat/modules/jsProtoHelper.jsm
@@ -237,17 +237,17 @@ const GenericAccountPrototype = {
   get singleFormatting() false,
   get noFontSizes() false,
   get noUrlDesc() false,
   get noImages() true
 };
 
 
 const GenericAccountBuddyPrototype = {
-  __proto__: ClassInfo("prplIAccountBuddy", "generic account buddy object"),
+  __proto__: ClassInfo("imIAccountBuddy", "generic account buddy object"),
   get DEBUG() this._account.DEBUG,
   get LOG() this._account.LOG,
   get WARN() this._account.WARN,
   get ERROR() this._account.ERROR,
 
   _init: function(aAccount, aBuddy, aTag, aUserName) {
     if (!aBuddy && !aUserName)
       throw "aUserName is required when aBuddy is null";
--- a/chat/modules/test/test_filtering.js
+++ b/chat/modules/test/test_filtering.js
@@ -143,18 +143,18 @@ function test_standardMode() {
   const okCSS = [
     "font-style: italic",
     "font-weight: bold"
   ];
   for each (let css in okCSS) {
     let string = "<span style=\"" + css + "\">foo</span>";
     do_check_eq(string, cleanupImMarkup(string));
   }
-  // text-decoration is a shorthand for several text-decoration properties.
-  do_check_eq("<span style=\"text-decoration-line: underline;\">foo</span>",
+  // text-decoration is a shorthand for several -moz-text-decoration properties.
+  do_check_eq("<span style=\"-moz-text-decoration-line: underline;\">foo</span>",
               cleanupImMarkup("<span style=\"text-decoration: underline\">foo</span>"));
 
   const badCSS = [
     "color: pink;",
     "font-family: Times",
     "font-size: larger",
     "-moz-binding: url('chrome://global/content/bindings/textbox.xml#textbox');",
     "display: none",
deleted file mode 100644
--- a/chat/nss-purple.def
+++ /dev/null
@@ -1,5 +0,0 @@
-PK11_PubEncryptRaw
-PK11_PubDecryptRaw
-PK11_Verify
-PK11_RestoreContext
-PK11_SaveContextAlloc
--- a/chat/protocols/irc/irc.js
+++ b/chat/protocols/irc/irc.js
@@ -20,36 +20,30 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 
 /*
  * Parses a raw IRC message into an object (see section 2.3 of RFC 2812). This
  * returns an object with the following fields:
  *   rawMessage The initial message string received without any processing.
  *   command    A string that is the command or response code.
  *   params     An array of strings for the parameters. The last parameter is
  *              stripped of its : prefix.
- *   origin     The user's nickname or the server who sent the message. Can be
- *              a host (e.g. irc.mozilla.org) or an IPv4 address (e.g. 1.2.3.4)
- *              or an IPv6 address (e.g. 3ffe:1900:4545:3:200:f8ff:fe21:67cf).
+ * If the message is from a user:
+ *   nickname   The user's nickname.
  *   user       The user's username, note that this can be undefined.
  *   host       The user's hostname, note that this can be undefined.
  *   source     A "nicely" formatted combination of user & host, which is
  *              <user>@<host> or <user> if host is undefined.
- *
- * There are cases (e.g. localhost) where it cannot be easily determined if a
- * message is from a server or from a user, thus the usage of a generic "origin"
- * instead of "nickname" or "servername".
- *
- * Inputs:
- *  aData       The raw string to parse, it should already have the \r\n
- *              stripped from the end.
- *  aOrigin     The default origin to use for unprefixed messages.
+ * Otherwise if it's from a server:
+ *   servername This is the address of the server as a host (e.g.
+ *              irc.mozilla.org) or an IPv4 address (e.g. 1.2.3.4) or IPv6
+ *              address (e.g. 3ffe:1900:4545:3:200:f8ff:fe21:67cf).
  */
-function ircMessage(aData, aOrigin) {
+function ircMessage(aData) {
   let message = {rawMessage: aData};
-  let temp;
+  let temp, prefix;
 
   // Splits the raw string into four parts (the second is required), the command
   // is required. A raw string looks like:
   //   [":" <prefix> " "] <command> [" " <parameter>]* [":" <last parameter>]
   //     <prefix>: :(<server name> | <nickname> [["!" <user>] "@" <host>])
   //     <command>: /[^ ]+/
   //     <parameter>: /[^ ]+/
   //     <last parameter>: /.+/
@@ -58,42 +52,42 @@ function ircMessage(aData, aOrigin) {
   // 2812 would allow. It allows for empty parameters (besides the last
   // parameter, which can always be empty), by allowing multiple spaces.
   // (This is for compatibility with Unreal's 432 response, which returns an
   // empty first parameter.) It also allows a trailing space after the
   // <parameter>s when no <last parameter> is present (also occurs with Unreal).
   if (!(temp = aData.match(/^(?::([^ ]+) )?([^ ]+)((?: +[^: ][^ ]*)*)? *(?::([\s\S]*))?$/)))
     throw "Couldn't parse message: \"" + aData + "\"";
 
+  // Assume message is from the server if not specified
+  prefix = temp[1];
   message.command = temp[2];
   // Space separated parameters. Since we expect a space as the first thing
   // here, we want to ignore the first value (which is empty).
   message.params = temp[3] ? temp[3].split(" ").slice(1) : [];
   // Last parameter can contain spaces or be an empty string.
   if (temp[4] != undefined)
     message.params.push(temp[4]);
 
-  // Handle the prefix part of the message per RFC 2812 Section 2.3.
-
-  // If no prefix is given, assume the current server is the origin.
-  if (!temp[1])
-    temp[1] = aOrigin;
-
-  // Split the prefix into separate nickname, username and hostname fields as:
-  //   :(servername|(nickname[[!user]@host]))
-  [message.origin, message.user, message.host] = temp[1].split(/[!@]/);
-
-  // It is occasionally useful to have a "source" which is a combination of
-  // user@host.
-  if (message.user)
-    message.source = message.user + "@" + message.host;
-  else if (message.host)
-    message.source = message.host;
-  else
-    message.source = "";
+  // The source string can be split into multiple parts as:
+  //   :(server|nickname[[!user]@host])
+  // If the source contains a . or a :, assume it's a server name. See RFC
+  // 2812 Section 2.3 definition of servername vs. nickname.
+  if (prefix &&
+      (temp = prefix.match(/^([^ !@\.:]+)(?:!([^ @]+))?(?:@([^ ]+))?$/))) {
+    message.nickname = temp[1];
+    message.user = temp[2] || null; // Optional
+    message.host = temp[3] || null; // Optional
+    if (message.user)
+      message.source = message.user + "@" + message.host;
+    else
+      message.source = message.host; // Note: this can be null!
+  }
+  else if (prefix)
+    message.servername = prefix;
 
   return message;
 }
 
 // This handles a mode change string for both channels and participants. A mode
 // change string is of the form:
 //   aAddNewMode is true if modes are being added, false otherwise.
 //   aNewModes is an array of mode characters.
@@ -105,16 +99,25 @@ function _setMode(aAddNewMode, aNewModes
     if (hasMode && !aAddNewMode)
       this._modes.delete(newMode);
     // If the mode is not in the list of modes and we want to add it.
     else if (!hasMode && aAddNewMode)
       this._modes.add(newMode);
   }
 }
 
+// This copies all the properties of aBase to aPrototype (which is expected to
+// be the prototype of an object). This is necessary because JavaScript does not
+// support multiple inheritance and both conversation objects have a lot of
+// shared code (but inherit from objects exposing different XPCOM interfaces).
+function copySharedBaseToPrototype(aBase, aPrototype) {
+  for (let property in aBase)
+    aPrototype[property] = aBase[property];
+}
+
 // Properties / methods shared by both ircChannel and ircConversation.
 const GenericIRCConversation = {
   _observedNicks: [],
   // This is set to true after a message is sent to notify the 401
   // ERR_NOSUCHNICK handler to write an error message to the conversation.
   _pendingMessage: false,
   _waitingForNick: false,
 
@@ -262,26 +265,27 @@ const GenericIRCConversation = {
 };
 
 function ircChannel(aAccount, aName, aNick) {
   this._init(aAccount, aName, aNick);
   this._participants = new NormalizedMap(this.normalizeNick.bind(this));
   this._modes = new Set();
   this._observedNicks = [];
   this.banMasks = [];
+  this._firstJoin = true;
 }
 ircChannel.prototype = {
   __proto__: GenericConvChatPrototype,
   _modes: null,
   _receivedInitialMode: false,
   // For IRC you're not in a channel until the JOIN command is received, open
   // all channels (initially) as left.
   _left: true,
-  // True while we are rejoining a channel previously parted by the user.
-  _rejoined: false,
+  // True until successfully joined for the first time.
+  _firstJoin: false,
   banMasks: [],
 
   // Overwrite the writeMessage function to apply CTCP formatting before
   // display.
   writeMessage: function(aWho, aText, aProperties) {
     GenericConvChatPrototype.writeMessage.call(this, aWho,
                                                ctcpFormatToHTML(aText),
                                                aProperties);
@@ -542,17 +546,17 @@ ircChannel.prototype = {
     if (!participant)
       return false;
 
     // If the channel mode is +t, hops and ops can set the topic; otherwise
     // everyone can.
     return !this._modes.has("t") || participant.op || participant.halfOp;
   }
 };
-Object.assign(ircChannel.prototype, GenericIRCConversation);
+copySharedBaseToPrototype(GenericIRCConversation, ircChannel.prototype);
 
 function ircParticipant(aName, aConv) {
   this._name = aName;
   this._conv = aConv;
   this._account = aConv._account;
   this._modes = new Set();
 
   // Handle multi-prefix modes.
@@ -615,17 +619,17 @@ ircConversation.prototype = {
     GenericConvIMPrototype.unInit.call(this);
   },
 
   updateNick: function(aNewNick) {
     this._name = aNewNick;
     this.notifyObservers(null, "update-conv-title");
   }
 };
-Object.assign(ircConversation.prototype, GenericIRCConversation);
+copySharedBaseToPrototype(GenericIRCConversation, ircConversation.prototype);
 
 function ircSocket(aAccount) {
   this._account = aAccount;
   this._initCharsetConverter();
 }
 ircSocket.prototype = {
   __proto__: Socket,
   // Although RFCs 1459 and 2812 explicitly say that \r\n is the message
@@ -676,18 +680,17 @@ ircSocket.prototype = {
     // Low level dequote: replace quote character \020 followed by 0, n, r or
     // \020 with a \0, \n, \r or \020, respectively. Any other character is
     // replaced with itself.
     const lowDequote = {"0": "\0", "n": "\n", "r": "\r", "\x10": "\x10"};
     let dequotedMessage = aRawMessage.replace(/\x10./g,
       function(aStr) lowDequote[aStr[1]] || aStr[1]);
 
     try {
-      let message = new ircMessage(dequotedMessage,
-                                   this._account._currentServerName);
+      let message = new ircMessage(dequotedMessage);
       this.DEBUG(JSON.stringify(message) + conversionWarning);
       if (!ircHandlers.handleMessage(this._account, message)) {
         // If the message was not handled, throw a warning containing
         // the original quoted message.
         this.WARN("Unhandled IRC message:\n" + aRawMessage);
       }
     } catch (e) {
       // Catch the error, display it and hope the connection can continue with
@@ -777,29 +780,25 @@ function ircAccount(aProtocol, aImAccoun
   this._init(aProtocol, aImAccount);
   this.buddies = new NormalizedMap(this.normalizeNick.bind(this));
   this.conversations = new NormalizedMap(this.normalize.bind(this));
 
   // Split the account name into usable parts.
   let splitter = this.name.lastIndexOf("@");
   this._accountNickname = this.name.slice(0, splitter);
   this._server = this.name.slice(splitter + 1);
-  // To avoid _currentServerName being null, initialize it to the server being
-  // connected to. This will also get overridden during the 001 response from
-  // the server.
-  this._currentServerName = this._server;
 
   this._nickname = this._accountNickname;
   this._requestedNickname = this._nickname;
 
   // For more information, see where these are defined in the prototype below.
   this.trackQueue = [];
   this.pendingIsOnQueue = [];
   this.whoisInformation = new NormalizedMap(this.normalizeNick.bind(this));
-  this._caps = new Set();
+  this._caps = [];
 
   this._roomInfoCallbacks = new Set();
 }
 ircAccount.prototype = {
   __proto__: GenericAccountPrototype,
   _socket: null,
   _MODE_WALLOPS: 1 << 2, // mode 'w'
   _MODE_INVISIBLE: 1 << 3, // mode 'i'
@@ -816,30 +815,16 @@ ircAccount.prototype = {
   // The nickname stored in the account name.
   _accountNickname: null,
   // The nickname that was last requested by the user.
   _requestedNickname: null,
   // The nickname that was last requested. This can differ from
   // _requestedNickname when a new nick is automatically generated (e.g. by
   // adding digits).
   _sentNickname: null,
-  // If we don't get the desired nick on connect, we try again a bit later,
-  // to see if it wasn't just our nick not having timed out yet.
-  _nickInUseTimeout: null,
-  get username() {
-    let username;
-    // Use a custom username in a hidden preference.
-    if (this.prefs.prefHasUserValue("username"))
-      username = this.getString("username");
-    // But fallback to brandShortName if no username is provided (or is empty).
-    if (!username)
-      username = Services.appinfo.name;
-
-    return username;
-  },
   // The prefix minus the nick (!user@host) as returned by the server, this is
   // necessary for guessing message lengths.
   prefix: null,
 
   // Parts of the specification give max lengths, keep track of them since a
   // server can overwrite them. The defaults given here are from RFC 2812.
   maxNicknameLength: 9, // 1.2.1 Users
   maxChannelLength: 50, // 1.3 Channels
@@ -1287,29 +1272,29 @@ ircAccount.prototype = {
   },
 
   handlePingReply: function(aSource, aPongTime) {
     // Received PING response, display to the user.
     let sentTime = new Date(parseInt(aPongTime, 10));
 
     // The received timestamp is invalid.
     if (isNaN(sentTime)) {
-      this.WARN(aMessage.origin +
+      this.WARN(aMessage.servername +
                 " returned an invalid timestamp from a PING: " + aPongTime);
       return false;
     }
 
     // Find the delay in milliseconds.
     let delay = Date.now() - sentTime;
 
     // If the delay is negative or greater than 1 minute, something is
     // feeding us a crazy value. Don't display this to the user.
     if (delay < 0 || 60 * 1000 < delay) {
-      this.WARN(aMessage.origin + " returned an invalid delay from a PING: " +
-                delay);
+      this.WARN(aMessage.servername +
+                " returned an invalid delay from a PING: " + delay);
       return false;
     }
 
     let msg = PluralForm.get(delay, _("message.ping", aSource))
                         .replace("#2", delay);
     this.getConversation(aSource).writeMessage(aSource, msg, {system: true});
     return true;
   },
@@ -1421,41 +1406,27 @@ ircAccount.prototype = {
     this._socket = new ircSocket(this);
     this._socket.connect(this._server, this._port, this._ssl ? ["ssl"] : []);
   },
 
   // Functions for keeping track of whether the Client Capabilities is done.
   // If a cap is to be handled, it should be registered with addCAP, where aCAP
   // is a "unique" string defining what is being handled. When the cap is done
   // being handled removeCAP should be called with the same string.
-  _caps: new Set(),
+  _caps: [],
   _capTimeout: null,
   addCAP: function(aCAP) {
-    if (this.connected) {
-      this.ERROR("Trying to add CAP " + aCAP + " after connection.");
-      return;
-    }
-
-    this._caps.add(aCAP);
+    this._caps.push(aCAP);
   },
   removeCAP: function(aDoneCAP) {
-    if (!this._caps.has(aDoneCAP)) {
-      this.ERROR("Trying to remove a CAP (" + aDoneCAP + ") which isn't added.");
-      return;
-    }
-    if (this.connected) {
-      this.ERROR("Trying to remove CAP " + aDoneCAP + " after connection.");
-      return;
-    }
-
     // Remove any reference to the given capability.
-    this._caps.delete(aDoneCAP);
+    this._caps = this._caps.filter(function(aCAP) aCAP != aDoneCAP);
 
     // If no more CAP messages are being handled, notify the server.
-    if (!this._caps.size)
+    if (!this._caps.length)
       this.sendMessage("CAP", "END");
   },
 
   // Used to wait for a response from the server.
   _quitTimer: null,
   // RFC 2812 Section 3.1.7.
   quit: function(aMessage) {
     this._reportDisconnecting(Ci.prplIAccount.NO_ERROR);
@@ -1499,26 +1470,21 @@ ircAccount.prototype = {
     }
 
     // A channel prefix is required. If the user didn't include one,
     // we prepend # automatically to match the behavior of other
     // clients. Not doing it used to cause user confusion.
     if (this.channelPrefixes.indexOf(channel[0]) == -1)
       channel = "#" + channel;
 
+    // No need to join a channel we are already in.
     if (this.conversations.has(channel)) {
       let conv = this.getConversation(channel);
-      if (!conv.left) {
-        // No need to join a channel we are already in.
+      if (!conv.left)
         return conv;
-      }
-      else if (!conv.chatRoomFields) {
-        // We are rejoining a channel that was parted by the user.
-        conv._rejoined = true;
-      }
     }
 
     let params = [channel];
     let key = aComponents.getValue("password");
     if (key)
       params.push(key);
 
     // Send the join command, but don't log the channel key.
@@ -1687,17 +1653,24 @@ ircAccount.prototype = {
       this.sendMessage("PASS", this.getString("serverPassword"),
                        "PASS <password not logged>");
     }
 
     // Send the nick message (section 3.1.2).
     this.changeNick(this._requestedNickname);
 
     // Send the user message (section 3.1.3).
-    this.sendMessage("USER", [this.username, this._mode.toString(), "*",
+    let username;
+    // Use a custom username in a hidden preference.
+    if (this.prefs.prefHasUserValue("username"))
+      username = this.getString("username");
+    // But fallback to brandShortName if no username is provided (or is empty).
+    if (!username)
+      username = Services.appinfo.name;
+    this.sendMessage("USER", [username, this._mode.toString(), "*",
                               this._realname || this._requestedNickname]);
   },
 
   _reportDisconnecting: function(aErrorReason, aErrorMessage) {
     this.reportDisconnecting(aErrorReason, aErrorMessage);
 
     // Mark all contacts on the account as having an unknown status.
     this.buddies.forEach(function(aBuddy)
@@ -1712,33 +1685,27 @@ ircAccount.prototype = {
     // If we are already disconnecting, this call to gotDisconnected
     // is when the server acknowledges our disconnection.
     // Otherwise it's because we lost the connection.
     if (!this.disconnecting)
       this._reportDisconnecting(aError, aErrorMessage);
     this._socket.disconnect();
     delete this._socket;
 
-    this._caps.clear();
-
     clearTimeout(this._isOnTimer);
     delete this._isOnTimer;
 
     // MOTD will be resent.
     delete this._motd;
     clearTimeout(this._motdTimer)
     delete this._motdTimer;
 
     // We must authenticate if we reconnect.
     delete this.isAuthenticated;
 
-    // Clear any pending attempt to regain our nick.
-    clearTimeout(this._nickInUseTimeout);
-    delete this._nickInUseTimeout;
-
     // Clean up each conversation: mark as left and remove participant.
     this.conversations.forEach(conversation => {
       if (conversation.isChat) {
         conversation.joining = false; // In case we never finished joining.
         if (!conversation.left) {
           // Remove the user's nick and mark the conversation as left as that's
           // the final known state of the room.
           conversation.removeParticipant(this._nickname);
--- a/chat/protocols/irc/ircBase.jsm
+++ b/chat/protocols/irc/ircBase.jsm
@@ -40,18 +40,19 @@ ircRoomInfo.prototype = {
     this._account.getChatRoomDefaultFieldValues(this.name)
 }
 
 function privmsg(aAccount, aMessage, aIsNotification) {
   let params = {incoming: true};
   if (aIsNotification)
     params.notification = true;
   aAccount.getConversation(aAccount.isMUCName(aMessage.params[0]) ?
-                             aMessage.params[0] : aMessage.origin)
-          .writeMessage(aMessage.origin, aMessage.params[1], params);
+                           aMessage.params[0] : aMessage.nickname)
+          .writeMessage(aMessage.nickname || aMessage.servername,
+                        aMessage.params[1], params);
   return true;
 }
 
 // Display the message and remove them from the rooms they're in.
 function leftRoom(aAccount, aNicks, aChannels, aSource, aReason, aKicked) {
   let msgId = "message." +  (aKicked ? "kicked" : "parted");
   // If a part message was included, include it.
   let reason = aReason ? _(msgId + ".reason", aReason) : "";
@@ -87,18 +88,18 @@ function leftRoom(aAccount, aNicks, aCha
     }
   }
   return true;
 }
 
 function writeMessage(aAccount, aMessage, aString, aType) {
   let type = {};
   type[aType] = true;
-  aAccount.getConversation(aMessage.origin)
-          .writeMessage(aMessage.origin, aString, type);
+  aAccount.getConversation(aMessage.servername)
+          .writeMessage(aMessage.servername, aString, type);
   return true;
 }
 
 // If aNoLastParam is true, the last parameter is not printed out.
 function serverMessage(aAccount, aMsg, aNoLastParam) {
   // If we don't want to show messages from the server, just mark it as handled.
   if (!aAccount._showServerTab)
     return true;
@@ -180,108 +181,111 @@ var ircBase = {
       if (Services.prefs.getIntPref("messenger.conversations.autoAcceptChatInvitations") == 1) {
         // Auto-accept the invite.
         this.joinChat(this.getChatRoomDefaultFieldValues(aMessage.params[1]));
         this.LOG("Received invite for " + aMessage.params[1] +
                  ", auto-accepting.");
       }
       // Otherwise, just notify the user.
       this.getConversation(aMessage.params[1])
-          .writeMessage(aMessage.origin,
-                        _("message.inviteReceived", aMessage.origin,
+          .writeMessage(aMessage.nickname,
+                        _("message.inviteReceived", aMessage.nickname,
                           aMessage.params[1]), {system: true});
       return true;
     },
     "JOIN": function(aMessage) {
       // JOIN ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] ) / "0"
       // Add the buddy to each channel
       for each (let channelName in aMessage.params[0].split(",")) {
         let conversation = this.getConversation(channelName);
-        if (this.normalize(aMessage.origin, this.userPrefixes) ==
+        if (this.normalize(aMessage.nickname, this.userPrefixes) ==
             this.normalize(this._nickname)) {
           // If you join, clear the participants list to avoid errors with
           // repeated participants.
           conversation.removeAllParticipants();
           conversation.left = false;
           conversation.joining = false;
 
           // If the user parted from this room earlier, confirm the rejoin.
-          if (conversation._rejoined) {
-            conversation.writeMessage(aMessage.origin, _("message.rejoined"),
+          // If conversation.chatRoomFields is present, the rejoin was due to
+          // an automatic reconnection, for which we already notify the user.
+          if (!conversation._firstJoin && !conversation.chatRoomFields) {
+            conversation.writeMessage(aMessage.nickname, _("message.rejoined"),
                                       {system: true});
-            delete conversation._rejoined;
           }
+          delete conversation._firstJoin;
 
           // Ensure chatRoomFields information is available for reconnection.
           if (!conversation.chatRoomFields) {
             this.WARN("Opening a MUC without storing its " +
                       "prplIChatRoomFieldValues first.");
             conversation.chatRoomFields =
               this.getChatRoomDefaultFieldValues(channelName);
           }
         }
         else {
           // Don't worry about adding ourself, RPL_NAMREPLY takes care of that
           // case.
-          conversation.getParticipant(aMessage.origin, true);
-          let msg = _("message.join", aMessage.origin, aMessage.source);
-          conversation.writeMessage(aMessage.origin, msg, {system: true,
-                                                           noLinkification: true});
+          conversation.getParticipant(aMessage.nickname, true);
+          let msg = _("message.join", aMessage.nickname, aMessage.source || "");
+          conversation.writeMessage(aMessage.nickname, msg, {system: true,
+                                                             noLinkification: true});
         }
       }
       // If the joiner is a buddy, mark as online.
-      let buddy = this.buddies.get(aMessage.origin);
+      let buddy = this.buddies.get(aMessage.nickname);
       if (buddy)
         buddy.setStatus(Ci.imIStatusInfo.STATUS_AVAILABLE, "");
       return true;
     },
     "KICK": function(aMessage) {
       // KICK <channel> *( "," <channel> ) <user> *( "," <user> ) [<comment>]
       let comment = aMessage.params.length == 3 ? aMessage.params[2] : null;
       // Some servers (moznet) send the kicker as the comment.
-      if (comment == aMessage.origin)
+      if (comment == aMessage.nickname)
         comment = null;
       return leftRoom(this, aMessage.params[1].split(","),
-                      aMessage.params[0].split(","), aMessage.origin, comment,
-                      true);
+                      aMessage.params[0].split(","), aMessage.nickname,
+                      comment, true);
     },
     "MODE": function(aMessage) {
       // MODE <nickname> *( ( "+" / "-") *( "i" / "w" / "o" / "O" / "r" ) )
       // MODE <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
       if (this.isMUCName(aMessage.params[0])) {
         // If the first parameter is a channel name, a channel/participant mode
         // was updated.
         this.getConversation(aMessage.params[0])
             .setMode(aMessage.params[1], aMessage.params.slice(2),
-                     aMessage.origin);
+                     aMessage.nickname || aMessage.servername);
 
         return true;
       }
 
       // Otherwise the user's own mode is being returned to them.
       return this.setUserMode(aMessage.params[0], aMessage.params[1],
-                              aMessage.origin, !this._userModeReceived);
+                              aMessage.nickname || aMessage.servername,
+                              !this._userModeReceived);
     },
     "NICK": function(aMessage) {
       // NICK <nickname>
-      this.changeBuddyNick(aMessage.origin, aMessage.params[0]);
+      this.changeBuddyNick(aMessage.nickname, aMessage.params[0]);
       return true;
     },
     "NOTICE": function(aMessage) {
       // NOTICE <msgtarget> <text>
-      // If the message is from the server, don't show it unless the user wants
-      // to see it.
-      if (!this.connected || aMessage.origin == this._currentServerName)
+      // If the message doesn't have a nickname, it's from the server, don't
+      // show it unless the user wants to see it.
+      if (!aMessage.hasOwnProperty("nickname"))
         return serverMessage(this, aMessage);
       return privmsg(this, aMessage, true);
     },
     "PART": function(aMessage) {
       // PART <channel> *( "," <channel> ) [ <Part Message> ]
-      return leftRoom(this, [aMessage.origin], aMessage.params[0].split(","),
-                      aMessage.source,
+      return leftRoom(this, [aMessage.nickname], aMessage.params[0].split(","),
+                      aMessage.source || "",
                       aMessage.params.length == 2 ? aMessage.params[1] : null);
     },
     "PING": function(aMessage) {
       // PING <server1> [ <server2> ]
       // Keep the connection alive.
       this.sendMessage("PONG", aMessage.params[0]);
       return true;
     },
@@ -291,78 +295,69 @@ var ircBase = {
 
       // Ping to keep the connection alive.
       if (pongTime.startsWith("_")) {
         this._socket.cancelDisconnectTimer();
         return true;
       }
       // Otherwise, the ping was from a user command.
       else
-        return this.handlePingReply(aMessage.origin, pongTime);
+        return this.handlePingReply(aMessage.servername, pongTime);
     },
     "PRIVMSG": function(aMessage) {
       // PRIVMSG <msgtarget> <text to be sent>
       // Display message in conversation
       return privmsg(this, aMessage);
     },
     "QUIT": function(aMessage) {
       // QUIT [ < Quit Message> ]
       // Some IRC servers automatically prefix a "Quit: " string. Remove the
       // duplication and use a localized version.
       let quitMsg = aMessage.params[0] || "";
       if (quitMsg.startsWith("Quit: "))
         quitMsg = quitMsg.slice(6); // "Quit: ".length
       // If a quit message was included, show it.
-      let nick = aMessage.origin;
-      let msg = _("message.quit", nick,
+      let msg = _("message.quit", aMessage.nickname,
                   quitMsg.length ? _("message.quit2", quitMsg) : "");
       // Loop over every conversation with the user and display that they quit.
       this.conversations.forEach(conversation => {
-        if (conversation.isChat && conversation._participants.has(nick)) {
-          conversation.writeMessage(nick, msg, {system: true});
-          conversation.removeParticipant(nick);
+        if (conversation.isChat &&
+            conversation._participants.has(aMessage.nickname)) {
+          conversation.writeMessage(aMessage.servername, msg, {system: true});
+          conversation.removeParticipant(aMessage.nickname);
         }
       });
 
       // Remove from the whois table.
-      this.removeBuddyInfo(nick);
+      this.removeBuddyInfo(aMessage.nickname);
 
       // If the leaver is a buddy, mark as offline.
-      let buddy = this.buddies.get(nick);
+      let buddy = this.buddies.get(aMessage.nickname);
       if (buddy)
         buddy.setStatus(Ci.imIStatusInfo.STATUS_OFFLINE, "");
-
-      // If we wanted this nickname, grab it.
-      if (nick == this._requestedNickname && nick != this._nickname) {
-        this.changeNick(this._requestedNickname);
-        clearTimeout(this._nickInUseTimeout);
-        delete this._nickInUseTimeout;
-      }
       return true;
     },
     "SQUIT": function(aMessage) {
       // <server> <comment>
       return true;
     },
     "TOPIC": function(aMessage) {
       // TOPIC <channel> [ <topic> ]
       // Show topic as a message.
+      let source = aMessage.nickname || aMessage.servername;
       let conversation = this.getConversation(aMessage.params[0]);
       let topic = aMessage.params[1];
       // Set the topic in the conversation and update the UI.
-      conversation.setTopic(topic ? ctcpFormatToText(topic) : "",
-                            aMessage.origin);
+      conversation.setTopic(topic ? ctcpFormatToText(topic) : "", source);
       return true;
     },
     "001": function(aMessage) { // RPL_WELCOME
       // Welcome to the Internet Relay Network <nick>!<user>@<host>
       this._socket.resetPingTimer();
-      // This seems a little strange, but we don't differentiate between a
-      // nickname and the servername since it can be ambiguous.
-      this._currentServerName = aMessage.origin;
+      this._currentServerName = aMessage.servername;
 
       // Clear user mode.
       this._modes = new Set();
       this._userModeReceived = false;
 
       // Check if our nick has changed.
       if (aMessage.params[0] != this._nickname)
         this.changeBuddyNick(this._nickname, aMessage.params[0]);
@@ -372,20 +367,16 @@ var ircBase = {
 
       // If our status is Unavailable, tell the server.
       if (this.imAccount.statusInfo.statusType < Ci.imIStatusInfo.STATUS_AVAILABLE)
         this.observe(null, "status-changed");
 
       // Check if any of our buddies are online!
       this.sendIsOn();
 
-      // If we didn't handle all the CAPs we added, something is wrong.
-      if (this._caps.size)
-        this.ERROR("Connected without removing CAPs: " + [...this._caps]);
-
       // Done!
       this.reportConnected();
       return serverMessage(this, aMessage);
     },
     "002": function(aMessage) { // RPL_YOURHOST
       // Your host is <servername>, running version <ver>
       return serverMessage(this, aMessage);
     },
@@ -494,17 +485,17 @@ var ircBase = {
     "219": function(aMessage) { // RPL_ENDOFSTATS
       // <stats letter> :End of STATS report
       return serverMessage(this, aMessage);
     },
 
     "221": function(aMessage) { // RPL_UMODEIS
       // <user mode string>
       return this.setUserMode(aMessage.params[0], aMessage.params[1],
-                              aMessage.origin, true);
+                              aMessage.servername, true);
     },
 
     /*
      * Services
      */
     "231": function(aMessage) { // RPL_SERVICEINFO
       // Non-generic
       return serverMessage(this, aMessage);
@@ -823,17 +814,17 @@ var ircBase = {
 
     /*
      * Channel functions
      */
     "324": function(aMessage) { // RPL_CHANNELMODEIS
       // <channel> <mode> <mode params>
       this.getConversation(aMessage.params[1])
           .setMode(aMessage.params[2], aMessage.params.slice(3),
-                   aMessage.origin);
+                   aMessage.servername);
 
       return true;
     },
     "325": function(aMessage) { // RPL_UNIQOPIS
       // <channel> <nickname>
       // TODO parse this and have the UI respond accordingly.
       return false;
     },
@@ -860,17 +851,17 @@ var ircBase = {
     /*
      * Invitations
      */
     "341": function(aMessage) { // RPL_INVITING
       // <channel> <nick>
       // Note that servers reply with parameters in the reverse order from the
       // above (which is as specified by RFC 2812).
       this.getConversation(aMessage.params[2])
-          .writeMessage(aMessage.origin,
+          .writeMessage(aMessage.servername,
                         _("message.invited", aMessage.params[1],
                           aMessage.params[2]), {system: true});
       return true;
     },
     "342": function(aMessage) { // RPL_SUMMONING
       // <user> :Summoning user to IRC
       return writeMessage(this, aMessage,
                           _("message.summoned", aMessage.params[0]));
@@ -995,17 +986,17 @@ var ircBase = {
       let conv = this.getConversation(aMessage.params[1]);
       let msg;
       if (conv.banMasks.length) {
         msg = [_("message.banMasks", aMessage.params[1])]
                .concat(conv.banMasks).join("\n");
       }
       else
         msg = _("message.noBanMasks", aMessage.params[1]);
-      conv.writeMessage(aMessage.origin, msg, {system: true});
+      conv.writeMessage(aMessage.servername, msg, {system: true});
       return true;
     },
     "369": function(aMessage) { // RPL_ENDOFWHOWAS
       // <nick> :End of WHOWAS
       // We've received everything about WHOWAS, tell the tooltip that is waiting
       // for this information.
       this.notifyWhois(aMessage.params[1]);
       return true;
@@ -1032,19 +1023,19 @@ var ircBase = {
       return true;
     },
     "375": function(aMessage) { // RPL_MOTDSTART
       // :- <server> Message of the day -
       return addMotd(this, aMessage);
     },
     "376": function(aMessage) { // RPL_ENDOFMOTD
       // :End of MOTD command
-      // Show the MOTD if the user wants to see server messages or if
-      // RPL_WELCOME has not been received since some servers (e.g. irc.ppy.sh)
-      // use this as a CAPTCHA like mechanism before login can occur.
+      // Show the MOTD if the user wants to see server messages or if RPL_WELCOME has not been
+      // received since some servers (e.g. irc.ppy.sh) use this as a CAPTCHA
+      // like mechanism before login can occur.
       if (this._showServerTab || !this.connected)
         writeMessage(this, aMessage, this._motd.join("\n"), "incoming");
       // No reason to keep the MOTD in memory.
       delete this._motd;
       // Clear the MOTD timer.
       clearTimeout(this._motdTimer)
       delete this._motdTimer;
 
@@ -1231,25 +1222,16 @@ var ircBase = {
         // Reset original nickname to the account nickname in case of
         // later reconnections.
         this._requestedNickname = this._accountNickname;
       }
       return true;
     },
     "433": function(aMessage) { // ERR_NICKNAMEINUSE
       // <nick> :Nickname is already in use
-      // Try to get the desired nick back in 2.5 minutes if this happens when
-      // connecting, in case it was just due to the user's nick not having
-      // timed out yet on the server.
-      if (this.connecting && aMessage.params[1] == this._requestedNickname) {
-        this._nickInUseTimeout = setTimeout(() => {
-            this.changeNick(this._requestedNickname);
-            delete this._nickInUseTimeout;
-          }, 150000);
-      }
       return this.tryNewNick(aMessage.params[1]);
     },
     "436": function(aMessage) { // ERR_NICKCOLLISION
       // <nick> :Nickname collision KILL from <user>@<host>
       return this.tryNewNick(aMessage.params[1]);
     },
     "437": function(aMessage) { // ERR_UNAVAILRESOURCE
       // <nick/channel> :Nick/channel is temporarily unavailable
@@ -1265,17 +1247,17 @@ var ircBase = {
       // <channel> :You're not on that channel
       this.ERROR("A command affecting " + aMessage.params[1] +
                  " failed because you aren't in that channel.");
       return true;
     },
     "443": function(aMessage) { // ERR_USERONCHANNEL
       // <user> <channel> :is already on channel
       this.getConversation(aMessage.params[2])
-          .writeMessage(aMessage.origin,
+          .writeMessage(aMessage.servername,
                         _("message.alreadyInChannel", aMessage.params[1],
                           aMessage.params[2]), {system: true});
       return true;
     },
     "444": function(aMessage) { // ERR_NOLOGIN
       // <user> :User not logged in
       // TODO
       return false;
@@ -1297,25 +1279,17 @@ var ircBase = {
         this.LOG("Server doesn't support CAP.");
         return true;
       }
       // TODO
       return false;
     },
     "461": function(aMessage) { // ERR_NEEDMOREPARAMS
       // <command> :Not enough parameters
-
-      if (!this.connected) {
-        // The account has been set up with an illegal username.
-        this.ERROR("Erroneous username: " + this.username);
-        this.gotDisconnected(Ci.prplIAccount.ERROR_INVALID_USERNAME,
-                             _("connection.error.invalidUsername", this.user));
-        return true;
-      }
-
+      // TODO
       return false;
     },
     "462": function(aMessage) { // ERR_ALREADYREGISTERED
       // :Unauthorized command (already registered)
       // TODO
       return false;
     },
     "463": function(aMessage) { // ERR_NOPERMFORHOST
--- a/chat/protocols/irc/ircCAP.jsm
+++ b/chat/protocols/irc/ircCAP.jsm
@@ -72,17 +72,17 @@ var ircCAP = {
         // Display the list of unhandled CAP messages.
         let unhandledMessages =
           messages.map(function(aMsg) aMsg.cap.parameter).join(" ");
         this.LOG("Unhandled CAP messages: " + unhandledMessages +
                  "\nRaw message: " + aMessage.rawMessage);
       }
 
       // If no CAP handlers were added, just tell the server we're done.
-      if (aMessage.cap.subcommand == "LS" && !this._caps.size)
+      if (!this._caps.length)
         this.sendMessage("CAP", "END");
       return true;
     },
 
     "410": function(aMessage) { // ERR_INVALIDCAPCMD
       // <unrecognized subcommand> :Invalid CAP subcommand
       this.WARN("Invalid subcommand: " + aMessage.params[1]);
       return true;
--- a/chat/protocols/irc/ircCTCP.jsm
+++ b/chat/protocols/irc/ircCTCP.jsm
@@ -94,17 +94,18 @@ function ctcpHandleMessage(aMessage) {
 
   // Loop over each raw CTCP message.
   for each (let message in ctcpMessages) {
     if (!ircHandlers.handleCTCPMessage(this, message)) {
       this.WARN("Unhandled CTCP message: " + message.ctcp.rawMessage +
                 "\nin IRC message: " + message.rawMessage);
       // For unhandled CTCP message, respond with a NOTICE ERRMSG that echoes
       // back the original command.
-      this.sendCTCPMessage(message.origin, true, "ERRMSG",
+      this.sendCTCPMessage(message.nickname || message.servername, true,
+                           "ERRMSG",
                            [message.ctcp.rawMessage, ":Unhandled CTCP command"]);
     }
   }
 
   // We have handled this message as much as we can.
   return true;
 }
 
@@ -116,25 +117,26 @@ var ctcpBase = {
   isEnabled: function() true,
 
   // These represent CTCP commands.
   commands: {
     "ACTION": function(aMessage) {
       // ACTION <text>
       // Display message in conversation
       this.getConversation(this.isMUCName(aMessage.params[0]) ?
-                             aMessage.params[0] : aMessage.origin)
-          .writeMessage(aMessage.origin, "/me " + aMessage.ctcp.param,
+                             aMessage.params[0] : aMessage.nickname)
+          .writeMessage(aMessage.nickname || aMessage.servername,
+                        "/me " + aMessage.ctcp.param,
                         {incoming: true});
       return true;
     },
 
     // Used when an error needs to be replied with.
     "ERRMSG": function(aMessage) {
-      this.WARN(aMessage.origin + " failed to handle CTCP message: " +
+      this.WARN(aMessage.nickname + " failed to handle CTCP message: " +
                 aMessage.ctcp.param);
       return true;
     },
 
     // This is commented out since CLIENTINFO automatically returns the
     // supported CTCP parameters and this is not supported.
 
     // Returns the user's full name, and idle time.
@@ -149,41 +151,41 @@ var ctcpBase = {
         for (let handler of ircHandlers._ctcpHandlers) {
           for (let command in handler.commands)
             info.add(command);
         }
 
         let supportedCtcp = [...info].join(" ");
         this.LOG("Reporting support for the following CTCP messages: " +
                  supportedCtcp);
-        this.sendCTCPMessage(aMessage.origin, true, "CLIENTINFO",
+        this.sendCTCPMessage(aMessage.nickname, true, "CLIENTINFO",
                              supportedCtcp);
       }
       else {
         // Received a CLIENTINFO response, store the information for future
         // use.
         let info = aMessage.ctcp.param.split(" ");
-        this.setWhois(aMessage.origin, {clientInfo: info})
+        this.setWhois(aMessage.nickname, {clientInfo: info})
       }
       return true;
     },
 
     // Used to measure the delay of the IRC network between clients.
     "PING": function(aMessage) {
       // PING timestamp
       if (aMessage.command == "PRIVMSG") {
         // Received PING request, send PING response.
-        this.LOG("Received PING request from " + aMessage.origin +
+        this.LOG("Received PING request from " + aMessage.nickname +
                  ". Sending PING response: \"" + aMessage.ctcp.param + "\".");
-        this.sendCTCPMessage(aMessage.origin, true, "PING",
+        this.sendCTCPMessage(aMessage.nickname, true, "PING",
                              aMessage.ctcp.param);
         return true;
       }
       else
-        return this.handlePingReply(aMessage.origin, aMessage.ctcp.param);
+        return this.handlePingReply(aMessage.nickname, aMessage.ctcp.param);
     },
 
     // These are commented out since CLIENTINFO automatically returns the
     // supported CTCP parameters and this is not supported.
 
     // An encryption protocol between clients without any known reference.
     //"SED": function(aMessage) false,
 
@@ -191,28 +193,28 @@ var ctcpBase = {
     //"SOURCE": function(aMessage) false,
 
     // Gets the local date and time from other clients.
     "TIME": function(aMessage) {
       if (aMessage.command == "PRIVMSG") {
         // TIME
         // Received a TIME request, send a human readable response.
         let now = (new Date()).toString();
-        this.LOG("Received TIME request from " + aMessage.origin +
+        this.LOG("Received TIME request from " + aMessage.nickname +
                  ". Sending TIME response: \"" + now + "\".");
-        this.sendCTCPMessage(aMessage.origin, true, "TIME", ":" + now);
+        this.sendCTCPMessage(aMessage.nickname, true, "TIME", ":" + now);
       }
       else {
         // TIME :<human-readable-time-string>
         // Received a TIME reply, display it.
         // Remove the : prefix, if it exists and display the result.
         let time = aMessage.ctcp.param.slice(aMessage.ctcp.param[0] == ":");
-        this.getConversation(aMessage.origin)
-            .writeMessage(aMessage.origin,
-                          _("ctcp.time", aMessage.origin, time),
+        this.getConversation(aMessage.nickname)
+            .writeMessage(aMessage.nickname,
+                          _("ctcp.time", aMessage.nickname, time),
                           {system: true});
       }
       return true;
     },
 
     // This is commented out since CLIENTINFO automatically returns the
     // supported CTCP parameters and this is not supported.
 
@@ -220,24 +222,24 @@ var ctcpBase = {
     //"USERINFO": function(aMessage) false,
 
     // The version and type of the client.
     "VERSION": function(aMessage) {
       if (aMessage.command == "PRIVMSG") {
         // VERSION
         // Received VERSION request, send VERSION response.
         let version = Services.appinfo.name + " " + Services.appinfo.version;
-        this.LOG("Received VERSION request from " + aMessage.origin +
+        this.LOG("Received VERSION request from " + aMessage.nickname +
                  ". Sending VERSION response: \"" + version + "\".");
-        this.sendCTCPMessage(aMessage.origin, true, "VERSION", version);
+        this.sendCTCPMessage(aMessage.nickname, true, "VERSION", version);
       }
       else if (aMessage.command == "NOTICE" && aMessage.ctcp.param.length) {
         // VERSION #:#:#
         // Received VERSION response, display to the user.
-        let response = _("ctcp.version", aMessage.origin,
+        let response = _("ctcp.version", aMessage.nickname,
                          aMessage.ctcp.param);
-        this.getConversation(aMessage.origin)
-            .writeMessage(aMessage.origin, response, {system: true});
+        this.getConversation(aMessage.nickname)
+            .writeMessage(aMessage.nickname, response, {system: true});
       }
       return true;
     }
   }
 };
--- a/chat/protocols/irc/ircISUPPORT.jsm
+++ b/chat/protocols/irc/ircISUPPORT.jsm
@@ -180,24 +180,17 @@ var isupportBase = {
                   value);
         return false;
       }
 
       for (let i = 0; i < matches[2].length; i++)
         this.userPrefixToModeMap[matches[2][i]] = matches[1][i];
       return true;
     },
-    // SAFELIST allows the client to request the server buffer LIST responses to
-    // avoid flooding the client. This is not an issue for us, so just ignore
-    // it.
-    "SAFELIST": function(aMessage) true,
-    // SECURELIST tells us that the server won't send LIST data directly after
-    // connection. Unfortunately, the exact time the client has to wait is
-    // configurable, so we can't do anything with this information.
-    "SECURELIST": function(aMessage) true,
+    "SAFELIST": function(aMessage) false,
     "STATUSMSG": function(aMessage) false,
     "STD": function(aMessage) {
       // This was never updated as the RFC was never formalized.
       if (aMessage.isupport.value != "rfcnnnn")
         this.WARN("Unknown ISUPPORT numeric form: " + aMessage.isupport.value);
       return true;
     },
     "TARGMAX": function(aMessage) {
--- a/chat/protocols/irc/ircNonStandard.jsm
+++ b/chat/protocols/irc/ircNonStandard.jsm
@@ -22,55 +22,20 @@ Cu.import("resource:///modules/ircUtils.
 var ircNonStandard = {
   name: "Non-Standard IRC Extensions",
   priority: ircHandlers.DEFAULT_PRIORITY + 1,
   isEnabled: function() true,
 
   commands: {
     "NOTICE": function(aMessage) {
       // NOTICE <msgtarget> <text>
-
-      // Try to avoid the stupid case where the user's nick is AUTH. If this
-      // happens, it is ambiguous if it is an AUTH message or a NOTICE to the
-      // user. Generally AUTH messages start with ***, but this could pretty
-      // easily be faked.
-      // Freenode simply sends * for the target. Moznet sends Auth (used to send
-      // AUTH); in this case, check if the user's nickname is not auth, or the
-      // the message starts with ***.
-      let target = aMessage.params[0].toLowerCase();
-      let nickname = aMessage.origin ? aMessage.origin.toLowerCase() : "";
-      let isAuth = target == "*" ||
-        (target == "auth" && (nickname != "auth" ||
-                              aMessage.params[1].startsWith("***")));
-
-      // Some servers , e.g. irc.umich.edu, use NOTICE before connection to give
-      // directions to users.
-      if (!this.connected && !isAuth) {
-        this.getConversation(aMessage.origin)
-            .writeMessage(aMessage.origin, aMessage.params[1],
-                          {incoming: true});
-        return true;
-      }
-
-      if (aMessage.params[1].startsWith("*** You cannot list within the first")) {
-        // SECURELIST: "You cannot list within the first N seconds of connecting.
-        // Please try again later." This NOTICE will be followed by a 321/323
-        // pair, but no list data.
-        // We fake the last LIST time so that we will retry LIST the next time
-        // the user requires it after the interval specified.
-        const kMinute = 60000;
-        let waitTime = (aMessage.params[1].split(" ")[7] * 1000) || kMinute;
-        this._lastListTime = Date.now() + waitTime - kListRefreshInterval;
-        return true;
-      }
-
       // If we receive a ZNC error message requesting a password, the
       // serverPassword preference was not set by the user. Attempt to log into
       // ZNC using the account password.
-      if (!isAuth ||
+      if (aMessage.params[0] != "AUTH" ||
           aMessage.params[1] != "*** You need to send your password. Try /quote PASS <username>:<password>")
         return false;
 
       if (this.imAccount.password) {
         // Send the password now, if it is available.
         this.shouldAuthenticate = false;
         this.sendMessage("PASS", this.imAccount.password,
                          "PASS <password not logged>");
@@ -149,48 +114,29 @@ var ircNonStandard = {
     },
 
     "378": function(aMessage) { // RPL_WHOISHOST (Unreal & Charybdis)
       // <nick> :is connecting from <host> <ip>
       let [host, ip] = aMessage.params[2].split(" ").slice(-2);
       return this.setWhois(aMessage.params[1], {host: host, ip: ip});
     },
 
-    "396": function(aMessage) {
-      // RPL_HOSTHIDDEN (Charybdis, Hybrid, ircu, etc.)
-      // RPL_VISIBLEHOST (Plexus)
-      // RPL_YOURDISPLAYEDHOST (Inspircd)
-      // <host> :is now your hidden host
-
-      // This is the host that will be sent to other users.
-      this.prefix = "!" + aMessage.user + "@" + aMessage.params[1];
-      return true;
-    },
-
     "464": function(aMessage) {
       // :Password required
       // If we receive a ZNC error message requesting a password, eat it since
       // a NOTICE AUTH will follow causing us to send the password. This numeric
       // is, unfortunately, also sent if you give a wrong password. The
       // parameter in that case is "Invalid Password".
-      return aMessage.origin == "irc.znc.in" &&
+      return aMessage.servername == "irc.znc.in" &&
              aMessage.params[1] == "Password required";
     },
 
     "499": function(aMessage) { // ERR_CHANOWNPRIVNEEDED (Unreal)
       // <channel> :You're not the channel owner (status +q is needed)
       return conversationErrorMessage(this, aMessage, "error.notChannelOwner");
     },
 
     "671": function(aMessage) { // RPL_WHOISSECURE (Unreal & Charybdis)
       // <nick> :is using a Secure connection
       return this.setWhois(aMessage.params[1], {secure: true});
-    },
-
-    "998": function(aMessage) {
-      // irc.umich.edu shows an ASCII captcha that must be typed in by the user.
-      this.getConversation(aMessage.origin)
-          .writeMessage(aMessage.origin, aMessage.params[1],
-                        {incoming: true, noFormat: true});
-      return true;
     }
   }
 };
--- a/chat/protocols/irc/ircSASL.jsm
+++ b/chat/protocols/irc/ircSASL.jsm
@@ -36,29 +36,25 @@ var ircSASL = {
       // btoa for Unicode, see https://developer.mozilla.org/en-US/docs/DOM/window.btoa
       let base64Data = btoa(unescape(encodeURIComponent(data)));
       this.sendMessage("AUTHENTICATE", base64Data,
                        "AUTHENTICATE <base64 encoded nick, user and password not logged>");
       return true;
     },
 
     "900": function(aMessage) {
-      // <nick>!<ident>@<host> <account> :You are now logged in as <user>
-      // Now logged in ("whether by SASL or otherwise").
+      // Now logged in.
+      this.isAuthenticated = true;
+      this.LOG("SASL authentication successful.");
+      this.removeCAP("sasl");
       return true;
     },
 
     "903": function(aMessage) {
       // Authentication was successful.
-      this.isAuthenticated = true;
-      this.LOG("SASL authentication successful.");
-      // We may receive this again while already connected if the user manually
-      // identifies with Nickserv.
-      if (!this.connected)
-        this.removeCAP("sasl");
       return true;
     },
 
     "904": function(aMessage) {
       // AUTHENTICATE message failed.
       // Only PLAIN is currently supported, so fail here.
       this.WARN("The server does not support SASL PLAIN authentication.");
       this.removeCAP("sasl");
--- a/chat/protocols/irc/ircServices.jsm
+++ b/chat/protocols/irc/ircServices.jsm
@@ -36,17 +36,17 @@ function ServiceMessage(aAccount, aMessa
   // map "bar": "NickServ"). Note that the keys of this map should be
   // normalized.
   let nicknameToServiceName = {
     "chanserv": "ChanServ",
     "infoserv": "InfoServ",
     "nickserv": "NickServ"
   }
 
-  let nickname = aAccount.normalize(aMessage.origin);
+  let nickname = aAccount.normalize(aMessage.nickname);
   if (nicknameToServiceName.hasOwnProperty(nickname))
     aMessage.serviceName = nicknameToServiceName[nickname];
 
   return aMessage;
 }
 
 var ircServices = {
   name: "IRC Services",
@@ -59,17 +59,17 @@ var ircServices = {
                            "IDENTIFY <password not logged>");
     }
   },
 
   commands: {
     // If we automatically reply to a NOTICE message this does not abide by RFC
     // 2812. Oh well.
     "NOTICE": function(aMessage) {
-      if (!ircHandlers.hasServicesHandlers)
+      if (!ircHandlers.hasServicesHandlers || !aMessage.hasOwnProperty("nickname"))
         return false;
 
       let message = ServiceMessage(this, aMessage);
 
       // If no service was found, return early.
       if (!message.hasOwnProperty("serviceName"))
         return false;
 
@@ -79,19 +79,21 @@ var ircServices = {
     },
 
     "NICK": function(aMessage) {
       let newNick = aMessage.params[0];
       // We only auto-authenticate for the account nickname.
       if (this.normalize(newNick) != this.normalize(this._accountNickname))
         return false;
 
-      // If we're not identified already, try to identify.
-      if (!this.isAuthenticated)
-        ircServices.sendIdentify(this);
+      // We may still be authenticated, but we try to authenticate with the
+      // new nick anyway, since there is no good way to tell if we are still
+      // authenticated.
+      delete this.isAuthenticated;
+      ircServices.sendIdentify(this);
 
       // We always want the RFC 2812 handler to handle NICK, so return false.
       return false;
     },
 
     "001": function(aMessage) { // RPL_WELCOME
       // If SASL authentication failed, attempt IDENTIFY.
       ircServices.sendIdentify(this);
@@ -139,33 +141,34 @@ var servicesBase = {
       // Otherwise, display the message in that conversation.
       let params = {incoming: true};
       if (aMessage.command == "NOTICE")
         params.notification = true;
 
       // The message starts after the channel name, plus [, ] and a space.
       let message = aMessage.params[1].slice(channel.length + 3);
       this.getConversation(channel)
-          .writeMessage(aMessage.origin, message, params);
+          .writeMessage(aMessage.nickname, message, params);
       return true;
     },
 
     "InfoServ": function(aMessage) {
       let text = aMessage.params[1];
 
       // Show the message of the day in the server tab.
       if (text == "*** \u0002Message(s) of the Day\u0002 ***") {
         this._infoServMotd = [text];
         return true;
       }
       else if (text == "*** \u0002End of Message(s) of the Day\u0002 ***") {
         if (this._showServerTab && this._infoServMotd) {
           this._infoServMotd.push(text);
-          this.getConversation(aMessage.origin)
-              .writeMessage(aMessage.origin, this._infoServMotd.join("\n"),
+          this.getConversation(aMessage.servername || this._currentServerName)
+              .writeMessage(aMessage.servername || aMessage.nickname,
+                            this._infoServMotd.join("\n"),
                             {incoming: true});
           delete this._infoServMotd;
         }
         return true;
       }
       else if (this.hasOwnProperty("_infoServMotd")) {
         this._infoServMotd.push(text);
         return true;
--- a/chat/protocols/irc/ircUtils.jsm
+++ b/chat/protocols/irc/ircUtils.jsm
@@ -216,17 +216,17 @@ function mIRCColoring(aStack, aInput) {
   return [stack, output, length];
 }
 
 // Print an error message into a conversation, optionally mark the conversation
 // as not joined and/or not rejoinable.
 function conversationErrorMessage(aAccount, aMessage, aError,
                                   aJoinFailed = false, aRejoinable = true) {
   let conv = aAccount.getConversation(aMessage.params[1]);
-  conv.writeMessage(aMessage.origin, _(aError, aMessage.params[1]),
+  conv.writeMessage(aMessage.servername, _(aError, aMessage.params[1]),
                     {error: true, system: true});
   delete conv._pendingMessage;
 
   // Channels have a couple extra things that can be done to them.
   if (aAccount.isMUCName(aMessage.params[1])) {
     // If a value for joining is explictly given, mark it.
     if (aJoinFailed)
       conv.joining = false;
--- a/chat/protocols/irc/test/test_ircMessage.js
+++ b/chat/protocols/irc/test/test_ircMessage.js
@@ -15,17 +15,18 @@ const testData = [
   "OPER foo bar",
   "MODE WiZ -w",
   "MODE Angel +i",
   "MODE WiZ -o",
   "SERVICE dict * *.fr 0 0 :French Dictionary",
   "QUIT :Gone to have lunch",
   ":syrk!kalt@millennium.stealth.net QUIT :Gone to have lunch",
   "SQUIT tolsun.oulu.fi :Bad Link ?",
-  ":Trillian SQUIT cm22.eng.umd.edu :Server out of control",
+  // This fails! But do we really care? It wasn't designed to handle server messages.
+  //":Trillian SQUIT cm22.eng.umd.edu :Server out of control",
   "JOIN #foobar",
   "JOIN &foo fubar",
   "JOIN #foo,&bar fubar",
   "JOIN #foo,#bar fubar,foobar",
   "JOIN #foo,#bar",
   "JOIN 0",
   ":WiZ!jto@tolsun.oulu.fi JOIN #Twilight_zone",
   "PART #twilight_zone",
@@ -114,49 +115,41 @@ const testData = [
   "PRIVMSG foo :", // Empty last parameter.
   "PRIVMSG foo :This is :a test." // A "second" last parameter.
 ];
 
 function run_test() {
   add_test(testRFC2812Messages);
   add_test(testBrokenUnrealMessages);
   add_test(testNewLinesInMessages);
-  add_test(testLocalhost);
 
   run_next_test();
 }
 
-/*
- * Test round tripping parsing and then rebuilding the messages from RFC 2812.
- */
 function testRFC2812Messages() {
   for each (let expectedStringMessage in testData) {
-    // Pass in an empty default origin in order to check this below.
-    let message = irc.ircMessage(expectedStringMessage, "");
+    let message = irc.ircMessage(expectedStringMessage);
 
     let stringMessage =
       irc.ircAccount.prototype.buildMessage(message.command, message.params);
 
     // Let's do a little dance here...we don't rebuild the "source" of the
     // message (the server does that), so when comparing our output message, we
     // need to avoid comparing to that part.
-    if (message.origin) {
+    if (message.servername || message.source) {
       expectedStringMessage =
         expectedStringMessage.slice(expectedStringMessage.indexOf(" ") + 1);
     }
 
     do_check_eq(stringMessage, expectedStringMessage);
   }
 
   run_next_test();
 }
 
-/*
- * Test if two objects have the same fields (recursively).
- */
 function isEqual(aObject1, aObject2) {
   let result = true;
   for (let fieldName in aObject1) {
     let field1 = aObject1[fieldName];
     let field2 = aObject2[fieldName];
     if (typeof field1 == "object")
       result &= isEqual(field1, field2);
     else if (Array.isArray(field1))
@@ -166,88 +159,63 @@ function isEqual(aObject1, aObject2) {
   }
   return result;
 }
 
 // Unreal sends a couple of broken messages, see ircMessage in irc.js for a
 // description of what's wrong.
 function testBrokenUnrealMessages() {
   let messages = {
-    // Two spaces after command.
     ":gravel.mozilla.org 432  #momo :Erroneous Nickname: Illegal characters": {
       rawMessage: ":gravel.mozilla.org 432  #momo :Erroneous Nickname: Illegal characters",
       command: "432",
       params: ["", "#momo", "Erroneous Nickname: Illegal characters"],
-      origin: "gravel.mozilla.org"
+      servername: "gravel.mozilla.org"
     },
-    // An extraneous space at the end.
     ":gravel.mozilla.org MODE #tckk +n ": {
       rawMessage: ":gravel.mozilla.org MODE #tckk +n ",
       command: "MODE",
       params: ["#tckk", "+n"],
-      origin: "gravel.mozilla.org"
+      servername: "gravel.mozilla.org"
     },
-    // Two extraneous spaces at the end.
     ":services.esper.net MODE #foo-bar +o foobar  ": {
       rawMessage: ":services.esper.net MODE #foo-bar +o foobar  ",
       command: "MODE",
       params: ["#foo-bar", "+o", "foobar"],
-      origin: "services.esper.net"
+      servername: "services.esper.net"
     }
   };
 
   for (let messageStr in messages)
-    do_check_true(isEqual(messages[messageStr], irc.ircMessage(messageStr, "")));
+    do_check_true(isEqual(messages[messageStr], irc.ircMessage(messageStr)));
 
   run_next_test();
 }
 
 // After unescaping we can end up with line breaks inside of IRC messages. Test
 // this edge case specifically.
 function testNewLinesInMessages() {
   let messages = {
     ":test!Instantbir@host PRIVMSG #instantbird :First line\nSecond line": {
       rawMessage: ":test!Instantbir@host PRIVMSG #instantbird :First line\nSecond line",
       command: "PRIVMSG",
       params: ["#instantbird", "First line\nSecond line"],
-      origin: "test",
+      nickname: "test",
       user: "Instantbir",
       host: "host",
       source: "Instantbir@host"
     },
     ":test!Instantbir@host PRIVMSG #instantbird :First line\r\nSecond line": {
       rawMessage: ":test!Instantbir@host PRIVMSG #instantbird :First line\r\nSecond line",
       command: "PRIVMSG",
       params: ["#instantbird", "First line\r\nSecond line"],
-      origin: "test",
+      nickname: "test",
       user: "Instantbir",
       host: "host",
       source: "Instantbir@host"
     }
   };
 
   for (let messageStr in messages)
     do_check_true(isEqual(messages[messageStr], irc.ircMessage(messageStr)));
 
   run_next_test();
 }
-
-// Sometimes it is a bit hard to tell whether a prefix is a nickname or a
-// servername. Generally this happens when connecting to localhost or a local
-// hostname and is likely seen with bouncers.
-function testLocalhost() {
-  let messages = {
-    ":localhost 001 clokep :Welcome to the BitlBee gateway, clokep": {
-      rawMessage: ":localhost 001 clokep :Welcome to the BitlBee gateway, clokep",
-      command: "001",
-      params: ["clokep", "Welcome to the BitlBee gateway, clokep"],
-      origin: "localhost",
-      user: undefined,
-      host: undefined,
-      source: ""
-    }
-  };
-
-  for (let messageStr in messages)
-    do_check_true(isEqual(messages[messageStr], irc.ircMessage(messageStr)));
-
-  run_next_test();
-}
--- a/chat/protocols/xmpp/xmpp-xml.jsm
+++ b/chat/protocols/xmpp/xmpp-xml.jsm
@@ -199,18 +199,18 @@ XMLNode.prototype = {
     this.children.filter(function(c) c.uri == aNS),
 
   /* Get the first element inside the node that matches a query. */
   getElement: function(aQuery) {
     if (aQuery.length == 0)
       return this;
 
     let nq = aQuery.slice(1);
-    for (let child of this.children) {
-      if (child.type == "text" || child.qName != aQuery[0])
+    for each (let child in this.children) {
+      if (child.qName != aQuery[0])
         continue;
       let n = child.getElement(nq);
       if (n)
         return n;
     }
 
     return null;
   },
@@ -228,17 +228,17 @@ XMLNode.prototype = {
       res = res.concat(n);
     }
 
     return res;
   },
 
   /* Get immediate children by the node name */
   getChildren: function(aName)
-    this.children.filter((c) => (c.type != "text" && c.qName == aName)),
+    this.children.filter(function(c) c.qName == aName),
 
   /* Test if the node is a stanza */
   isXmppStanza: function() {
     if (!TOP_LEVEL_ELEMENTS.hasOwnProperty(this.qName))
       return false;
     let ns = TOP_LEVEL_ELEMENTS[this.qName];
     return ns == this.uri || (Array.isArray(ns) && ns.indexOf(this.uri) != -1);
   },
--- a/chat/protocols/yahoo/moz.build
+++ b/chat/protocols/yahoo/moz.build
@@ -1,14 +1,15 @@
 # vim: set filetype=python:
 # 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/.
 
-XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
+if not CONFIG['MOZ_THUNDERBIRD']:
+    XPCSHELL_TESTS_MANIFESTS += ['test/xpcshell.ini']
 
 EXTRA_COMPONENTS += [
     'yahoo.js',
     'yahoo.manifest',
 ]
 
 EXTRA_JS_MODULES += [
     'yahoo-session.jsm',
--- a/chat/protocols/yahoo/test/test_yahooAccount.js
+++ b/chat/protocols/yahoo/test/test_yahooAccount.js
@@ -1,12 +1,12 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource:///modules/Services.jsm");
 let yahoo = {};
 Services.scriptloader.loadSubScript("resource:///components/yahoo.js", yahoo);
 
 function run_test()
 {
   add_test(test_cleanUsername);
   add_test(test_fixFontSize);
   run_next_test();
--- a/chat/protocols/yahoo/test/test_yahooLoginHelper.js
+++ b/chat/protocols/yahoo/test/test_yahooLoginHelper.js
@@ -1,13 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Components.utils.import("resource:///modules/ArrayBufferUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource:///modules/Services.jsm");
 Components.utils.import("resource:///modules/yahoo-session.jsm");
 let yahoo = {};
 Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo);
 
 // Preset test values.
 const kUsername = "testUser";
 const kPassword = "instantbird";
 const kPagerIp = "123.456.78.9";
--- a/chat/protocols/yahoo/test/test_yahoopacket.js
+++ b/chat/protocols/yahoo/test/test_yahoopacket.js
@@ -1,13 +1,13 @@
 /* Any copyright is dedicated to the Public Domain.
  * http://creativecommons.org/publicdomain/zero/1.0/ */
 
 Components.utils.import("resource:///modules/ArrayBufferUtils.jsm");
-Components.utils.import("resource://gre/modules/Services.jsm");
+Components.utils.import("resource:///modules/Services.jsm");
 Components.utils.import("resource:///modules/yahoo-session.jsm");
 let yahoo = {};
 Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo);
 
 const kPacketIdBytes = StringToBytes(yahoo.kPacketIdentfier);
 const kHelloKey = 1;
 const kHelloValue = "Hello";
 const kWorldKey = 20;
--- a/chat/themes/conv.css
+++ b/chat/themes/conv.css
@@ -40,12 +40,8 @@
 
 .ib-nick {
   font-weight: bold;
 }
 
 .ib-nick[left] {
   color: grey;
 }
-
-.monospaced {
-  font-family: monospace;
-}
--- a/client.py
+++ b/client.py
@@ -12,17 +12,17 @@
 # Define x_REV to override. Where x can be one of:
 #  "COMM", "MOZILLA", "CHATZILLA", "INSPECTOR", "LDAPSDKS"
 DEFAULTS = {
   # Global Default Revision
   'REV': "default",
 
   # LDAPSDKS
   'LDAPSDKS_REPO': 'https://hg.mozilla.org/projects/ldap-sdks/',
-  'LDAPSDKS_REV': 'LDAPCSDK_6_0_7G_RTM',
+  'LDAPSDKS_REV': 'LDAPCSDK_6_0_7F_RTM',
 
   # URL of the default hg repository to clone for ChatZilla.
   'CHATZILLA_REPO': 'https://hg.mozilla.org/chatzilla/',
   # The stable revision to use
   'CHATZILLA_REV':  'SEA2_32_RELBRANCH',
 
   # URL of the default hg repository to clone for DOM Inspector.
   'INSPECTOR_REPO': 'https://hg.mozilla.org/dom-inspector/',
--- a/config/baseconfig.mk
+++ b/config/baseconfig.mk
@@ -1,21 +1,16 @@
 # This file is normally included by autoconf.mk, but it is also used
 # directly in python/mozbuild/mozbuild/base.py for gmake validation.
 # We thus use INCLUDED_AUTOCONF_MK to enable/disable some parts depending
 # whether a normal build is happening or whether the check is running.
 
-# When mach wants to know if we're to use mozmake, it runs:
-# make -f topsrcdir/config/baseconfig.mk
-# The first word of MAKEFILE_LIST is the main file we're running. Grabbing the
-# parent of that directory therefore gets us the topsrcdir of comm-central,
-# whence we get the mozilla directory to run the "real" baseconfig.mk logic.
+MOZILLA_SRCDIR = $(topsrcdir)/mozilla
 ifndef INCLUDED_AUTOCONF_MK
-topsrcdir := $(dir $(firstword $(MAKEFILE_LIST)))..
+default::
+else
+include $(MOZILLA_SRCDIR)/config/baseconfig.mk
 endif
 
-MOZILLA_SRCDIR = $(topsrcdir)/mozilla
-include $(MOZILLA_SRCDIR)/config/baseconfig.mk
-
 # WIN_TOP_SRC is converted by config.mk to mozilla-central, but this needs to be comm-central.
 ifdef WIN_TOP_SRC
 WIN_TOP_SRC := $(patsubst %/mozilla,%,$(WIN_TOP_SRC))
 endif
--- a/config/config.mk
+++ b/config/config.mk
@@ -24,21 +24,82 @@ topsrcdir	= $(DEPTH)
 endif
 
 ifndef INCLUDED_AUTOCONF_MK
 include $(DEPTH)/config/autoconf.mk
 endif
 
 -include $(DEPTH)/.mozconfig.mk
 
+# Integrate with mozbuild-generated make files. We first verify that no
+# variables provided by the automatically generated .mk files are
+# present. If they are, this is a violation of the separation of
+# responsibility between Makefile.in and mozbuild files.
+_MOZBUILD_EXTERNAL_VARIABLES := \
+  ANDROID_GENERATED_RESFILES \
+  ANDROID_RESFILES \
+  CMMSRCS \
+  CPP_UNIT_TESTS \
+  DIRS \
+  DIST_SUBDIR \
+  EXTRA_DSO_LDOPTS \
+  EXTRA_JS_MODULES \
+  EXTRA_PP_COMPONENTS \
+  EXTRA_PP_JS_MODULES \
+  FINAL_LIBRARY \
+  FINAL_TARGET \
+  GTEST_CMMSRCS \
+  GTEST_CPPSRCS \
+  GTEST_CSRCS \
+  HOST_CSRCS \
+  HOST_LIBRARY_NAME \
+  IS_COMPONENT \
+  JAR_MANIFEST \
+  LIBRARY_NAME \
+  LIBS \
+  LIBXUL_LIBRARY \
+  MAKE_FRAMEWORK \
+  MODULE \
+  MSVC_ENABLE_PGO \
+  NO_DIST_INSTALL \
+  PARALLEL_DIRS \
+  SDK_HEADERS \
+  SDK_LIBRARY \
+  SHARED_LIBRARY_LIBS \
+  SHARED_LIBRARY_NAME \
+  SIMPLE_PROGRAMS \
+  STATIC_LIBRARY_NAME \
+  TEST_DIRS \
+  TESTING_JS_MODULES \
+  TESTING_JS_MODULE_DIR \
+  TIERS \
+  TOOL_DIRS \
+  XPCSHELL_TESTS \
+  XPIDL_MODULE \
+  XPI_NAME \
+  $(NULL)
+
+_DEPRECATED_VARIABLES := \
+  MOCHITEST_FILES_PARTS \
+  MOCHITEST_BROWSER_FILES_PARTS \
+  $(NULL)
+
 ifndef EXTERNALLY_MANAGED_MAKE_FILE
 # Using $(firstword) may not be perfect. But it should be good enough for most
 # scenarios.
 _current_makefile = $(CURDIR)/$(firstword $(MAKEFILE_LIST))
 
+$(foreach var,$(_MOZBUILD_EXTERNAL_VARIABLES),$(if $(filter file override,$(subst $(NULL) ,_,$(origin $(var)))),\
+    $(error Variable $(var) is defined in $(_current_makefile). It should only be defined in moz.build files),\
+    ))
+
+$(foreach var,$(_DEPRECATED_VARIABLES),$(if $(filter file override,$(subst $(NULL) ,_,$(origin $(var)))),\
+    $(error Variable $(var) is defined in $(_current_makefile). This variable has been deprecated. It does nothing. It must be removed in order to build)\
+    ))
+
 # Import the automatically generated backend file. If this file doesn't exist,
 # the backend hasn't been properly configured. We want this to be a fatal
 # error, hence not using "-include".
 ifndef STANDALONE_MAKEFILE
 GLOBAL_DEPS += backend.mk
 include backend.mk
 endif
 
@@ -210,20 +271,30 @@ endif # MOZ_DEBUG_SYMBOLS
 #
 ifdef NS_TRACE_MALLOC
 MOZ_OPTIMIZE_FLAGS=-Zi -Od -UDEBUG -DNDEBUG
 OS_LDFLAGS = -DEBUG -PDB:NONE -OPT:REF -OPT:nowin98
 endif # NS_TRACE_MALLOC
 
 endif # MOZ_DEBUG
 
+# We don't build a static CRT when building a custom CRT,
+# it appears to be broken. So don't link to jemalloc if
+# the Makefile wants static CRT linking.
+ifeq ($(MOZ_MEMORY)_$(USE_STATIC_LIBS),1_1)
+# Disable default CRT libs and add the right lib path for the linker
+MOZ_GLUE_LDFLAGS =
+endif
+
 endif # WINNT && !GNU_CC
 
-ifdef MOZ_GLUE_IN_PROGRAM
+ifdef MOZ_GLUE_PROGRAM_LDFLAGS
 DEFINES += -DMOZ_GLUE_IN_PROGRAM
+else
+MOZ_GLUE_PROGRAM_LDFLAGS=$(MOZ_GLUE_LDFLAGS)
 endif
 
 # Determine if module being compiled is destined 
 # to be merged into libxul
 
 ifeq ($(FINAL_LIBRARY),xul)
   ifdef LIBXUL_LIBRARY
     $(error FINAL_LIBRARY is "xul", LIBXUL_LIBRARY is implied)
@@ -270,16 +341,20 @@ OS_CFLAGS += $(if $(filter $(notdir $<),
 OS_CXXFLAGS += $(if $(filter $(notdir $<),$(notdir $(NO_PROFILE_GUIDED_OPTIMIZE))),,$(PROFILE_USE_CFLAGS))
 OS_LDFLAGS += $(PROFILE_USE_LDFLAGS)
 ifeq (WINNT,$(OS_ARCH))
 AR_FLAGS += -LTCG
 endif
 endif # MOZ_PROFILE_USE
 endif # NO_PROFILE_GUIDED_OPTIMIZE
 
+ifdef _MSC_VER
+OS_LDFLAGS += $(DELAYLOAD_LDFLAGS)
+endif # _MSC_VER
+
 # Does the makefile specifies the internal XPCOM API linkage?
 ifneq (,$(MOZILLA_INTERNAL_API)$(LIBXUL_LIBRARY))
 DEFINES += -DMOZILLA_INTERNAL_API
 endif
 
 # Force XPCOM/widget/gfx methods to be _declspec(dllexport) when we're
 # building libxul libraries
 ifdef LIBXUL_LIBRARY
@@ -667,16 +742,34 @@ EXPAND_CC = $(EXPAND_LIBS_EXEC) --uselis
 EXPAND_CCC = $(EXPAND_LIBS_EXEC) --uselist -- $(CCC)
 EXPAND_LD = $(EXPAND_LIBS_EXEC) --uselist -- $(LD)
 EXPAND_MKSHLIB_ARGS = --uselist
 ifdef SYMBOL_ORDER
 EXPAND_MKSHLIB_ARGS += --symbol-order $(SYMBOL_ORDER)
 endif
 EXPAND_MKSHLIB = $(EXPAND_LIBS_EXEC) $(EXPAND_MKSHLIB_ARGS) -- $(MKSHLIB)
 
+# EXPAND_LIBNAME - $(call EXPAND_LIBNAME,foo)
+# expands to $(LIB_PREFIX)foo.$(LIB_SUFFIX) or -lfoo, depending on linker
+# arguments syntax. Should only be used for system libraries
+
+# EXPAND_LIBNAME_PATH - $(call EXPAND_LIBNAME_PATH,foo,dir)
+# expands to dir/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+# EXPAND_MOZLIBNAME - $(call EXPAND_MOZLIBNAME,foo)
+# expands to $(DIST)/lib/$(LIB_PREFIX)foo.$(LIB_SUFFIX)
+
+ifdef GNU_CC
+EXPAND_LIBNAME = $(addprefix -l,$(1))
+else
+EXPAND_LIBNAME = $(foreach lib,$(1),$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+endif
+EXPAND_LIBNAME_PATH = $(foreach lib,$(1),$(2)/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+EXPAND_MOZLIBNAME = $(foreach lib,$(1),$(DIST)/lib/$(LIB_PREFIX)$(lib).$(LIB_SUFFIX))
+
 # Include internal ply only if needed
 ifndef MOZ_SYSTEM_PLY
 PLY_INCLUDE = -I$(MOZILLA_DIR)/other-licenses/ply
 endif
  
 export CL_INCLUDES_PREFIX
 
 ifneq (,$(MOZ_LIBSTDCXX_TARGET_VERSION)$(MOZ_LIBSTDCXX_HOST_VERSION))
--- a/config/recurse.mk
+++ b/config/recurse.mk
@@ -1,9 +1,158 @@
 # 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/.
 
 ifndef INCLUDED_RULES_MK
 include $(topsrcdir)/config/rules.mk
 endif
 
-include $(MOZILLA_DIR)/config/recurse.mk
+# The traditional model of directory traversal with make is as follows:
+#   make -C foo
+#     Entering foo
+#     make -C bar
+#       Entering foo/bar
+#     make -C baz
+#       Entering foo/baz
+#   make -C qux
+#     Entering qux
+#
+# Pseudo derecurse transforms the above into:
+#   make -C foo
+#   make -C foo/bar
+#   make -C foo/baz
+#   make -C qux
+
+ifeq (.,$(DEPTH))
+
+include root.mk
+
+# Disable build status for mach in top directories without TIERS.
+# In practice this disables it when recursing under js/src, which confuses mach.
+ifndef TIERS
+BUILDSTATUS =
+endif
+
+# Main rules (export, compile, libs and tools) call recurse_* rules.
+# This wrapping is only really useful for build status.
+compile libs export tools::
+	$(call BUILDSTATUS,TIER_START $@)
+	+$(MAKE) recurse_$@
+	$(call BUILDSTATUS,TIER_FINISH $@)
+
+# Special rule that does install-manifests (cf. Makefile.in) + compile
+binaries::
+	+$(MAKE) recurse_compile
+
+# Carefully avoid $(eval) type of rule generation, which makes pymake slower
+# than necessary.
+# Get current tier and corresponding subtiers from the data in root.mk.
+CURRENT_TIER := $(filter $(foreach tier,compile libs export tools,recurse_$(tier) $(tier)-deps),$(MAKECMDGOALS))
+ifneq (,$(filter-out 0 1,$(words $(CURRENT_TIER))))
+$(error $(CURRENT_TIER) not supported on the same make command line)
+endif
+CURRENT_TIER := $(subst recurse_,,$(CURRENT_TIER:-deps=))
+
+# The rules here are doing directory traversal, so we don't want further
+# recursion to happen when running make -C subdir $tier. But some make files
+# further call make -C something else, and sometimes expect recursion to
+# happen in that case (see browser/metro/locales/Makefile.in for example).
+# Conveniently, every invocation of make increases MAKELEVEL, so only stop
+# recursion from happening at current MAKELEVEL + 1.
+ifdef CURRENT_TIER
+ifeq (0,$(MAKELEVEL))
+export NO_RECURSE_MAKELEVEL=1
+else
+export NO_RECURSE_MAKELEVEL=$(word $(MAKELEVEL),2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20)
+endif
+endif
+
+# Get all directories traversed for all subtiers in the current tier, or use
+# directly the $(*_dirs) variables available in root.mk when there is no
+# TIERS (like for js/src).
+CURRENT_DIRS := $($(CURRENT_TIER)_dirs)
+
+# The compile tier has different rules from other tiers.
+ifeq ($(CURRENT_TIER),compile)
+
+# Need a list of compile targets because we can't use pattern rules:
+# https://savannah.gnu.org/bugs/index.php?42833
+.PHONY: $(compile_targets)
+$(compile_targets):
+	$(call SUBMAKE,$(if $(filter $(@D),$(staticdirs)),,$(@F)),$(@D))
+
+else
+
+# Recursion rule for all directories traversed for all subtiers in the
+# current tier.
+$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): %/$(CURRENT_TIER):
+	$(call SUBMAKE,$(CURRENT_TIER),$*)
+
+.PHONY: $(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS))
+
+# Dummy rules for possibly inexisting dependencies for the above tier targets
+$(addsuffix /Makefile,$(CURRENT_DIRS)) $(addsuffix /backend.mk,$(CURRENT_DIRS)):
+
+ifeq ($(CURRENT_TIER),export)
+# At least build/export requires config/export for buildid, but who knows what
+# else, so keep this global dependency to make config/export first for now.
+$(addsuffix /$(CURRENT_TIER),$(filter-out config,$(CURRENT_DIRS))): config/$(CURRENT_TIER)
+
+# The export tier requires nsinstall, which is built from config. So every
+# subdirectory traversal needs to happen after building nsinstall in config,
+# which is done with the config/host target. Note the config/host target only
+# exists if nsinstall is actually built, which it is not on Windows, because we
+# use nsinstall.py there.
+ifneq (,$(filter config/host, $(compile_targets)))
+$(addsuffix /$(CURRENT_TIER),$(CURRENT_DIRS)): config/host
+
+# Ensure rules for config/host and its possible dependencies.
+.PHONY: $(filter %/host, $(compile_targets))
+$(filter %/host, $(compile_targets)):
+	$(call SUBMAKE,host,$(@D))
+endif
+endif
+
+endif # ifeq ($(CURRENT_TIER),compile)
+
+else
+
+# Don't recurse if MAKELEVEL is NO_RECURSE_MAKELEVEL as defined above
+ifeq ($(NO_RECURSE_MAKELEVEL),$(MAKELEVEL))
+
+compile libs export tools::
+
+else
+#########################
+# Tier traversal handling
+#########################
+
+ifdef TIERS
+
+libs export tools::
+	$(call BUILDSTATUS,TIER_START $@)
+	$(foreach tier,$(TIERS), $(if $(filter-out libs_precompile tools_precompile,$@_$(tier)), \
+		$(if $(filter libs,$@),$(foreach dir, $(tier_$(tier)_staticdirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),,1))) \
+		$(foreach dir, $(tier_$(tier)_dirs), $(call TIER_DIR_SUBMAKE,$@,$(tier),$(dir),$@))))
+	$(call BUILDSTATUS,TIER_FINISH $@)
+
+else
+
+define CREATE_SUBTIER_TRAVERSAL_RULE
+.PHONY: $(1)
+
+$(1):: $$(SUBMAKEFILES)
+	$$(LOOP_OVER_DIRS)
+
+endef
+
+$(foreach subtier,export libs tools,$(eval $(call CREATE_SUBTIER_TRAVERSAL_RULE,$(subtier))))
+
+endif # ifdef TIERS
+
+endif # ifeq ($(NO_RECURSE_MAKELEVEL),$(MAKELEVEL))
+
+endif # ifeq (.,$(DEPTH))
+
+recurse:
+	@$(RECURSED_COMMAND)
+	$(LOOP_OVER_DIRS)
--- a/config/rules.mk
+++ b/config/rules.mk
@@ -106,32 +106,28 @@ endif # ENABLE_TESTS
 #
 
 ifndef LIBRARY
 ifdef REAL_LIBRARY
 # Don't build actual static library if a shared library is also built
 ifdef FORCE_SHARED_LIB
 # ... except when we really want one
 ifdef NO_EXPAND_LIBS
-LIBRARY			:= $(REAL_LIBRARY)
+LIBRARY			:= $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
 else
 LIBRARY			:= $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
 endif
 else
 # Only build actual library if it is installed in DIST/lib or SDK
 ifeq (,$(SDK_LIBRARY)$(DIST_INSTALL)$(NO_EXPAND_LIBS))
 LIBRARY			:= $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
 else
-ifdef NO_EXPAND_LIBS
-LIBRARY                 := $(REAL_LIBRARY)
-else
 LIBRARY			:= $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
 endif
 endif
-endif
 endif # REAL_LIBRARY
 endif # LIBRARY
 
 ifndef HOST_LIBRARY
 ifdef HOST_LIBRARY_NAME
 HOST_LIBRARY		:= $(LIB_PREFIX)$(HOST_LIBRARY_NAME).$(LIB_SUFFIX)
 endif
 endif
@@ -441,16 +437,22 @@ endif
 #
 # GNU doesn't have path length limitation
 #
 
 ifeq ($(OS_ARCH),GNU)
 OS_CPPFLAGS += -DPATH_MAX=1024 -DMAXPATHLEN=1024
 endif
 
+ifeq ($(OS_ARCH),WINNT)
+ifdef USE_DELAYIMP
+OS_LIBS += $(call EXPAND_LIBNAME,delayimp)
+endif
+endif
+
 #
 # MINGW32
 #
 ifeq ($(OS_ARCH),WINNT)
 ifdef GNU_CC
 ifndef IS_COMPONENT
 DSO_LDOPTS += -Wl,--out-implib -Wl,$(IMPORT_LIBRARY)
 endif
@@ -481,18 +483,30 @@ endif
 
 ifeq (,$(CROSS_COMPILE))
 HOST_OUTOPTION = $(OUTOPTION)
 else
 HOST_OUTOPTION = -o # eol
 endif
 ################################################################################
 
+# The root makefile doesn't want to do a plain export/libs, because
+# of the tiers and because of libxul. Suppress the default rules in favor
+# of something else. Makefiles which use this var *must* provide a sensible
+# default rule before including rules.mk
+ifndef SUPPRESS_DEFAULT_RULES
 default all::
-	$(foreach tier,$(TIERS),$(call SUBMAKE,$(tier)))
+	$(MAKE) export
+ifdef COMPILE_ENVIRONMENT
+	$(MAKE) compile
+endif
+	$(MAKE) libs
+	$(MAKE) tools
+
+endif # SUPPRESS_DEFAULT_RULES
 
 ifeq ($(findstring s,$(filter-out --%, $(MAKEFLAGS))),)
 ECHO := echo
 QUIET :=
 else
 ECHO := true
 QUIET := -q
 endif
@@ -683,17 +697,17 @@ alltags:
 
 #
 # PROGRAM = Foo
 # creates OBJS, links with LIBS to create Foo
 #
 $(PROGRAM): $(PROGOBJS) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(EXE_DEF_FILE) $(RESFILE) $(GLOBAL_DEPS)
 	@$(RM) $@.manifest
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
-	$(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+	$(EXPAND_LD) -NOLOGO -OUT:$@ -PDB:$(LINK_PDBFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(PROGOBJS) $(RESFILE) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		if test -f '$(srcdir)/$@.manifest'; then \
 			echo 'Embedding manifest from $(srcdir)/$@.manifest and $@.manifest'; \
 			mt.exe -NOLOGO -MANIFEST '$(win_srcdir)/$@.manifest' $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		else \
 			echo 'Embedding manifest from $@.manifest'; \
 			mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
@@ -704,17 +718,17 @@ ifdef MSMANIFEST_TOOL
 	fi
 endif	# MSVC with manifest tool
 ifdef MOZ_PROFILE_GENERATE
 # touch it a few seconds into the future to work around FAT's
 # 2-second granularity
 	touch -t `date +%Y%m%d%H%M.%S -d 'now+5seconds'` pgo.relink
 endif
 else # !WINNT || GNU_CC
-	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
+	$(EXPAND_CCC) -o $@ $(CXXFLAGS) $(PROGOBJS) $(RESFILE) $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(EXE_DEF_FILE) $(STLPORT_LIBS)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -749,25 +763,25 @@ endif
 # in one directory, it assumes everything to compile Foo is in
 # Foo.o (from either Foo.c or Foo.cpp).
 #
 # SIMPLE_PROGRAMS = Foo Bar
 # creates Foo.o Bar.o, links with LIBS to create Foo, Bar.
 #
 $(SIMPLE_PROGRAMS): %$(BIN_SUFFIX): %.$(OBJ_SUFFIX) $(STATIC_LIBS_DEPS) $(EXTRA_DEPS) $(GLOBAL_DEPS)
 ifeq (_WINNT,$(GNU_CC)_$(OS_ARCH))
-	$(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
+	$(EXPAND_LD) -nologo -out:$@ -pdb:$(LINK_PDBFILE) $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS)
 ifdef MSMANIFEST_TOOL
 	@if test -f $@.manifest; then \
 		mt.exe -NOLOGO -MANIFEST $@.manifest -OUTPUTRESOURCE:$@\;1; \
 		rm -f $@.manifest; \
 	fi
 endif	# MSVC with manifest tool
 else
-	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(STATIC_LIBS) $(MOZ_PROGRAM_LDFLAGS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
+	$(EXPAND_CCC) $(CXXFLAGS) -o $@ $< $(WIN32_EXE_LDFLAGS) $(LDFLAGS) $(WRAP_LDFLAGS) $(MOZ_GLUE_PROGRAM_LDFLAGS) $(STATIC_LIBS) $(SHARED_LIBS) $(EXTRA_LIBS) $(OS_LIBS) $(BIN_FLAGS) $(STLPORT_LIBS)
 endif # WINNT && !GNU_CC
 
 ifdef ENABLE_STRIP
 	$(STRIP) $(STRIP_FLAGS) $@
 endif
 ifdef MOZ_POST_PROGRAM_COMMAND
 	$(MOZ_POST_PROGRAM_COMMAND) $@
 endif
@@ -784,18 +798,17 @@ endif
 endif
 
 ifdef DTRACE_PROBE_OBJ
 EXTRA_DEPS += $(DTRACE_PROBE_OBJ)
 OBJS += $(DTRACE_PROBE_OBJ)
 endif
 
 $(filter %.$(LIB_SUFFIX),$(LIBRARY)): $(OBJS) $(STATIC_LIBS_DEPS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(EXTRA_DEPS) $(GLOBAL_DEPS)
-# Always remove both library and library descriptor
-	$(RM) $(REAL_LIBRARY) $(REAL_LIBRARY).$(LIBS_DESC_SUFFIX)
+	$(RM) $(LIBRARY)
 	$(EXPAND_AR) $(AR_FLAGS) $(OBJS) $(STATIC_LIBS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS))
 	$(RANLIB) $@
 
 $(filter-out %.$(LIB_SUFFIX),$(LIBRARY)): $(filter %.$(LIB_SUFFIX),$(LIBRARY)) $(OBJS) $(STATIC_LIBS_DEPS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS)) $(EXTRA_DEPS) $(GLOBAL_DEPS)
 # When we only build a library descriptor, blow out any existing library
 	$(if $(filter %.$(LIB_SUFFIX),$(LIBRARY)),,$(RM) $(REAL_LIBRARY))
 	$(EXPAND_LIBS_GEN) -o $@ $(OBJS) $(STATIC_LIBS) $(filter %.$(LIB_SUFFIX),$(EXTRA_LIBS))
 
@@ -1192,21 +1205,20 @@ endif
 ################################################################################
 # Install a linked .xpt into the appropriate place.
 # This should ideally be performed by the non-recursive idl make file. Some day.
 ifdef XPT_NAME #{
 
 ifndef NO_DIST_INSTALL
 _XPT_NAME_FILES := $(DEPTH)/config/makefiles/xpidl/xpt/$(XPT_NAME)
 _XPT_NAME_DEST := $(FINAL_TARGET)/components
-_XPT_NAME_TARGET := misc
 INSTALL_TARGETS += _XPT_NAME
 
 ifndef NO_INTERFACES_MANIFEST
-misc:: $(call mkdir_deps,$(FINAL_TARGET)/components)
+libs:: $(call mkdir_deps,$(FINAL_TARGET)/components)
 	$(call py_action,buildlist,$(FINAL_TARGET)/components/interfaces.manifest 'interfaces $(XPT_NAME)')
 	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest 'manifest components/interfaces.manifest')
 endif
 endif
 
 endif #} XPT_NAME
 
 ################################################################################
@@ -1215,36 +1227,34 @@ ifneq (,$(filter %.js,$(EXTRA_COMPONENTS
 ifeq (,$(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS)))
 ifndef NO_JS_MANIFEST
 $(error .js component without matching .manifest. See https://developer.mozilla.org/en/XPCOM/XPCOM_changes_in_Gecko_2.0)
 endif
 endif
 endif
 
 ifdef EXTRA_COMPONENTS
-misc:: $(EXTRA_COMPONENTS)
+libs:: $(EXTRA_COMPONENTS)
 ifndef NO_DIST_INSTALL
 EXTRA_COMPONENTS_FILES := $(EXTRA_COMPONENTS)
 EXTRA_COMPONENTS_DEST := $(FINAL_TARGET)/components
-EXTRA_COMPONENTS_TARGET := misc
 INSTALL_TARGETS += EXTRA_COMPONENTS
 endif
 endif
 
 ifdef EXTRA_PP_COMPONENTS
 ifndef NO_DIST_INSTALL
 EXTRA_PP_COMPONENTS_PATH := $(FINAL_TARGET)/components
-EXTRA_PP_COMPONENTS_TARGET := misc
 PP_TARGETS += EXTRA_PP_COMPONENTS
 endif
 endif
 
 EXTRA_MANIFESTS = $(filter %.manifest,$(EXTRA_COMPONENTS) $(EXTRA_PP_COMPONENTS))
 ifneq (,$(EXTRA_MANIFESTS))
-misc:: $(call mkdir_deps,$(FINAL_TARGET))
+libs:: $(call mkdir_deps,$(FINAL_TARGET))
 	$(call py_action,buildlist,$(FINAL_TARGET)/chrome.manifest $(patsubst %,'manifest components/%',$(notdir $(EXTRA_MANIFESTS))))
 endif
 
 ################################################################################
 # Copy each element of EXTRA_JS_MODULES to
 # $(FINAL_TARGET)/modules
 FINAL_JS_MODULES_PATH := $(FINAL_TARGET)/modules
 
@@ -1358,19 +1368,19 @@ endif
 
 # See comment above about moving this out of the tools tier.
 ifdef INSTALL_EXTENSION_ID
 ifndef XPI_NAME
 $(error XPI_NAME must be set for INSTALL_EXTENSION_ID)
 endif
 
 tools::
-	$(RM) -r '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
-	$(NSINSTALL) -D '$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
-	$(call copy_dir,$(FINAL_TARGET),$(DIST)/bin$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID))
+	$(RM) -r '$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
+	$(NSINSTALL) -D '$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID)'
+	$(call copy_dir,$(FINAL_TARGET),$(DIST)/bin/distribution$(DIST_SUBDIR:%=/%)/extensions/$(INSTALL_EXTENSION_ID))
 
 endif
 
 #############################################################################
 # MDDEPDIR is the subdirectory where all the dependency files are placed.
 #   This uses a make rule (instead of a macro) to support parallel
 #   builds (-jN). If this were done in the LOOP_OVER_DIRS macro, two
 #   processes could simultaneously try to create the same directory.
@@ -1674,14 +1684,8 @@ include $(topsrcdir)/config/makefiles/au
 ifneq ($(NULL),$(AUTO_DEPS))
   default all libs tools export:: $(AUTO_DEPS)
 endif
 
 export:: $(GENERATED_FILES)
 
 GARBAGE += $(GENERATED_FILES)
 
-# We may have modified "frozen" variables in rules.mk (we do that), but we don't
-# want Makefile.in doing that, so collect the possibly modified variables here,
-# and check them again in recurse.mk, which is always included after Makefile.in
-# contents.
-$(foreach var,$(_MOZBUILD_EXTERNAL_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
-$(foreach var,$(_DEPRECATED_VARIABLES),$(eval $(var)_FROZEN := '$($(var))'))
--- a/editor/ui/dialogs/content/EdInsertMath.js
+++ b/editor/ui/dialogs/content/EdInsertMath.js
@@ -19,22 +19,19 @@ function Startup()
   gDialog.direction = document.getElementById("optionDirection");
   gDialog.input = document.getElementById("input");
   gDialog.output = document.getElementById("output");
 
   // Set initial focus
   gDialog.input.focus();
 
   // Load TeXZilla
-  // TeXZilla.js contains non-ASCII characters and explicitly sets
-  // window.TeXZilla, so we have to specify the charset parameter but don't
-  // need to worry about the targetObj parameter.
   Components.classes["@mozilla.org/moz/jssubscript-loader;1"]
             .getService(Components.interfaces.mozIJSSubScriptLoader)
-            .loadSubScript("chrome://editor/content/TeXZilla.js", {}, "UTF-8");
+            .loadSubScript("chrome://editor/content/TeXZilla.js");
 
   // Verify if the selection is on a <math> and initialize the dialog.
   gDialog.oldMath = editor.getElementOrParentByTagName("math", null);
   if (gDialog.oldMath) {
     // When these attributes are absent or invalid, they default to "inline" and "ltr" respectively.
     gDialog.mode.selectedIndex = gDialog.oldMath.getAttribute("display") == "block" ? 1 : 0;
     gDialog.direction.selectedIndex = gDialog.oldMath.getAttribute("dir") == "rtl" ? 1 : 0;
     gDialog.input.value = TeXZilla.getTeXSource(gDialog.oldMath);
--- a/editor/ui/dialogs/content/EdReplace.xul
+++ b/editor/ui/dialogs/content/EdReplace.xul
@@ -9,17 +9,17 @@
 
 <!DOCTYPE dialog SYSTEM "chrome://editor/locale/EditorReplace.dtd">
 
 <dialog id="replaceDlg" title="&replaceDialog.title;"
    xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    persist="screenX screenY"
    buttons="cancel"
    onload = "onLoad()"
-   ondialogaccept="onFindNext(); return false">
+   ondialogaccept="return onFindNext();">
 
   <!-- Methods common to all editor dialogs -->
   <script type="application/javascript" src="chrome://editor/content/editorUtilities.js"/>
   <script type="application/javascript" src="chrome://editor/content/EdDialogCommon.js"/>
   <script type="application/javascript" src="chrome://editor/content/EdReplace.js"/>
   <stringbundle id="findBundle" src="chrome://global/locale/finddialog.properties"/>
    
   <hbox>
--- a/editor/ui/texzilla/content/TeXZilla.js
+++ b/editor/ui/texzilla/content/TeXZilla.js
@@ -1,815 +1,5347 @@
 /* THIS IS A GENERATED FILE. DO NOT EDIT THIS DIRECTLY. */
 /* 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/. */
 
 "use strict";
 
-var h=!0,n=null,p=!1,u=function(){function t(b){return b.replace(/&/g,"&amp;").replace(/</g,"&lt;").replace(/>/g,"&gt;")}function B(b){b=b.trim();var a=/(-?[0-9]*(?:[0-9]\.?|\.[0-9])[0-9]*)(e[mx]|in|cm|mm|p[xtc]|%)?/.exec(b);if(a)return a[1]=parseFloat(a[1]),a[2]||(a[1]*=100,a[2]="%"),{j:a[1],l:a[2]};b="negativeveryverythinmathspace negativeverythinmathspace negativemediummathspace negativethickmathspace negativeverythickmathspace negativeveryverythickmathspace  veryverythinmathspace verythinmathspace thinmathspace mediummathspace thickmathspace verythickmathspace veryverythickmathspace".split(" ").indexOf(b);
-return{j:(-1===b?0:b-6)/18,l:"em"}}function d(b,a,d){var e="<"+b;d&&(e+=" "+d);return e+(">"+a+"</"+b+">")}function f(b,a,d){var e="<mo";a&&(e+=' lspace="'+a+'"');d&&(e+=' rspace="'+d+'"');return e+=">"+t(b)+"</mo>"}function r(b,a,d,e){return b?!d?"<mover>"+a+e+"</mover>":!e?"<munder>"+a+d+"</munder>":"<munderover>"+a+d+e+"</munderover>":!d?"<msup>"+a+e+"</msup>":!e?"<msub>"+a+d+"</msub>":"<msubsup>"+a+d+e+"</msubsup>"}function k(b,a,d){var e;if(!a){if(1==b.length)return b[0];a="mrow"}e="<"+a;d&&
-(e+=" "+d);return e+=">"+b.join("")+"</"+a+">"}function w(b,a,d){var e='<math xmlns="'+x+'"';a&&(e+=' display="block"');e+="><semantics>"+k(b);e=e+'<annotation encoding="TeX">'+t(d);return e+="</annotation></semantics></math>"}function C(b){if(!b||b.namespaceURI!==x)return n;if("semantics"===b.tagName)for(b=b.firstElementChild;b;b=b.nextElementSibling){if(b.namespaceURI===x&&"annotation"===b.localName&&-1!==D.indexOf(b.getAttribute("encoding")))return b.textContent}else if(1===b.childElementCount)return C(b.firstElementChild);
-return n}function E(b){for(var a="",d,e,g=0;g<b.length;g++)d=b.charCodeAt(g),128>d?a+=b.charAt(g):55296<=d&&56319>=d?(g++,e=b.charCodeAt(g),a+="&#x"+(1024*(d-55296)+e-56320+65536).toString(16)+";"):a+="&#x"+d.toString(16)+";";return a}function F(b){throw Error(b.replace(/\nExpecting [^\n]*$/,"\n"));}function y(){this.f={}}var l={trace:function(){},f:{},la:{error:2,textOptArg:3,"[":4,TEXTOPTARG:5,"]":6,textArg:7,"{":8,TEXTARG:9,"}":10,lengthOptArg:11,lengthArg:12,attrOptArg:13,attrArg:14,tokenContent:15,
-arrayAlign:16,columnAlign:17,collayout:18,COLLAYOUT:19,colalign:20,COLALIGN:21,rowalign:22,ROWALIGN:23,rowspan:24,ROWSPAN:25,colspan:26,COLSPAN:27,align:28,ALIGN:29,eqrows:30,EQROWS:31,eqcols:32,EQCOLS:33,rowlines:34,ROWLINES:35,collines:36,COLLINES:37,frame:38,FRAME:39,padding:40,PADDING:41,cellopt:42,celloptList:43,rowopt:44,arrayopt:45,arrayoptList:46,rowoptList:47,left:48,LEFT:49,OPFS:50,".":51,right:52,RIGHT:53,closedTerm:54,styledExpression:55,BIG:56,BBIG:57,BIGG:58,BBIGG:59,BIGL:60,BBIGL:61,
-BIGGL:62,BBIGGL:63,TEXATOP:64,TEXOVER:65,TEXCHOOSE:66,NUM:67,TEXT:68,A:69,F:70,MI:71,MN:72,MO:73,OP:74,OPS:75,OPAS:76,MS:77,MTEXT:78,HIGH_SURROGATE:79,LOW_SURROGATE:80,BMP_CHARACTER:81,OPERATORNAME:82,MATHOP:83,MATHBIN:84,MATHREL:85,FRAC:86,ROOT:87,SQRT:88,UNDERSET:89,OVERSET:90,UNDEROVERSET:91,XARROW:92,MATHRLAP:93,MATHLLAP:94,MATHCLAP:95,PHANTOM:96,TFRAC:97,BINOM:98,TBINOM:99,PMOD:100,UNDERBRACE:101,UNDERLINE:102,OVERBRACE:103,ACCENT:104,ACCENTNS:105,BOXED:106,SLASH:107,QUAD:108,QQUAD:109,NEGSPACE:110,
-NEGMEDSPACE:111,NEGTHICKSPACE:112,THINSPACE:113,MEDSPACE:114,THICKSPACE:115,SPACE:116,MATHRAISEBOX:117,MATHBB:118,MATHBF:119,MATHBIT:120,MATHSCR:121,MATHBSCR:122,MATHSF:123,MATHFRAK:124,MATHIT:125,MATHTT:126,MATHRM:127,HREF:128,STATUSLINE:129,TOOLTIP:130,TOGGLE:131,BTOGGLE:132,closedTermList:133,ETOGGLE:134,TENSOR:135,subsupList:136,MULTI:137,BMATRIX:138,tableRowList:139,EMATRIX:140,BGATHERED:141,EGATHERED:142,BPMATRIX:143,EPMATRIX:144,BBMATRIX:145,EBMATRIX:146,BVMATRIX:147,EVMATRIX:148,BBBMATRIX:149,
-EBBMATRIX:150,BVVMATRIX:151,EVVMATRIX:152,BSMALLMATRIX:153,ESMALLMATRIX:154,BCASES:155,ECASES:156,BALIGNED:157,EALIGNED:158,BARRAY:159,EARRAY:160,SUBSTACK:161,ARRAY:162,ARRAYOPTS:163,compoundTerm:164,_:165,"^":166,OPP:167,opm:168,OPM:169,FM:170,compoundTermList:171,subsupTermScript:172,subsupTerm:173,textstyle:174,DISPLAYSTYLE:175,TEXTSTYLE:176,TEXTSIZE:177,SCRIPTSIZE:178,SCRIPTSCRIPTSIZE:179,COLOR:180,BGCOLOR:181,tableCell:182,CELLOPTS:183,tableCellList:184,COLSEP:185,tableRow:186,ROWOPTS:187,ROWSEP:188,
-document:189,documentItemList:190,EOF:191,documentItem:192,STARTMATH0:193,ENDMATH0:194,STARTMATH1:195,ENDMATH1:196,STARTMATH2:197,ENDMATH2:198,STARTMATH3:199,ENDMATH3:200,$accept:0,$end:1},B:{2:"error",4:"[",5:"TEXTOPTARG",6:"]",8:"{",9:"TEXTARG",10:"}",19:"COLLAYOUT",21:"COLALIGN",23:"ROWALIGN",25:"ROWSPAN",27:"COLSPAN",29:"ALIGN",31:"EQROWS",33:"EQCOLS",35:"ROWLINES",37:"COLLINES",39:"FRAME",41:"PADDING",49:"LEFT",50:"OPFS",51:".",53:"RIGHT",56:"BIG",57:"BBIG",58:"BIGG",59:"BBIGG",60:"BIGL",61:"BBIGL",
-62:"BIGGL",63:"BBIGGL",64:"TEXATOP",65:"TEXOVER",66:"TEXCHOOSE",67:"NUM",68:"TEXT",69:"A",70:"F",71:"MI",72:"MN",73:"MO",74:"OP",75:"OPS",76:"OPAS",77:"MS",78:"MTEXT",79:"HIGH_SURROGATE",80:"LOW_SURROGATE",81:"BMP_CHARACTER",82:"OPERATORNAME",83:"MATHOP",84:"MATHBIN",85:"MATHREL",86:"FRAC",87:"ROOT",88:"SQRT",89:"UNDERSET",90:"OVERSET",91:"UNDEROVERSET",92:"XARROW",93:"MATHRLAP",94:"MATHLLAP",95:"MATHCLAP",96:"PHANTOM",97:"TFRAC",98:"BINOM",99:"TBINOM",100:"PMOD",101:"UNDERBRACE",102:"UNDERLINE",
-103:"OVERBRACE",104:"ACCENT",105:"ACCENTNS",106:"BOXED",107:"SLASH",108:"QUAD",109:"QQUAD",110:"NEGSPACE",111:"NEGMEDSPACE",112:"NEGTHICKSPACE",113:"THINSPACE",114:"MEDSPACE",115:"THICKSPACE",116:"SPACE",117:"MATHRAISEBOX",118:"MATHBB",119:"MATHBF",120:"MATHBIT",121:"MATHSCR",122:"MATHBSCR",123:"MATHSF",124:"MATHFRAK",125:"MATHIT",126:"MATHTT",127:"MATHRM",128:"HREF",129:"STATUSLINE",130:"TOOLTIP",131:"TOGGLE",132:"BTOGGLE",134:"ETOGGLE",135:"TENSOR",137:"MULTI",138:"BMATRIX",140:"EMATRIX",141:"BGATHERED",
-142:"EGATHERED",143:"BPMATRIX",144:"EPMATRIX",145:"BBMATRIX",146:"EBMATRIX",147:"BVMATRIX",148:"EVMATRIX",149:"BBBMATRIX",150:"EBBMATRIX",151:"BVVMATRIX",152:"EVVMATRIX",153:"BSMALLMATRIX",154:"ESMALLMATRIX",155:"BCASES",156:"ECASES",157:"BALIGNED",158:"EALIGNED",159:"BARRAY",160:"EARRAY",161:"SUBSTACK",162:"ARRAY",163:"ARRAYOPTS",165:"_",166:"^",167:"OPP",169:"OPM",170:"FM",175:"DISPLAYSTYLE",176:"TEXTSTYLE",177:"TEXTSIZE",178:"SCRIPTSIZE",179:"SCRIPTSCRIPTSIZE",180:"COLOR",181:"BGCOLOR",183:"CELLOPTS",
-185:"COLSEP",187:"ROWOPTS",188:"ROWSEP",191:"EOF",193:"STARTMATH0",194:"ENDMATH0",195:"STARTMATH1",196:"ENDMATH1",197:"STARTMATH2",198:"ENDMATH2",199:"STARTMATH3",200:"ENDMATH3"},W:[0,[3,3],[7,3],[11,3],[12,3],[13,1],[14,1],[15,1],[16,1],[17,1],[18,2],[20,2],[22,2],[24,2],[26,2],[28,2],[30,2],[32,2],[34,2],[36,2],[38,2],[40,2],[42,1],[42,1],[42,1],[42,1],[43,1],[43,2],[44,1],[44,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[45,1],[46,1],[46,2],[47,1],[47,2],[48,2],[48,2],[52,
-2],[52,2],[54,2],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,5],[54,5],[54,5],[54,5],[54,5],[54,5],[54,1],[54,1],[54,1],[54,1],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,2],[54,4],[54,2],[54,2],[54,1],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,2],[54,5],[54,3],[54,3],[54,4],[54,5],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,1],[54,
-4],[54,5],[54,4],[54,3],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,2],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,8],[54,7],[54,7],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,3],[54,5],[54,4],[54,4],[54,4],[54,8],[133,1],[133,2],[164,3],[164,5],[164,4],[164,5],[164,4],[164,3],[164,3],[164,2],[164,1],[164,5],[164,5],[164,3],[164,3],[164,1],[168,1],[168,1],[171,1],[171,2],[172,1],[172,1],[173,4],[173,2],[173,2],[173,3],[136,1],[136,2],[174,1],[174,1],
-[174,1],[174,1],[174,1],[174,2],[174,2],[55,2],[55,1],[182,0],[182,5],[182,1],[184,1],[184,3],[186,5],[186,1],[139,1],[139,3],[189,2],[190,1],[190,2],[192,1],[192,2],[192,3],[192,2],[192,3],[192,3],[192,3]],I:function(b,a,G,e,g,c){b=c.length-1;switch(g){case 1:this.b=c[b-1].replace(/\\[\\\]]/g,function(a){return a.slice(1)});this.b=t(this.b);break;case 2:this.b=c[b-1].replace(/\\[\\\}]/g,function(a){return a.slice(1)});this.b=t(this.b);break;case 3:this.b=B(c[b-1]);break;case 4:this.b=B(c[b-1]);break;
-case 5:this.b='"'+c[b].replace(/"/g,"&#x22;")+'"';break;case 6:this.b='"'+c[b].replace(/"/g,"&#x22;")+'"';break;case 7:this.b=c[b].replace(/\s+/g," ").replace(/^ | $/g," ");break;case 8:c[b]=c[b].trim();if("t"===c[b])this.b="axis 1";else if("c"===c[b])this.b="center";else if("b"===c[b])this.b="axis -1";else throw"Unknown array alignment";break;case 9:this.b="";c[b]=c[b].replace(/\s+/g,"");for(e=0;e<c[b].length;e++)"c"===c[b][e]?this.b+=" center":"l"===c[b][e]?this.b+=" left":"r"===c[b][e]&&(this.b+=
-" right");if(this.b.length)this.b=this.b.slice(1);else throw"Invalid column alignments";break;case 10:this.b="columnalign="+c[b];break;case 11:this.b="columnalign="+c[b];break;case 12:this.b="rowalign="+c[b];break;case 13:this.b="rowspan="+c[b];break;case 14:this.b="colspan="+c[b];break;case 15:this.b="align="+c[b];break;case 16:this.b="equalrows="+c[b];break;case 17:this.b="equalcolumns="+c[b];break;case 18:this.b="rowlines="+c[b];break;case 19:this.b="columnlines="+c[b];break;case 20:this.b="frame="+
-c[b];break;case 21:this.b="rowspacing="+c[b]+" columnspacing="+c[b];break;case 22:this.b=c[b];break;case 23:this.b=c[b];break;case 24:this.b=c[b];break;case 25:this.b=c[b];break;case 26:this.b=c[b];break;case 27:this.b=c[b-1]+" "+c[b];break;case 28:this.b=c[b];break;case 29:this.b=c[b];break;case 30:this.b=c[b];break;case 31:this.b=c[b];break;case 32:this.b=c[b];break;case 33:this.b=c[b];break;case 34:this.b=c[b];break;case 35:this.b=c[b];break;case 36:this.b=c[b];break;case 37:this.b=c[b];break;
-case 38:this.b=c[b];break;case 39:this.b=c[b];break;case 40:this.b=c[b];break;case 41:this.b=c[b-1]+" "+c[b];break;case 42:this.b=c[b];break;case 43:this.b=c[b-1]+" "+c[b];break;case 44:this.b=f(c[b]);break;case 45:this.b="";break;case 46:this.b=f(c[b]);break;case 47:this.b="";break;case 48:this.b="<mrow/>";break;case 49:this.b=k(c[b-1]);break;case 50:this.b=d("mo",c[b],'maxsize="1.2em" minsize="1.2em"');break;case 51:this.b=d("mo",c[b],'maxsize="1.8em" minsize="1.8em"');break;case 52:this.b=d("mo",
-c[b],'maxsize="2.4em" minsize="2.4em"');break;case 53:this.b=d("mo",c[b],'maxsize="3em" minsize="3em"');break;case 54:this.b=d("mo",c[b],'maxsize="1.2em" minsize="1.2em"');break;case 55:this.b=d("mo",c[b],'maxsize="1.8em" minsize="1.8em"');break;case 56:this.b=d("mo",c[b],'maxsize="2.4em" minsize="2.4em"');break;case 57:this.b=d("mo",c[b],'maxsize="3em" minsize="3em"');break;case 58:this.b=d("mrow",c[b-2]+k(c[b-1])+c[b]);break;case 59:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');break;
-case 60:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",c[b-4]+this.b+c[b-2]);break;case 61:this.b=d("mfrac",k(c[b-3])+k(c[b-1]));break;case 62:this.b=d("mfrac",k(c[b-3])+k(c[b-1]));this.b=d("mrow",c[b-4]+this.b+c[b-2]);break;case 63:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",f("(")+this.b+f(")"));break;case 64:this.b=d("mfrac",k(c[b-3])+k(c[b-1]),'linethickness="0"');this.b=d("mrow",c[b-4]+this.b+c[b-2]);this.b=d("mrow",f("(")+this.b+f(")"));
-break;case 65:this.b=d("mn",c[b]);break;case 66:this.b=d("mtext",c[b]);break;case 67:this.b=d("mi",t(c[b]));break;case 68:this.b=f(c[b],"0em","0em");break;case 69:this.b=d("mi",c[b]);break;case 70:this.b=d("mn",c[b]);break;case 71:this.b=f(c[b]);break;case 72:this.b=f(c[b]);break;case 73:this.b=f(c[b]);break;case 74:this.b=d("mo",c[b],'stretchy="false"');break;case 75:this.b=d("mo",c[b],'stretchy="false"');break;case 76:this.b=d("mo",c[b],'stretchy="false"');break;case 77:this.b=d("ms",c[b]);break;
-case 78:this.b=d("ms",c[b],"lquote="+c[b-2]+" rquote="+c[b-1]);break;case 79:this.b=d("mtext",c[b]);break;case 80:this.b=d("mtext",c[b-1]+c[b]);break;case 81:this.b=d("mtext",c[b]);break;case 82:this.b=f(c[b],"0em","thinmathspace");break;case 83:this.b=f(c[b],"thinmathspace","thinmathspace");break;case 84:this.b=f(c[b],"mediummathspace","mediummathspace");break;case 85:this.b=f(c[b],"thickmathspace","thickmathspace");break;case 86:this.b=d("mfrac",c[b-1]+c[b]);break;case 87:this.b=d("mroot",c[b]+
-c[b-1]);break;case 88:this.b=d("msqrt",c[b]);break;case 89:this.b=d("mroot",c[b]+k(c[b-2]));break;case 90:this.b=d("munder",c[b]+c[b-1]);break;case 91:this.b=d("mover",c[b]+c[b-1]);break;case 92:this.b=d("munderover",c[b]+c[b-2]+c[b-1]);break;case 93:this.