[tor-commits] [tor-messenger-build/master] Rebase Instantbird patches for ESR52

sukhbir at torproject.org sukhbir at torproject.org
Mon Jul 31 14:49:38 UTC 2017


commit b616cd695a39a8de3293ca35e3cee8bd9333f11a
Author: Sukhbir Singh <sukhbir at torproject.org>
Date:   Fri Jul 28 15:53:39 2017 -0400

    Rebase Instantbird patches for ESR52
---
 .../0001-Set-Tor-Messenger-preferences.patch       |  145 +-
 ...c-21634-Autologin-default-should-be-false.patch |   12 +-
 ...Support-Special-Characters-input-prompt-o.patch |   78 -
 ....patch => 0003-XMPP-in-band-registration.patch} |   48 +-
 ...m-UI.patch => 0004-Remove-search-from-UI.patch} |   10 +-
 ...Better-error-reporting-for-failed-outgoin.patch |   67 -
 ...patch => 0005-Add-Tor-Messenger-branding.patch} |   80 +-
 .../0005-Trac-13312-OTR-over-Twitter-DMs.patch     |  766 -------
 ...-Fix-tab-strip-background-colour-on-OS-X..patch |   26 -
 ...e-option-for-configuring-account-picture.patch} |    8 +-
 ...-XMPP-createConversation-should-handle-in.patch |   26 -
 ...tch => 0007-Modify-top-protocol-defaults.patch} |   29 +-
 ...faults.patch => 0008-Modify-IRC-defaults.patch} |   12 +-
 .../0009-Do-not-set-default-XMPP-server.patch      |   25 +
 ...odify-themes.patch => 0010-Modify-themes.patch} |   14 +-
 ...gging-UI.patch => 0011-Remove-logging-UI.patch} |    8 +-
 ...ert-override.patch => 0012-Cert-override.patch} |   18 +-
 ...tch => 0013-Display-all-traffic-over-Tor.patch} |   12 +-
 ...nk.patch => 0014-Trac-17480-Content-sink.patch} |   10 +-
 .../instantbird/0015-Modify-XMPP-defaults.patch    |   48 -
 ...ch => 0015-SASL-ECDSA-NIST256P-CHALLENGE.patch} |   14 +-
 ...Use-built-in-functions-instead-of-an-svg.patch} |   28 +-
 ...Add-a-pref-to-disable-JavaScript-in-brow.patch} |   18 +-
 ...517-Use-different-color-for-Add-Exception.patch |   23 +
 ...1736-Hide-account-timestamp-from-message.patch} |   10 +-
 ...wed-duplicated-files-for-Windows-and-Linu.patch |   98 +
 ...-msg-is-not-defined-error-in-irc.js-chang.patch |   29 -
 ...Contact-list-entries-should-adapt-their-h.patch |  322 ---
 ...1187281-Only-show-close-button-on-Windows.patch |   25 -
 ...-Remove-old-Yahoo-Messenger-support.-r-al.patch | 2398 --------------------
 ...517-Use-different-color-for-Add-Exception.patch |   25 -
 ...-Add-duplicated-files-to-allowed-dupes.mn.patch |   29 -
 projects/instantbird/config                        |   46 +-
 33 files changed, 409 insertions(+), 4098 deletions(-)

diff --git a/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch b/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch
index 9a72cd6..63dab5d 100644
--- a/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch
+++ b/projects/instantbird/0001-Set-Tor-Messenger-preferences.patch
@@ -1,19 +1,19 @@
-From 8db9ea380fb0d2b54bb3dd6d6003532d13d2c2bf Mon Sep 17 00:00:00 2001
+From 54583578a3e2753cd5fee169596325fa761d5554 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Mon, 10 Oct 2016 19:48:41 -0700
-Subject: [PATCH 01/28] Set Tor Messenger preferences
+Date: Wed, 26 Jul 2017 14:30:41 -0400
+Subject: [PATCH 01/20] Set Tor Messenger preferences
 
 ---
- im/app/profile/all-instantbird.js | 424 ++++++++++++++++++++++++++++++++++++--
- 1 file changed, 402 insertions(+), 22 deletions(-)
+ im/app/profile/all-instantbird.js | 451 ++++++++++++++++++++++++++++++++++++--
+ 1 file changed, 429 insertions(+), 22 deletions(-)
 
 diff --git a/im/app/profile/all-instantbird.js b/im/app/profile/all-instantbird.js
-index b7a397017..89593abeb 100644
+index 127c86a662..454ca7ea1b 100644
 --- a/im/app/profile/all-instantbird.js
 +++ b/im/app/profile/all-instantbird.js
 @@ -1,3 +1,53 @@
 +/**
-+ * This file is divded into three section,
++ * This file is divided into three section,
 + *
 + * 1) Tor Messenger prefs, not found in the next two sections;
 + * 2) The original Instantbird prefs found here, modified by TM;
@@ -115,7 +115,7 @@ index b7a397017..89593abeb 100644
  
  // Interval: Time before prompting the user to restart to install the latest
  //           download (in seconds) default=30 minutes
-@@ -202,7 +249,7 @@ pref("browser.search.order.1",                "chrome://instantbird/locale/regio
+@@ -195,7 +242,7 @@ pref("browser.search.order.1",                "chrome://instantbird/locale/regio
  pref("browser.search.order.2",                "chrome://instantbird/locale/region.properties");
  
  // send ping to the server to update
@@ -124,7 +124,7 @@ index b7a397017..89593abeb 100644
  
  // disable logging for the search service update system by default
  pref("browser.search.update.log", false);
-@@ -222,10 +269,10 @@ pref("extensions.ignoreMTimeChanges", false);
+@@ -235,10 +282,10 @@ pref("extensions.ignoreMTimeChanges", false);
  pref("extensions.logging.enabled", false);
  pref("general.skins.selectedSkin", "classic/1.0");
  
@@ -137,24 +137,17 @@ index b7a397017..89593abeb 100644
  
  // Preferences for the Get Add-ons pane
  pref("extensions.getAddons.cache.enabled", false);
-@@ -244,10 +291,24 @@ pref("extensions.getMoreMessageStylesURL", "https://add-ons.instantbird.org/%LOC
- pref("extensions.getMoreEmoticonsURL", "https://add-ons.instantbird.org/%LOCALE%/%APP%/%VERSION%/emoticons/");
- pref("extensions.getMoreProtocolsURL", "https://add-ons.instantbird.org/%LOCALE%/%APP%/%VERSION%/protocols/");
+@@ -265,16 +312,16 @@ pref("plugins.click_to_play", false);
+ pref("plugin.default.state", 0);
  
-+// Click-to-play has not been ported yet, see bug 814168.
-+// The default plugin state should be changed to "ask to activate" when this
-+// has been done.
-+pref("plugins.click_to_play", false);
-+// Disable by default.
-+pref("plugin.default.state", 0);
-+
-+// Plugins bundled in XPIs are enabled by default.
+ // Plugins bundled in XPIs are enabled by default.
+-pref("plugin.defaultXpi.state", 2);
 +pref("plugin.defaultXpi.state", 0);
-+
-+// Flash and Java disabled by default.
-+pref("plugin.state.flash", 0);
-+pref("plugin.state.java", 0);
-+
+ 
+ // Flash and Java disabled by default.
+ pref("plugin.state.flash", 0);
+ pref("plugin.state.java", 0);
+ 
  // suppress external-load warning for standard browser schemes
 -pref("network.protocol-handler.warn-external.http", false);
 -pref("network.protocol-handler.warn-external.https", false);
@@ -165,7 +158,7 @@ index b7a397017..89593abeb 100644
  
  // don't load links inside Instantbird
  pref("network.protocol-handler.expose-all", false);
-@@ -259,13 +320,13 @@ pref("network.protocol-handler.expose.https", true);
+@@ -286,13 +333,13 @@ pref("network.protocol-handler.expose.https", true);
  
  // expose javascript: so that message themes can use it.
  // javascript: links inside messages are filtered out.
@@ -182,7 +175,7 @@ index b7a397017..89593abeb 100644
  
  // We have an Error Console menu item by default so let's display chrome errors
  pref("javascript.options.showInConsole", true);
-@@ -300,14 +361,333 @@ pref("browser.tabs.tabClipWidth", 140);
+@@ -327,7 +374,7 @@ pref("browser.tabs.tabClipWidth", 140);
  // 3  at the end of the tabstrip
  pref("browser.tabs.closeButtons", 1);
  
@@ -191,11 +184,8 @@ index b7a397017..89593abeb 100644
  
  pref("chat.twitter.consumerKey", "TSuyS1ieRAkB3qWv8yyEw");
  pref("chat.twitter.consumerSecret", "DKtKaSf5a7pBNhdBsSZHTnI5Y03hRlPFYWmb4xXBlkU");
- 
- // Comma separated list of prpl ids that should use libpurple even if there is
- // a JS implementation. This is used to land JS-prpls pref'ed off in nightlies.
--pref("chat.prpls.forcePurple", "prpl-jabber");
-+pref("chat.prpls.forcePurple", "");
+@@ -337,4 +384,364 @@ pref("chat.twitter.consumerSecret", "DKtKaSf5a7pBNhdBsSZHTnI5Y03hRlPFYWmb4xXBlkU
+ pref("chat.prpls.forcePurple", "");
  
  // Whether to parse log files for conversation statistics.
 -pref("statsService.parseLogsForStats", true);
@@ -210,7 +200,7 @@ index b7a397017..89593abeb 100644
 +// Please maintain unit tests at ./tbb-tests/browser_tor_TB4.js
 +
 +// Disable initial homepage notifications
-+//pref("browser.search.update", false);  // TM
++//pref("browser.search.update", false); // TM
 +pref("browser.rights.3.shown", true);
 +pref("startup.homepage_welcome_url", "");
 +pref("startup.homepage_welcome_url.additional", "");
@@ -234,6 +224,10 @@ index b7a397017..89593abeb 100644
 +pref("app.update.staging.enabled", false);
 +#endif
 +
++// No need to contact the Kinto-based blocklist system in addition to the old
++// one which is still used, see bug 22071.
++pref("services.blocklist.update_enabled", false);
++
 +// Disable "Slow startup" warnings and associated disk history
 +// (bug #13346)
 +pref("browser.slowStartup.notificationDisabled", true);
@@ -251,7 +245,7 @@ index b7a397017..89593abeb 100644
 +pref("permissions.memory_only", true);
 +pref("network.cookie.lifetimePolicy", 2);
 +pref("browser.download.manager.retention", 1);
-+pref("security.nocertdb", false);  // TM
++pref("security.nocertdb", false); // TM
 +
 +// Disk activity: TBB Directory Isolation
 +pref("browser.download.useDownloadDir", false);
@@ -272,6 +266,17 @@ index b7a397017..89593abeb 100644
 +pref("browser.search.suggest.enabled", false);
 +pref("browser.safebrowsing.enabled", false);
 +pref("browser.safebrowsing.malware.enabled", false);
++pref("browser.safebrowsing.phishing.enabled", false);
++pref("browser.safebrowsing.downloads.enabled", false);
++pref("browser.safebrowsing.downloads.remote.enabled", false);
++pref("browser.safebrowsing.blockedURIs.enabled", false);
++pref("browser.safebrowsing.downloads.remote.url", "");
++pref("browser.safebrowsing.provider.google.updateURL", "");
++pref("browser.safebrowsing.provider.google.gethashURL", "");
++pref("browser.safebrowsing.provider.google4.updateURL", "");
++pref("browser.safebrowsing.provider.google4.gethashURL", "");
++pref("browser.safebrowsing.provider.mozilla.updateURL", "");
++pref("browser.safebrowsing.provider.mozilla.gethashURL", "");
 +pref("browser.download.manager.scanWhenDone", false); // prevents AV remote reporting of downloads
 +pref("extensions.ui.lastCategory", "addons://list/extension");
 +pref("datareporting.healthreport.service.enabled", false); // Yes, all three of these must be set
@@ -285,10 +290,11 @@ index b7a397017..89593abeb 100644
 +pref("browser.selfsupport.enabled", false);
 +pref("browser.selfsupport.url", "");
 +pref("toolkit.telemetry.unified", false);
++// No experiments, use Tor Browser. See 21797.
++pref("experiments.enabled", false);
 +// Disable the UITour backend so there is no chance that a remote page
 +// can use it to confuse Tor Browser users.
 +pref("browser.uitour.enabled", false);
-+pref("security.mixed_content.block_active_content", false); // Disable until https://bugzilla.mozilla.org/show_bug.cgi?id=878890 is patched
 +pref("browser.syncPromoViewsLeftMap", "{\"addons\":0, \"passwords\":0, \"bookmarks\":0}"); // Don't promote sync
 +pref("services.sync.engine.prefs", false); // Never sync prefs, addons, or tabs with other browsers
 +pref("services.sync.engine.addons", false);
@@ -300,6 +306,7 @@ index b7a397017..89593abeb 100644
 +pref("browser.newtabpage.enhanced", false); // Bug 16316 - Avoid potential confusion over tiles for now.
 +pref("browser.newtabpage.introShown", true); // Bug 16316 - Avoid potential confusion over tiles for now.
 +pref("browser.newtabpage.preload", false); // Bug 16316 - Avoid potential confusion over tiles for now.
++pref("browser.newtabpage.remote", false); // Bug 21685: Disable remote new tab pages
 +pref("browser.search.countryCode", "US"); // The next three prefs disable GeoIP search lookups (#16254)
 +pref("browser.search.region", "US");
 +pref("browser.search.geoip.url", "");
@@ -310,19 +317,28 @@ index b7a397017..89593abeb 100644
 +pref("browser.pocket.enabled", false);
 +pref("browser.pocket.api", "");
 +pref("browser.pocket.site", "");
++pref("network.http.referer.hideOnionSource", true);
++
++// Disable Social API and related stuff (Bug #13612)
++pref("social.directories", "");
++pref("social.remote-install.enabled", false);
++pref("social.share.activationPanelEnabled", false);
++pref("social.shareDirectory", "");
++pref("social.toast-notifications.enabled", false);
++pref("social.whitelist", "");
 +
 +// Fingerprinting
 +pref("webgl.min_capability_mode", true);
 +pref("webgl.disable-extensions", true);
 +pref("webgl.disable-fail-if-major-performance-caveat", true);
-+pref("dom.battery.enabled", false); // fingerprinting due to differing OS implementations
++pref("webgl.enable-webgl2", false);
 +pref("dom.network.enabled",false); // fingerprinting due to differing OS implementations
 +pref("gfx.downloadable_fonts.fallback_delay", -1);
 +pref("general.appname.override", "Netscape");
 +pref("general.appversion.override", "5.0 (Windows)");
 +pref("general.oscpu.override", "Windows NT 6.1");
 +pref("general.platform.override", "Win32");
-+pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:45.0) Gecko/20100101 Firefox/45.0");
++pref("general.useragent.override", "Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0");
 +pref("general.productSub.override", "20100101");
 +pref("general.buildID.override", "20100101");
 +pref("browser.startup.homepage_override.buildID", "20100101");
@@ -353,15 +369,19 @@ index b7a397017..89593abeb 100644
 +pref("browser.reader.detectedFirstArticle", true);
 +pref("reader.parse-on-load.enabled", false);
 +pref("privacy.use_utc_timezone", false);  // TM
++pref("media.webspeech.synth.enabled", false); // Bug 10283: Disable SpeechSynthesis API
++pref("dom.webaudio.enabled", false); // Bug 13017: Disable Web Audio API
++pref("dom.maxHardwareConcurrency", 1); // Bug 21675: Spoof single-core cpu
++pref("dom.w3c_touch_events.enabled", 0); // Bug 10286: Always disable Touch API
 +
 +// Third party stuff
-+//pref("network.cookie.cookieBehavior", 1);  // TM
++//pref("network.cookie.cookieBehavior", 1); // TM
 +pref("security.enable_tls_session_tickets", false);
 +pref("network.http.spdy.enabled", false); // Stores state and may have keepalive issues (both fixable)
 +pref("network.http.spdy.enabled.v2", false); // Seems redundant, but just in case
 +pref("network.http.spdy.enabled.v3", false); // Seems redundant, but just in case
 +pref("network.http.spdy.enabled.v3-1", false); // Seems redundant, but just in case
-+pref("privacy.thirdparty.isolate", 0); // Always enforce third party isolation  // TM
++pref("privacy.firstparty.isolate", true); // Always enforce first party isolation
 +pref("network.http.spdy.enabled.http2", false); // Temporarily disabled pending implementation review
 +pref("network.http.spdy.enabled.http2draft", false); // Temporarily disabled pending implementation review
 +pref("network.predictor.enabled", false); // Temporarily disabled. See https://bugs.torproject.org/16633
@@ -370,14 +390,14 @@ index b7a397017..89593abeb 100644
 +
 +// Proxy and proxy security
 +pref("network.proxy.socks", "127.0.0.1");
-+pref("network.proxy.socks_port", 9152);  // TM
++pref("network.proxy.socks_port", 9152);   // TM
 +pref("network.proxy.socks_version", 5);  // TM
 +pref("network.proxy.socks_remote_dns", true);
 +pref("network.proxy.no_proxies_on", ""); // For fingerprinting and local service vulns (#10419)
 +pref("network.proxy.type", 1);
 +pref("network.security.ports.banned", "9050,9051,9150,9151");
 +pref("network.dns.disablePrefetch", true);
-+//pref("network.protocol-handler.external-default", false);  // TM
++//pref("network.protocol-handler.external-default", false); // TM
 +//pref("network.protocol-handler.external.mailto", false);  // TM
 +pref("network.protocol-handler.external.news", false);
 +pref("network.protocol-handler.external.nntp", false);
@@ -400,12 +420,19 @@ index b7a397017..89593abeb 100644
 +// clever solution for https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=769716.
 +pref("media.gmp-provider.enabled", false);
 +pref("media.gmp-manager.url.override", "data:text/plain,");
-+// EME prefs: Strictly speaking these prefs don't need to be set as we are
-+// using the --disable-eme compile flag. However, in order to not confuse users,
-+// who might stumble upon them while looking into about:config, we set them to
-+// 'false' communicating that EME is really disabled.
++// Since ESR52 it is not enough anymore to block pinging the GMP update/download
++// server. There is a local fallback that must be blocked now as well. See:
++// https://bugzilla.mozilla.org/show_bug.cgi?id=1267495.
++pref("media.gmp-manager.updateEnabled", false);
++// Mozilla is relying on preferences to make sure no DRM blob is downloaded and
++// run. Even though those prefs should be set correctly by specifying
++// --disable-eme (which we do), we disable all of them here as well for defense
++// in depth.
 +pref("browser.eme.ui.enabled", false);
++pref("media.gmp-eme-adobe.visible", false);
 +pref("media.gmp-eme-adobe.enabled", false);
++pref("media.gmp-widevinecdm.visible", false);
++pref("media.gmp-widevinecdm.enabled", false);
 +pref("media.eme.enabled", false);
 +pref("media.eme.apiVisible", false);
 +// WebIDE can bypass proxy settings for remote debugging. It also downloads
@@ -418,10 +445,6 @@ index b7a397017..89593abeb 100644
 +// restrictive DNS look-up policy. We use "127.0.0.1" instead of "localhost" as
 +// a workaround. See bug 16523 for more details.
 +pref("devtools.debugger.chrome-debugging-host", "127.0.0.1");
-+// Don't show the "Open with" option on the download dialog if the preference
-+// is |true|. This helps to avoid confusion e.g. in case the browser is
-+// sandboxed. See bug 17502 for details.
-+pref("browser.download.forbid_open_with", false);
 +// Disable mozTCPSocket for sure (bug 18863)
 +pref("dom.mozTCPSocket.enabled", false);
 +
@@ -431,6 +454,9 @@ index b7a397017..89593abeb 100644
 +// Until we address at least the linkability concerns in #19417 let's disable
 +// asmjs.
 +pref("javascript.options.asmjs", false);
++// Mozilla keeps still finding critical bugs in Graphite code. Disable it for
++// now, see bug 21726.
++pref("gfx.font_rendering.graphite.enabled", false);
 +
 +// Network and performance
 +pref("network.http.pipelining", true);
@@ -447,11 +473,8 @@ index b7a397017..89593abeb 100644
 +pref("network.http.pipelining.max-optimistic-requests", 3);
 +pref("security.ssl.disable_session_identifiers", true);
 +pref("network.manage-offline-status", false);
-+
-+// Disable Xrender as it causes serious performance regressions on some machines
-+// and is disabled in Firefox >= 47 anyway.
-+pref("gfx.xrender.enabled",false);
-+
++// No need to leak things to Mozilla, see bug 21790
++pref("network.captive-portal-service.enabled", false);
 +// As a "defense in depth" measure, configure an empty push server URL (the
 +// DOM Push features are disabled by default via other prefs).
 +pref("dom.push.serverURL", "");
@@ -473,7 +496,7 @@ index b7a397017..89593abeb 100644
 +
 +// Putting the search engine prefs into this file to fix #11236.
 +// Default search engine
-+//pref("browser.search.defaultenginename", "DuckDuckGo");  // TM
++//pref("browser.search.defaultenginename", "data:text/plain,browser.search.defaultenginename=DuckDuckGo");  // TM
 +// Make sure we use the same search engine regardless of locale
 +pref("browser.search.geoSpecificDefaults", false);
 +
@@ -482,7 +505,7 @@ index b7a397017..89593abeb 100644
 +// two search engines as below. See
 +// https://bugzilla.mozilla.org/show_bug.cgi?id=1126722 for details.
 +//pref("browser.search.order.extra.1", "DuckDuckGo");  // TM
-+//pref("browser.search.order.extra.2", "YouTube");  // TM
++//pref("browser.search.order.extra.2", "YouTube"); // TM
 +
 +// Hacks/workarounds: Direct2D seems to crash w/ lots of video cards w/ MinGW?
 +// Nvida cards also experience crashes without the second pref set to disabled
@@ -508,9 +531,17 @@ index b7a397017..89593abeb 100644
 +// Enforce certificate pinning, see: https://bugs.torproject.org/16206
 +pref("security.cert_pinning.enforcement_level", 2);
 +
++// Don't allow MitM via Microsoft Family Safety, see bug 21686
++pref("security.family_safety.mode", 0);
++
 +// Enforce SHA1 deprecation, see: bug 18042.
 +pref("security.pki.sha1_enforcement_level", 2);
 +
++// Avoid report TLS errors to Mozilla. We might want to repurpose this feature
++// one day to help detecting bad relays (which is bug 19119). For now we just
++// hide the checkbox, see bug 22072.
++pref("security.ssl.errorReporting.enabled", false);
++
 +// Workaround for https://bugs.torproject.org/13579. Progress on
 +// `about:downloads` is only shown if the following preference is set to `true`
 +// in case the download panel got removed from the toolbar.
@@ -520,5 +551,5 @@ index b7a397017..89593abeb 100644
 +#expand pref("torbrowser.version", __TOR_BROWSER_VERSION__);
 +#endif
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0002-Trac-21634-Autologin-default-should-be-false.patch b/projects/instantbird/0002-Trac-21634-Autologin-default-should-be-false.patch
index a428a00..b075186 100644
--- a/projects/instantbird/0002-Trac-21634-Autologin-default-should-be-false.patch
+++ b/projects/instantbird/0002-Trac-21634-Autologin-default-should-be-false.patch
@@ -1,7 +1,7 @@
-From 4b44c103a9b4c7a35ce9157bb671a2937a0111e1 Mon Sep 17 00:00:00 2001
+From d6d5054c6dd1aaa01d14729ebcbd423dec2146b7 Mon Sep 17 00:00:00 2001
 From: Arlo Breault <arlolra at gmail.com>
 Date: Mon, 16 Nov 2015 20:37:53 -0800
-Subject: [PATCH 02/28] Trac 21634: Autologin default should be false
+Subject: [PATCH 02/20] Trac 21634: Autologin default should be false
 
 ---
  chat/components/src/imAccounts.js | 2 +-
@@ -9,7 +9,7 @@ Subject: [PATCH 02/28] Trac 21634: Autologin default should be false
  2 files changed, 2 insertions(+), 2 deletions(-)
 
 diff --git a/chat/components/src/imAccounts.js b/chat/components/src/imAccounts.js
-index c13c6100d..5bfea57f2 100644
+index 02cca923c0..a1bf1a803f 100644
 --- a/chat/components/src/imAccounts.js
 +++ b/chat/components/src/imAccounts.js
 @@ -588,7 +588,7 @@ imAccount.prototype = {
@@ -22,10 +22,10 @@ index c13c6100d..5bfea57f2 100644
        autoLogin = this.prefBranch.getBoolPref(kPrefAccountAutoLogin);
      } catch (e) { }
 diff --git a/im/content/accountWizard.xul b/im/content/accountWizard.xul
-index 5fa5b8293..f0933af7f 100644
+index d51df3225c..904d22ba57 100644
 --- a/im/content/accountWizard.xul
 +++ b/im/content/accountWizard.xul
-@@ -138,7 +138,7 @@
+@@ -139,7 +139,7 @@
        <rows id="summaryRows"/>
      </grid>
      <separator/>
@@ -35,5 +35,5 @@ index 5fa5b8293..f0933af7f 100644
  
  </wizard>
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch b/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch
deleted file mode 100644
index af29c25..0000000
--- a/projects/instantbird/0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch
+++ /dev/null
@@ -1,78 +0,0 @@
-From 5eec6f52c78cb09a1e4c4501a95e34ffe21d0d14 Mon Sep 17 00:00:00 2001
-From: aleth <aleth at instantbird.org>
-Date: Sat, 30 Jan 2016 20:56:38 +0100
-Subject: [PATCH 03/28] Trac 17896: Support "Special Characters" input prompt
- on OS X
-
- * Bug 1151784 - Add Edit menu to the conversation window on OS X. r=nhnt11,florian
-
-   Adding an edit menu also enables the emoji panel and dictation.
----
- im/content/instantbird.xul | 23 ++++++++++++++++++++++-
- im/content/menus.xul       |  2 +-
- im/content/menus.xul.inc   |  2 ++
- 3 files changed, 25 insertions(+), 2 deletions(-)
-
-diff --git a/im/content/instantbird.xul b/im/content/instantbird.xul
-index 15a3f988b..d20892198 100644
---- a/im/content/instantbird.xul
-+++ b/im/content/instantbird.xul
-@@ -48,7 +48,28 @@
-   <script type="application/javascript" src="chrome://instantbird/content/nsContextMenu.js"/>
- 
- #ifdef XP_MACOSX
--#include menus.xul.inc
-+# As menus.xul.inc, but with an Edit menu.
-+  <commandset id="maincommandset"/>
-+  <keyset id="mainkeyset"/>
-+  <menubar id="blistMenubar">
-+    <menu id="menu_edit">
-+      <menupopup id="menu_editpopup">
-+        <menuitem id="menu_undo"/>
-+        <menuitem id="menu_redo"/>
-+        <menuseparator/>
-+        <menuitem id="menu_cut"/>
-+        <menuitem id="menu_copy"/>
-+        <menuitem id="menu_paste"/>
-+        <menuitem id="menu_delete"/>
-+        <menuseparator/>
-+        <menuitem id="menu_selectAll"/>
-+        <menuseparator/>
-+        <menuitem id="menu_find"/>
-+        <menuitem id="menu_findAgain"/>
-+      </menupopup>
-+    </menu>
-+  </menubar>
-+  <popupset id="mainPopupSet"/>
- #endif
- 
-   <commandset id="conversationsCommands">
-diff --git a/im/content/menus.xul b/im/content/menus.xul
-index 0889ce87d..894ef13c4 100644
---- a/im/content/menus.xul
-+++ b/im/content/menus.xul
-@@ -43,7 +43,7 @@
-   </keyset>
- 
-   <menubar id="blistMenubar">
--    <menu label="&file.menu;" id="fileMenu" accesskey="&file.accesskey;">
-+    <menu label="&file.menu;" id="fileMenu" accesskey="&file.accesskey;" insertbefore="menu_edit">
-       <menupopup id="fileMenuPopup" onpopupshowing="menus.updateFileMenuitems();">
-         <menuitem id="addBuddyMenuItem" label="&addContact;" command="cmd_addbuddy" key="addBuddykey" accesskey="&addContact.accesskey;"/>
-         <menuitem id="newTabMenuItem" label="&newtab;" command="cmd_newtab" key="newtabkey" accesskey="&newtab.accesskey;"/>
-diff --git a/im/content/menus.xul.inc b/im/content/menus.xul.inc
-index 30aeb1fc5..14fc9e8f6 100644
---- a/im/content/menus.xul.inc
-+++ b/im/content/menus.xul.inc
-@@ -2,6 +2,8 @@
- # 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/.
- 
-+# Note instantbird.xul contains a modified copy of this file that
-+# should be kept in sync.
-   <commandset id="maincommandset"/>
-   <keyset id="mainkeyset"/>
-   <menubar id="blistMenubar"/>
--- 
-2.12.2
-
diff --git a/projects/instantbird/0008-XMPP-in-band-registration.patch b/projects/instantbird/0003-XMPP-in-band-registration.patch
similarity index 93%
rename from projects/instantbird/0008-XMPP-in-band-registration.patch
rename to projects/instantbird/0003-XMPP-in-band-registration.patch
index 096e648..bf68dac 100644
--- a/projects/instantbird/0008-XMPP-in-band-registration.patch
+++ b/projects/instantbird/0003-XMPP-in-band-registration.patch
@@ -1,7 +1,7 @@
-From a1de4a4aaedf227494a80f91bfa8edbf15547e49 Mon Sep 17 00:00:00 2001
+From d4e57e5009a5c14ddec53518352862d0fbc5aeb9 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Mon, 10 Oct 2016 18:42:25 -0700
-Subject: [PATCH 08/28] XMPP in-band registration
+Date: Wed, 26 Jul 2017 15:09:40 -0400
+Subject: [PATCH 03/20] XMPP in-band registration
 
 ---
  chat/locales/en-US/xmpp.properties                 |   5 +
@@ -17,7 +17,7 @@ Subject: [PATCH 08/28] XMPP in-band registration
  create mode 100644 im/content/xmppRegister.xul
 
 diff --git a/chat/locales/en-US/xmpp.properties b/chat/locales/en-US/xmpp.properties
-index 293ab01d4..237d20c92 100644
+index a53be368bd..5192e24d1e 100644
 --- a/chat/locales/en-US/xmpp.properties
 +++ b/chat/locales/en-US/xmpp.properties
 @@ -13,6 +13,9 @@ connection.initializingEncryption=Initializing encryption
@@ -27,23 +27,23 @@ index 293ab01d4..237d20c92 100644
 +connection.registering=Registering new account
 +connection.gettingRegistration=Getting registration form
 +connection.onRegistrationSuccess=Account registered
+ connection.srvLookup=Looking up the SRV record
  
  # LOCALIZATION NOTE (connection.error.*)
- #   These will show in the account manager if an error occurs during the
-@@ -33,6 +36,8 @@ connection.error.notSendingPasswordInClear=The server only supports authenticati
+@@ -34,6 +37,8 @@ connection.error.notSendingPasswordInClear=The server only supports authenticati
  connection.error.authenticationFailure=Authentication failure
  connection.error.notAuthorized=Not authorized (Did you enter the wrong password?)
  connection.error.failedToGetAResource=Failed to get a resource
 +connection.error.noRegistrationSupport=The server does not support in-band registration
 +connection.error.registrationCancel=Registration canceled
- 
- 
- # LOCALIZATION NOTE (conversation.error.notDelivered):
+ connection.error.failedMaxResourceLimit=This account is connected from too many places at the same time.
+ connection.error.failedResourceNotValid=Resource is not valid.
+ connection.error.XMPPNotSupported=This server does not support XMPP
 diff --git a/chat/protocols/xmpp/xmpp-session.jsm b/chat/protocols/xmpp/xmpp-session.jsm
-index 24618ee0c..246ec2b7c 100644
+index f61d6c5634..1c001064bd 100644
 --- a/chat/protocols/xmpp/xmpp-session.jsm
 +++ b/chat/protocols/xmpp/xmpp-session.jsm
-@@ -11,6 +11,8 @@ Cu.import("resource:///modules/socket.jsm");
+@@ -13,6 +13,8 @@ Cu.import("resource:///modules/socket.jsm");
  Cu.import("resource:///modules/xmpp-xml.jsm");
  Cu.import("resource:///modules/xmpp-authmechs.jsm");
  
@@ -52,7 +52,7 @@ index 24618ee0c..246ec2b7c 100644
  XPCOMUtils.defineLazyGetter(this, "_", () =>
    l10nHelper("chrome://chat/locale/xmpp.properties")
  );
-@@ -68,6 +70,7 @@ XMPPSession.prototype = {
+@@ -101,6 +103,7 @@ XMPPSession.prototype = {
                                Stanza.node("ping", Stanza.NS.ping)),
                      this.cancelDisconnectTimer, this);
    },
@@ -60,7 +60,7 @@ index 24618ee0c..246ec2b7c 100644
    _lastReceiveTime: 0,
    _lastSendTime: 0,
    checkPingTimer(aJustSentSomething = false) {
-@@ -271,6 +274,69 @@ XMPPSession.prototype = {
+@@ -370,6 +373,69 @@ XMPPSession.prototype = {
        this.onXmppStanza = this.stanzaListeners.startAuth;
        this.onXmppStanza(aStanza);
      },
@@ -130,7 +130,7 @@ index 24618ee0c..246ec2b7c 100644
      startTLS: function(aStanza) {
        if (aStanza.localName != "proceed") {
          this._networkError(_("connection.error.failedToStartTLS"));
-@@ -283,6 +349,18 @@ XMPPSession.prototype = {
+@@ -382,6 +448,18 @@ XMPPSession.prototype = {
        this.onXmppStanza = this.stanzaListeners.startAuth;
      },
      startAuth: function(aStanza) {
@@ -150,7 +150,7 @@ index 24618ee0c..246ec2b7c 100644
          this.ERROR("Unexpected stanza " + aStanza.localName + ", expected 'features'");
          this._networkError(_("connection.error.incorrectResponse"));
 diff --git a/im/content/accountWizard.js b/im/content/accountWizard.js
-index 73707c9e2..889c06908 100644
+index 8092621c4f..2ca9ba3b0e 100644
 --- a/im/content/accountWizard.js
 +++ b/im/content/accountWizard.js
 @@ -119,6 +119,12 @@ var accountWizard = {
@@ -166,7 +166,7 @@ index 73707c9e2..889c06908 100644
      let bundle = document.getElementById("accountsBundle");
      let usernameInfo;
      let emptyText = this.proto.usernameEmptyText;
-@@ -424,6 +430,8 @@ var accountWizard = {
+@@ -348,6 +354,8 @@ var accountWizard = {
        acc.alias = this.alias;
      //FIXME: newMailNotification
  
@@ -176,10 +176,10 @@ index 73707c9e2..889c06908 100644
        let option = this.prefs[i];
        let opt = option.opt;
 diff --git a/im/content/accountWizard.xul b/im/content/accountWizard.xul
-index f0933af7f..de9d0d809 100644
+index 904d22ba57..135b68386c 100644
 --- a/im/content/accountWizard.xul
 +++ b/im/content/accountWizard.xul
-@@ -65,6 +65,7 @@
+@@ -66,6 +66,7 @@
      <vbox id="userNameBox"/>
      <separator/>
      <description id="duplicateAccount" hidden="true">&accountUsernameDuplicate.label;</description>
@@ -188,10 +188,10 @@ index f0933af7f..de9d0d809 100644
  
    <wizardpage id="accountpassword" pageid="accountpassword" next="accountadvanced"
 diff --git a/im/content/jar.mn b/im/content/jar.mn
-index 98d9a09a9..20ea9dce7 100644
+index 1d05a9c744..88662ff437 100644
 --- a/im/content/jar.mn
 +++ b/im/content/jar.mn
-@@ -61,6 +61,8 @@ instantbird.jar:
+@@ -59,6 +59,8 @@ instantbird.jar:
  *	content/instantbird/viewlog.xul
  	content/instantbird/viewlog.js
  	content/instantbird/viewlog.css
@@ -202,7 +202,7 @@ index 98d9a09a9..20ea9dce7 100644
  	content/instantbird/menus-mac.xul
 diff --git a/im/content/xmppRegister.js b/im/content/xmppRegister.js
 new file mode 100644
-index 000000000..52852f045
+index 0000000000..52852f045c
 --- /dev/null
 +++ b/im/content/xmppRegister.js
 @@ -0,0 +1,142 @@
@@ -350,7 +350,7 @@ index 000000000..52852f045
 +}
 diff --git a/im/content/xmppRegister.xul b/im/content/xmppRegister.xul
 new file mode 100644
-index 000000000..e2bd36750
+index 0000000000..e2bd36750a
 --- /dev/null
 +++ b/im/content/xmppRegister.xul
 @@ -0,0 +1,27 @@
@@ -382,7 +382,7 @@ index 000000000..e2bd36750
 +
 +</dialog>
 diff --git a/im/locales/en-US/chrome/instantbird/accountWizard.dtd b/im/locales/en-US/chrome/instantbird/accountWizard.dtd
-index 43d0f19e3..c46fb2f95 100644
+index 43d0f19e3f..c46fb2f956 100644
 --- a/im/locales/en-US/chrome/instantbird/accountWizard.dtd
 +++ b/im/locales/en-US/chrome/instantbird/accountWizard.dtd
 @@ -31,3 +31,5 @@
@@ -392,5 +392,5 @@ index 43d0f19e3..c46fb2f95 100644
 +
 +<!ENTITY registerXMPP.label "Create this new account on the server">
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0009-Remove-search-from-UI.patch b/projects/instantbird/0004-Remove-search-from-UI.patch
similarity index 92%
rename from projects/instantbird/0009-Remove-search-from-UI.patch
rename to projects/instantbird/0004-Remove-search-from-UI.patch
index 7e716d1..3fefe06 100644
--- a/projects/instantbird/0009-Remove-search-from-UI.patch
+++ b/projects/instantbird/0004-Remove-search-from-UI.patch
@@ -1,7 +1,7 @@
-From 1416efe7c0d089fa0782f8234c66096f5d5e9520 Mon Sep 17 00:00:00 2001
+From 7ecf693b9af472fce841b2bf10ea332967e5de91 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 18:47:48 -0700
-Subject: [PATCH 09/28] Remove search from UI
+Subject: [PATCH 04/20] Remove search from UI
 
 ---
  im/content/nsContextMenu.js         | 18 +-----------------
@@ -9,7 +9,7 @@ Subject: [PATCH 09/28] Remove search from UI
  2 files changed, 1 insertion(+), 28 deletions(-)
 
 diff --git a/im/content/nsContextMenu.js b/im/content/nsContextMenu.js
-index 5261b793f..f667793be 100644
+index 5261b793fc..f667793be0 100644
 --- a/im/content/nsContextMenu.js
 +++ b/im/content/nsContextMenu.js
 @@ -468,23 +468,7 @@ nsContextMenu.prototype = {
@@ -38,7 +38,7 @@ index 5261b793f..f667793be 100644
  
    // Returns true if anything is selected.
 diff --git a/im/content/preferences/advanced.xul b/im/content/preferences/advanced.xul
-index fad67c190..cfe2405ea 100644
+index fad67c190b..cfe2405ea3 100644
 --- a/im/content/preferences/advanced.xul
 +++ b/im/content/preferences/advanced.xul
 @@ -143,17 +143,6 @@
@@ -60,5 +60,5 @@ index fad67c190..cfe2405ea 100644
            <groupbox>
              <caption label="&configEditDesc.label;"/>
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch b/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch
deleted file mode 100644
index 0a42f29..0000000
--- a/projects/instantbird/0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch
+++ /dev/null
@@ -1,67 +0,0 @@
-From 81f299a5113a5fd7261bdfffca05be8ecec71bbd Mon Sep 17 00:00:00 2001
-From: Arlo Breault <arlolra at gmail.com>
-Date: Tue, 2 Feb 2016 16:04:51 -0800
-Subject: [PATCH 04/28] Trac 17494: Better error reporting for failed outgoing
- messages
-
- * Bug 1245325 - Better error reporting for failed outgoing messages. r=clokep
----
- chat/locales/en-US/xmpp.properties |  6 ++++--
- chat/protocols/xmpp/xmpp.jsm       | 17 ++++++++++++-----
- 2 files changed, 16 insertions(+), 7 deletions(-)
-
-diff --git a/chat/locales/en-US/xmpp.properties b/chat/locales/en-US/xmpp.properties
-index 7f824e534..293ab01d4 100644
---- a/chat/locales/en-US/xmpp.properties
-+++ b/chat/locales/en-US/xmpp.properties
-@@ -66,7 +66,10 @@ conversation.error.sendFailedAsNotInRoom=Message could not be sent to %1$S as yo
- #   %2$S is the text of the message that wasn't delivered.
- conversation.error.sendFailedAsRecipientNotInRoom=Message could not be sent to %1$S as the recipient is no longer in the room: %2$S
- #   These are displayed in a conversation as a system error message.
--conversation.error.remoteServerNotFound=Could not reach the recipient's server
-+conversation.error.remoteServerNotFound=Could not reach the recipient's server.
-+conversation.error.unknownSendError=An unknown error occurred on sending this message.
-+#   %S is the name of the message recipient.
-+conversation.error.sendServiceUnavailable=It is not possible to send messages to %S at this time.
- #   %S is the nick of participant that is not in room.
- conversation.error.nickNotInRoom=%S is not in the room.
- conversation.error.banCommandAnonymousRoom=You can't ban participants from anonymous rooms. Try /kick instead.
-@@ -80,7 +83,6 @@ conversation.error.failedJIDNotFound=Could not reach %S.
- #   %S is the jid that is invalid.
- conversation.error.invalidJID=%S is an invalid jid (Jabber identifiers must be of the form user at domain).
- conversation.error.commandFailedNotInRoom=You have to rejoin the room to be able to use this command.
--conversation.error.unknownError=Unknown error
- 
- # LOCALIZATION NOTE (tooltip.*):
- #   These are the titles of lines of information that will appear in
-diff --git a/chat/protocols/xmpp/xmpp.jsm b/chat/protocols/xmpp/xmpp.jsm
-index 7c3fcd7e6..282575938 100644
---- a/chat/protocols/xmpp/xmpp.jsm
-+++ b/chat/protocols/xmpp/xmpp.jsm
-@@ -679,11 +679,18 @@ var XMPPConversationPrototype = {
-       let muc = this._account._mucs.get(norm);
- 
-       if (!aMsg) {
--        // Failed outgoing message unknown.
--        if (error.condition == "remote-server-not-found")
--          aMsg = _("conversation.error.remoteServerNotFound");
--        else
--          aMsg = _("conversation.error.unknownError");
-+        // Failed outgoing message.
-+        switch (error.condition) {
-+          case "remote-server-not-found":
-+            aMsg = _("conversation.error.remoteServerNotFound");
-+            break;
-+          case "service-unavailable":
-+            aMsg = _("conversation.error.sendServiceUnavailable", this.shortName);
-+            break;
-+          default:
-+            aMsg = _("conversation.error.unknownSendError");
-+            break;
-+        }
-       }
-       else if (this._isMucParticipant && muc && !muc.left &&
-                error.condition == "item-not-found") {
--- 
-2.12.2
-
diff --git a/projects/instantbird/0010-Add-Tor-Messenger-branding.patch b/projects/instantbird/0005-Add-Tor-Messenger-branding.patch
similarity index 99%
rename from projects/instantbird/0010-Add-Tor-Messenger-branding.patch
rename to projects/instantbird/0005-Add-Tor-Messenger-branding.patch
index d1f733f..4864018 100644
--- a/projects/instantbird/0010-Add-Tor-Messenger-branding.patch
+++ b/projects/instantbird/0005-Add-Tor-Messenger-branding.patch
@@ -1,7 +1,7 @@
-From 1368d7678fbfb6dc5fbd09a70dbf328f847d5e1d Mon Sep 17 00:00:00 2001
+From c763e4771c903d78ed5168fe4746b9d035d56d85 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Mon, 10 Oct 2016 18:56:27 -0700
-Subject: [PATCH 10/28] Add Tor Messenger branding
+Date: Wed, 26 Jul 2017 15:46:51 -0400
+Subject: [PATCH 05/20] Add Tor Messenger branding
 
 ---
  im/app/macbuild/Contents/Info.plist.in             |   2 +-
@@ -49,12 +49,12 @@ Subject: [PATCH 10/28] Add Tor Messenger branding
  im/content/aboutDialog-appUpdater.js               | 576 +++++++++++++++++++++
  im/content/aboutDialog.css                         | 105 ++--
  im/content/aboutDialog.js                          |  80 +++
- im/content/aboutDialog.xul                         | 257 +++++----
+ im/content/aboutDialog.xul                         | 253 +++++----
  im/content/browserMountPoints.inc                  |  12 +
  im/content/jar.mn                                  |   3 +-
  .../en-US/chrome/instantbird/aboutDialog.dtd       | 139 ++++-
  im/locales/en-US/updater/updater.ini               |   2 +-
- 50 files changed, 1695 insertions(+), 160 deletions(-)
+ 50 files changed, 1691 insertions(+), 160 deletions(-)
  create mode 100644 im/branding/messenger/Makefile.in
  create mode 100644 im/branding/messenger/background.png
  create mode 100755 im/branding/messenger/branding.nsi
@@ -101,7 +101,7 @@ Subject: [PATCH 10/28] Add Tor Messenger branding
  create mode 100644 im/content/browserMountPoints.inc
 
 diff --git a/im/app/macbuild/Contents/Info.plist.in b/im/app/macbuild/Contents/Info.plist.in
-index 615e4e6b8..ac61e6134 100644
+index dc048c0ea8..78a53051f0 100644
 --- a/im/app/macbuild/Contents/Info.plist.in
 +++ b/im/app/macbuild/Contents/Info.plist.in
 @@ -11,7 +11,7 @@
@@ -115,7 +115,7 @@ index 615e4e6b8..ac61e6134 100644
  	<key>CFBundleName</key>
 diff --git a/im/branding/messenger/Makefile.in b/im/branding/messenger/Makefile.in
 new file mode 100644
-index 000000000..b4309568e
+index 0000000000..e96de1faf6
 --- /dev/null
 +++ b/im/branding/messenger/Makefile.in
 @@ -0,0 +1,49 @@
@@ -144,7 +144,7 @@ index 000000000..b4309568e
 +	cp $(srcdir)/disk.icns         $(DIST)/branding/disk.icns
 +#	cp $(srcdir)/license.r         $(DIST)/branding/license.r
 +endif
-+ifdef MOZ_WIDGET_GTK
++ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
 +	cp $(srcdir)/mozicon128.png    $(DIST)/branding/mozicon128.png
 +	cp $(srcdir)/mozicon16.xpm     $(DIST)/branding/mozicon16.xpm
 +	cp $(srcdir)/mozicon50.xpm     $(DIST)/branding/mozicon50.xpm
@@ -157,7 +157,7 @@ index 000000000..b4309568e
 +	cp $(srcdir)/windows/convWindow.ico  $(DIST)/branding/convWindow.ico
 +	cp $(srcdir)/windows/default.ico     $(DIST)/branding/default.ico
 +endif
-+ifdef MOZ_WIDGET_GTK
++ifneq (,$(filter gtk%,$(MOZ_WIDGET_TOOLKIT)))
 +	cp $(srcdir)/gtk/blistWindow.png    $(DIST)/branding/blistWindow.png
 +	cp $(srcdir)/gtk/blistWindow16.png  $(DIST)/branding/blistWindow16.png
 +	cp $(srcdir)/gtk/blistWindow48.png  $(DIST)/branding/blistWindow48.png
@@ -183,7 +183,7 @@ HcmV?d00001
 
 diff --git a/im/branding/messenger/branding.nsi b/im/branding/messenger/branding.nsi
 new file mode 100755
-index 000000000..4683827fa
+index 0000000000..4683827fae
 --- /dev/null
 +++ b/im/branding/messenger/branding.nsi
 @@ -0,0 +1,13 @@
@@ -202,7 +202,7 @@ index 000000000..4683827fa
 +
 diff --git a/im/branding/messenger/configure.sh b/im/branding/messenger/configure.sh
 new file mode 100644
-index 000000000..7e580518b
+index 0000000000..7e580518b9
 --- /dev/null
 +++ b/im/branding/messenger/configure.sh
 @@ -0,0 +1,5 @@
@@ -1218,7 +1218,7 @@ HcmV?d00001
 
 diff --git a/im/branding/messenger/content/aboutDialog.css b/im/branding/messenger/content/aboutDialog.css
 new file mode 100644
-index 000000000..9a3c04eb3
+index 0000000000..9a3c04eb32
 --- /dev/null
 +++ b/im/branding/messenger/content/aboutDialog.css
 @@ -0,0 +1,48 @@
@@ -2197,7 +2197,7 @@ HcmV?d00001
 
 diff --git a/im/branding/messenger/jar.mn b/im/branding/messenger/jar.mn
 new file mode 100644
-index 000000000..929e7c998
+index 0000000000..929e7c9986
 --- /dev/null
 +++ b/im/branding/messenger/jar.mn
 @@ -0,0 +1,14 @@
@@ -2217,7 +2217,7 @@ index 000000000..929e7c998
 +	content/branding/about-wordmark.png	(content/about-wordmark.png)
 diff --git a/im/branding/messenger/locales/en-US/brand.dtd b/im/branding/messenger/locales/en-US/brand.dtd
 new file mode 100644
-index 000000000..4dc69f244
+index 0000000000..4dc69f2446
 --- /dev/null
 +++ b/im/branding/messenger/locales/en-US/brand.dtd
 @@ -0,0 +1,10 @@
@@ -2233,7 +2233,7 @@ index 000000000..4dc69f244
 +<!ENTITY  vendorShortName       "Tor Project">
 diff --git a/im/branding/messenger/locales/en-US/brand.properties b/im/branding/messenger/locales/en-US/brand.properties
 new file mode 100644
-index 000000000..c09000fdb
+index 0000000000..c09000fdb9
 --- /dev/null
 +++ b/im/branding/messenger/locales/en-US/brand.properties
 @@ -0,0 +1,7 @@
@@ -2246,7 +2246,7 @@ index 000000000..c09000fdb
 +vendorShortName=Tor Project
 diff --git a/im/branding/messenger/locales/jar.mn b/im/branding/messenger/locales/jar.mn
 new file mode 100755
-index 000000000..4fb707f30
+index 0000000000..4fb707f30b
 --- /dev/null
 +++ b/im/branding/messenger/locales/jar.mn
 @@ -0,0 +1,10 @@
@@ -2262,7 +2262,7 @@ index 000000000..4fb707f30
 +	locale/@AB_CD@/branding/brand.properties	(%brand.properties)
 diff --git a/im/branding/messenger/locales/moz.build b/im/branding/messenger/locales/moz.build
 new file mode 100644
-index 000000000..e59008d87
+index 0000000000..e59008d87f
 --- /dev/null
 +++ b/im/branding/messenger/locales/moz.build
 @@ -0,0 +1,8 @@
@@ -2276,7 +2276,7 @@ index 000000000..e59008d87
 +DEFINES['MOZ_DISTRIBUTION_ID_UNQUOTED'] = CONFIG['MOZ_DISTRIBUTION_ID']
 diff --git a/im/branding/messenger/moz.build b/im/branding/messenger/moz.build
 new file mode 100644
-index 000000000..bd8ad850b
+index 0000000000..bd8ad850b8
 --- /dev/null
 +++ b/im/branding/messenger/moz.build
 @@ -0,0 +1,8 @@
@@ -2624,7 +2624,7 @@ HcmV?d00001
 
 diff --git a/im/branding/messenger/mozicon16.xpm b/im/branding/messenger/mozicon16.xpm
 new file mode 100644
-index 000000000..3434739f6
+index 0000000000..3434739f68
 --- /dev/null
 +++ b/im/branding/messenger/mozicon16.xpm
 @@ -0,0 +1,193 @@
@@ -2823,7 +2823,7 @@ index 000000000..3434739f6
 +};
 diff --git a/im/branding/messenger/mozicon50.xpm b/im/branding/messenger/mozicon50.xpm
 new file mode 100644
-index 000000000..76e799c60
+index 0000000000..76e799c603
 --- /dev/null
 +++ b/im/branding/messenger/mozicon50.xpm
 @@ -0,0 +1,314 @@
@@ -3855,7 +3855,7 @@ HcmV?d00001
 
 diff --git a/im/content/aboutDialog-appUpdater.js b/im/content/aboutDialog-appUpdater.js
 new file mode 100644
-index 000000000..f223f061e
+index 0000000000..f223f061e7
 --- /dev/null
 +++ b/im/content/aboutDialog-appUpdater.js
 @@ -0,0 +1,576 @@
@@ -4436,7 +4436,7 @@ index 000000000..f223f061e
 +  }
 +};
 diff --git a/im/content/aboutDialog.css b/im/content/aboutDialog.css
-index 25070608b..a065c8e88 100644
+index 25070608b8..a065c8e88d 100644
 --- a/im/content/aboutDialog.css
 +++ b/im/content/aboutDialog.css
 @@ -1,66 +1,91 @@
@@ -4573,7 +4573,7 @@ index 25070608b..a065c8e88 100644
 +}
 diff --git a/im/content/aboutDialog.js b/im/content/aboutDialog.js
 new file mode 100644
-index 000000000..e265f239c
+index 0000000000..e265f239c7
 --- /dev/null
 +++ b/im/content/aboutDialog.js
 @@ -0,0 +1,80 @@
@@ -4658,15 +4658,10 @@ index 000000000..e265f239c
 +  }
 +}
 diff --git a/im/content/aboutDialog.xul b/im/content/aboutDialog.xul
-index aa3b80ec9..ba924b9ad 100644
+index c20b4f7add..4fd375d1ad 100644
 --- a/im/content/aboutDialog.xul
 +++ b/im/content/aboutDialog.xul
-@@ -1,130 +1,173 @@
- <?xml version="1.0"?> <!-- -*- Mode: HTML -*- -->
-+
- # 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/.
+@@ -5,126 +5,165 @@
  
  <?xml-stylesheet href="chrome://global/skin/" type="text/css"?>
  <?xml-stylesheet href="chrome://instantbird/content/aboutDialog.css" type="text/css"?>
@@ -4681,14 +4676,11 @@ index aa3b80ec9..ba924b9ad 100644
  <!ENTITY % aboutDialogDTD SYSTEM "chrome://instantbird/locale/aboutDialog.dtd" >
  %aboutDialogDTD;
 -<!ENTITY copyrightYear "2015">
-+]>
-+
- #ifdef XP_MACOSX
+-#ifdef XP_MACOSX
 - <!ENTITY % instantbirdDTD SYSTEM "chrome://instantbird/locale/instantbird.dtd">
 - %instantbirdDTD;
-+<?xul-overlay href="chrome://instantbird/content/macBrowserOverlay.xul"?>
- #endif
--]>
+-#endif
+ ]>
  
 -<dialog xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
 +<window xmlns:html="http://www.w3.org/1999/xhtml"
@@ -4700,12 +4692,12 @@ index aa3b80ec9..ba924b9ad 100644
 -        title="&aboutDialog.title;" creditslabel="&credits.label;" creditsaccesskey="&credits.accesskey;"
 -        aboutlabel="&aboutLink.label;" aboutaccesskey="&aboutLink.accesskey;" versionlabel="&aboutVersion;"
 -        style="width: 299px; height: 330px;">
--
 +        windowtype="Browser:About"
 +        onload="init(event);"
 +#ifdef MOZ_UPDATER
 +        onunload="onUnload(event);"
 +#endif
+ 
  #ifdef XP_MACOSX
 -#include menus.xul.inc
 +        inwindowmenu="false"
@@ -4716,7 +4708,7 @@ index aa3b80ec9..ba924b9ad 100644
 +        aria-describedby="version distribution distributionId communityDesc contributeDesc trademark"
 +        >
  
--    <script type="application/x-javascript">
+-    <script type="application/javascript">
 -      <![CDATA[
 -        var gSelectedPage;
 -
@@ -4944,7 +4936,7 @@ index aa3b80ec9..ba924b9ad 100644
 +</window>
 diff --git a/im/content/browserMountPoints.inc b/im/content/browserMountPoints.inc
 new file mode 100644
-index 000000000..e4315b04a
+index 0000000000..e4315b04a8
 --- /dev/null
 +++ b/im/content/browserMountPoints.inc
 @@ -0,0 +1,12 @@
@@ -4962,7 +4954,7 @@ index 000000000..e4315b04a
 +<menubar id="main-menubar"/>
 \ No newline at end of file
 diff --git a/im/content/jar.mn b/im/content/jar.mn
-index 20ea9dce7..b3d9e492f 100644
+index 88662ff437..5d40350089 100644
 --- a/im/content/jar.mn
 +++ b/im/content/jar.mn
 @@ -10,7 +10,8 @@ instantbird.jar:
@@ -4973,10 +4965,10 @@ index 20ea9dce7..b3d9e492f 100644
 +*	content/instantbird/aboutDialog.js
 +*	content/instantbird/aboutDialog-appUpdater.js
  	content/instantbird/account.js
- 	content/instantbird/accounts.css
  	content/instantbird/accounts.js
+ *	content/instantbird/accounts.xul
 diff --git a/im/locales/en-US/chrome/instantbird/aboutDialog.dtd b/im/locales/en-US/chrome/instantbird/aboutDialog.dtd
-index ecd8d9d24..187cf5c3e 100644
+index ecd8d9d248..187cf5c3e1 100644
 --- a/im/locales/en-US/chrome/instantbird/aboutDialog.dtd
 +++ b/im/locales/en-US/chrome/instantbird/aboutDialog.dtd
 @@ -1,10 +1,129 @@
@@ -5120,7 +5112,7 @@ index ecd8d9d24..187cf5c3e 100644
 +<!ENTITY bottomLinks.license  "Licensing Information">
 +<!ENTITY tor.TrademarkStatement   "'Tor' and the 'Onion Logo' are registered trademarks of the Tor Project, Inc.">
 diff --git a/im/locales/en-US/updater/updater.ini b/im/locales/en-US/updater/updater.ini
-index 15ec569c1..4a2d35d8a 100644
+index 15ec569c11..4a2d35d8a1 100644
 --- a/im/locales/en-US/updater/updater.ini
 +++ b/im/locales/en-US/updater/updater.ini
 @@ -5,4 +5,4 @@
@@ -5130,5 +5122,5 @@ index 15ec569c1..4a2d35d8a 100644
 -Info=Instantbird is installing your updates and will start in a few moments…
 +Info=Tor Messenger is installing your updates and will start in a few moments…
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch b/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch
deleted file mode 100644
index 18d684e..0000000
--- a/projects/instantbird/0005-Trac-13312-OTR-over-Twitter-DMs.patch
+++ /dev/null
@@ -1,766 +0,0 @@
-From 610d64905425755c3602d33ba36af5435dbc2631 Mon Sep 17 00:00:00 2001
-From: Arlo Breault <arlolra at gmail.com>
-Date: Tue, 15 Mar 2016 17:40:42 -0700
-Subject: [PATCH 05/28] Trac 13312: OTR over Twitter DMs
-
----
- chat/components/src/imConversations.js |   3 +-
- chat/locales/en-US/twitter.properties  |   4 +
- chat/modules/imContentSink.jsm         |  10 +-
- chat/protocols/twitter/twitter.js      | 484 +++++++++++++++++++--------------
- 4 files changed, 293 insertions(+), 208 deletions(-)
-
-diff --git a/chat/components/src/imConversations.js b/chat/components/src/imConversations.js
-index 6fc5d0d24..2a53a2c86 100644
---- a/chat/components/src/imConversations.js
-+++ b/chat/components/src/imConversations.js
-@@ -414,7 +414,8 @@ UIConversation.prototype = {
-       this.notifyObservers(aSubject, "received-message");
-       if (aSubject.cancelled)
-         return;
--      aSubject.conversation.prepareForDisplaying(aSubject);
-+      if (!aSubject.system)
-+        aSubject.conversation.prepareForDisplaying(aSubject);
- 
-       this._messages.push(aSubject);
-       ++this._unreadMessageCount;
-diff --git a/chat/locales/en-US/twitter.properties b/chat/locales/en-US/twitter.properties
-index 759eaa79c..8f0701aa7 100644
---- a/chat/locales/en-US/twitter.properties
-+++ b/chat/locales/en-US/twitter.properties
-@@ -17,6 +17,8 @@ error.tooLong=Status is over 140 characters.
- error.general=An error %1$S occurred while sending: %2$S
- error.retweet=An error %1$S occurred while retweeting: %2$S
- error.delete=An error %1$S occurred while deleting: %2$S
-+error.like=An error %1$S occured while liking: %2$S
-+error.unlike=An error %1$S occured while unliking: %2$S
- # LOCALIZATION NOTE (error.descriptionTooLong)
- #   %S is the truncated string that was sent to the server.
- error.descriptionTooLong=Description is over the maximum length (160 characters), it was automatically truncated to: %S.
-@@ -36,6 +38,8 @@ action.delete=Delete
- #  %S will be replaced by the screen name of a twitter user.
- action.follow=Follow %S
- action.stopFollowing=Stop following %S
-+action.like=Like
-+action.unlike=Remove Like
- 
- # LOCALIZATION NOTE (event.follow, event.unfollow, event.followed):
- #  This will be displayed in system messages inside the timeline conversation.
-diff --git a/chat/modules/imContentSink.jsm b/chat/modules/imContentSink.jsm
-index ee067afdf..abd95fc71 100644
---- a/chat/modules/imContentSink.jsm
-+++ b/chat/modules/imContentSink.jsm
-@@ -47,6 +47,7 @@ var kAllowedMozClasses =
-   aClassName => aClassName == "moz-txt-underscore" ||
-                 aClassName == "moz-txt-tag" ||
-                 aClassName == "ib-person";
-+var kAllowedAnchorClasses = aClassName => aClassName == "ib-person";
- 
- /* Tags whose content should be fully removed, and reported in the Error Console. */
- var kForbiddenTags = {
-@@ -61,7 +62,8 @@ var kStrictMode = {
-   tags: {
-     'a': {
-       'title': true,
--      'href': kAllowedURLs
-+      'href': kAllowedURLs,
-+      'class': kAllowedAnchorClasses
-     },
-     'br': true,
-     'p': true
-@@ -80,7 +82,8 @@ var kStandardMode = {
-     'div': true,
-     'a': {
-       'title': true,
--      'href': kAllowedURLs
-+      'href': kAllowedURLs,
-+      'class': kAllowedAnchorClasses
-     },
-     'em': true,
-     'strong': true,
-@@ -117,7 +120,8 @@ var kPermissiveMode = {
-     'div': true,
-     'a': {
-       'title': true,
--      'href': kAllowedURLs
-+      'href': kAllowedURLs,
-+      'class': kAllowedAnchorClasses
-     },
-     'font': {
-       'face': true,
-diff --git a/chat/protocols/twitter/twitter.js b/chat/protocols/twitter/twitter.js
-index 59f60cc22..4d8e04c02 100644
---- a/chat/protocols/twitter/twitter.js
-+++ b/chat/protocols/twitter/twitter.js
-@@ -36,8 +36,11 @@ ChatBuddy.prototype = {
-   set buddyIconFilename(aName) {
-     // Prevent accidental removal of the getter.
-     throw("Don't set chatBuddy.buddyIconFilename directly for Twitter.");
-+  },
-+  createConversation: function() {
-+    return this._account.createConversation(this._name);
-   }
--}
-+};
- 
- function Tweet(aTweet, aWho, aMessage, aObject)
- {
-@@ -48,6 +51,13 @@ Tweet.prototype = {
-   __proto__: GenericMessagePrototype,
-   _deleted: false,
-   getActions: function(aCount) {
-+    // Direct messages have no actions.
-+    if (!this.conversation.isChat) {
-+      if (aCount)
-+        aCount.value = 0;
-+      return [];
-+    }
-+
-     let account = this.conversation._account;
-     let actions = [];
- 
-@@ -68,6 +78,11 @@ Tweet.prototype = {
-         let screenName = this._tweet.user.screen_name;
-         actions.push(new Action(_("action." + action, screenName),
-                                 function() { account[action](screenName); }));
-+
-+        const favAction = this._tweet.favorited ? "unlike" : "like";
-+        actions.push(new Action(_("action." + favAction), () => {
-+          this.conversation.like(this._tweet, this._tweet.favorited);
-+        }, this));
-       }
-       else if (this.outgoing && !this._deleted) {
-         actions.push(
-@@ -123,83 +138,13 @@ Action.prototype = {
-   get run() { return this._action.bind(this._tweet); }
- };
- 
--function Conversation(aAccount)
--{
--  this._init(aAccount);
--  this._ensureParticipantExists(aAccount.name);
--  // We need the screen names for the IDs in _friends, but _userInfo is
--  // indexed by name, so we build an ID -> name map.
--  let names = new Map([userInfo.id_str, name] for ([name, userInfo] of aAccount._userInfo));
--  for (let id_str of aAccount._friends)
--    this._ensureParticipantExists(names.get(id_str));
--
--  // If the user's info has already been received, update the timeline topic.
--  if (aAccount._userInfo.has(aAccount.name)) {
--    let userInfo = aAccount._userInfo.get(aAccount.name);
--    if ("description" in userInfo)
--      this.setTopic(userInfo.description, aAccount.name, true);
--  }
--}
--Conversation.prototype = {
--  __proto__: GenericConvChatPrototype,
--  unInit: function() {
--    delete this._account._timeline;
--    GenericConvChatPrototype.unInit.call(this);
--  },
--  inReplyToStatusId: null,
--  startReply: function(aTweet) {
--    this.inReplyToStatusId = aTweet.id_str;
--    let entities = aTweet.entities;
--
--    // Twitter replies go to all the users mentioned in the tweet.
--    let nicks = [aTweet.user.screen_name];
--    if ("user_mentions" in entities && Array.isArray(entities.user_mentions)) {
--      nicks = nicks.concat(entities.user_mentions
--                                   .map(um => um.screen_name));
--    }
--    // Ignore duplicates and the user's nick.
--    let prompt =
--      nicks.filter(function(aNick, aPos) {
--             return nicks.indexOf(aNick) == aPos && aNick != this._account.name;
--           }, this)
--           .map(aNick => "@" + aNick)
--           .join(" ") + " ";
--
--    this.notifyObservers(null, "replying-to-prompt", prompt);
--    this.notifyObservers(null, "status-text-changed",
--                         _("replyingToStatusText", aTweet.text));
--  },
--  reTweet: function(aTweet) {
--    this._account.reTweet(aTweet, this.onSentCallback,
--                          function(aException, aData) {
--      this.systemMessage(_("error.retweet", this._parseError(aData),
--                           aTweet.text), true);
--    }, this);
--  },
-+// Properties / methods shared by both DirectMessageConversation and
-+// TimelineConversation.
-+var GenericTwitterConversation = {
-   getTweetLength: function (aString) {
-     // Use the Twitter library to calculate the length.
-     return twttr.txt.getTweetLength(aString, this._account.config);
-   },
--  sendMsg: function (aMsg) {
--    if (this.getTweetLength(aMsg) > kMaxMessageLength) {
--      this.systemMessage(_("error.tooLong"), true);
--      throw Cr.NS_ERROR_INVALID_ARG;
--    }
--    this._account.tweet(aMsg, this.inReplyToStatusId, this.onSentCallback,
--                        function(aException, aData) {
--      let error = this._parseError(aData);
--      this.systemMessage(_("error.general", error, aMsg), true);
--    }, this);
--    this.sendTyping("");
--  },
--  sendTyping: function(aString) {
--    if (aString.length == 0 && this.inReplyToStatusId) {
--      delete this.inReplyToStatusId;
--      this.notifyObservers(null, "status-text-changed", "");
--      return kMaxMessageLength;
--    }
--    return kMaxMessageLength - this.getTweetLength(aString);
--  },
-   systemMessage: function(aMessage, aIsError, aDate) {
-     let flags = {system: true};
-     if (aIsError)
-@@ -208,27 +153,26 @@ Conversation.prototype = {
-       flags.time = aDate;
-     this.writeMessage("twitter.com", aMessage, flags);
-   },
--  onSentCallback: function(aData) {
-+  onSentCallback: function(aMsg, aData) {
-+    // The conversation may have been unitialized in the time it takes for
-+    // the async callback to fire.  Use `_observers` as a proxy for uninit'd.
-+    if (!this._observers)
-+      return;
-+
-     let tweet = JSON.parse(aData);
--    if (tweet.user.screen_name != this._account.name)
--      throw "Wrong screen_name... Uh?";
--    this._account.displayMessages([tweet]);
--  },
--  _parseError: function(aData) {
--    let error = "";
--    try {
--      let data = JSON.parse(aData);
--      if ("error" in data)
--        error = data.error;
--      else if ("errors" in data)
--        error = data.errors[0].message;
--      if (error)
--        error = "(" + error + ")";
--    } catch(e) {}
--    return error;
-+    // The OTR extension requires that the protocol not modify the message
-+    // (see the notes at `imIOutgoingMessage`).  That's the contract we made.
-+    // Unfortunately, Twitter trims tweets and substitutes links.
-+    tweet.text = aMsg;
-+    this.displayMessages([tweet]);
-   },
--  parseTweet: function(aTweet) {
--    let text = aTweet.text;
-+  prepareForDisplaying: function(aMsg) {
-+    if (!this._tweets.has(aMsg.id))
-+      return;
-+    let tweet = this._tweets.get(aMsg.id)._tweet;
-+    this._tweets.delete(aMsg.id);
-+
-+    let text = aMsg.displayMessage;
-     let entities = {};
- 
-     // Handle retweets: retweeted_status contains the object for the original
-@@ -238,8 +182,8 @@ Conversation.prototype = {
-     // the FULL text from the original tweet and update the entities to match.
-     // Note: the truncated flag is not always set correctly by twitter, so we
-     // always make use of the original tweet.
--    if ("retweeted_status" in aTweet) {
--      let retweet = aTweet["retweeted_status"];
-+    if ("retweeted_status" in tweet) {
-+      let retweet = tweet["retweeted_status"];
-       let retweetText, retweetEntities = {};
- 
-       if ("extended_tweet" in retweet) {
-@@ -259,22 +203,24 @@ Conversation.prototype = {
-       // We're going to take portions of the retweeted status and replace parts
-       // of the original tweet, the retweeted status prepends the original
-       // status with "RT @<username>: ", we need to keep the prefix.
-+      // Note: this doesn't play nice with extensions that may have altered
-+      // `text` to this point, but at least OTR doesn't act on `isChat`.
-       let offset = text.indexOf(": ") + 2;
-       text = text.slice(0, offset) + retweetText;
- 
-       // Keep any entities that refer to the prefix (we can refer directly to
--      // aTweet for these since they are not edited).
--      if ("entities" in aTweet) {
--        for (let type in aTweet.entities) {
-+      // the tweet for these since they are not edited).
-+      if ("entities" in tweet) {
-+        for (let type in tweet.entities) {
-           let filteredEntities =
--            aTweet.entities[type].filter(e => e.indices[0] < offset);
-+            tweet.entities[type].filter(e => e.indices[0] < offset);
-           if (filteredEntities.length)
-             entities[type] = filteredEntities;
-         }
-       }
- 
-       // Add the entities from the retweet (a copy of these must be made since
--      // they will be edited and we do not wish to change aTweet).
-+      // they will be edited and we do not wish to change the tweet).
-       for (let type in retweetEntities) {
-         if (!(type in entities))
-           entities[type] = [];
-@@ -288,90 +234,41 @@ Conversation.prototype = {
-             return entity;
-           })
-         );
--       }
--    } else if ("extended_tweet" in aTweet) {
-+      }
-+    } else if ("extended_tweet" in tweet) {
-       // Bare bones extended tweet handling.
--      let extended = aTweet.extended_tweet;
-+      let extended = tweet.extended_tweet;
-       text = extended.full_text;
-       if ("entities" in extended)
-         entities = extended.entities;
-     } else {
-       // For non-retweets, we just want to use the entities that are given.
--      if ("entities" in aTweet)
--        entities = aTweet.entities;
-+      if ("entities" in tweet)
-+        entities = tweet.entities;
-     }
- 
-     this._account.LOG("Tweet: " + text);
- 
--    if (Object.keys(entities).length) {
--      /* entArray is an array of entities ready to be replaced in the tweet,
--       * each entity contains:
--       *  - start: the start index of the entity inside the tweet,
--       *  - end: the end index of the entity inside the tweet,
--       *  - str: the string that should be replaced inside the tweet,
--       *  - href: the url (href attribute) of the created link tag,
--       *  - [optional] text: the text to display for the link,
--       *     The original string (str) will be used if this is not set.
--       *  - [optional] title: the title attribute for the link.
--       */
--      let entArray = [];
--      if ("hashtags" in entities && Array.isArray(entities.hashtags)) {
--        entArray = entArray.concat(entities.hashtags.map(h => ({
--          start: h.indices[0],
--          end: h.indices[1],
--          str: "#" + h.text,
--          href: "https://twitter.com/#!/search?q=%23" + h.text})));
--      }
--      if ("urls" in entities && Array.isArray(entities.urls)) {
--        entArray = entArray.concat(entities.urls.map(u => ({
--          start: u.indices[0],
--          end: u.indices[1],
--          str: u.url,
--          text: u.display_url || u.url,
--          href: u.expanded_url || u.url})));
--      }
--      if ("user_mentions" in entities &&
--          Array.isArray(entities.user_mentions)) {
--        entArray = entArray.concat(entities.user_mentions.map(um => ({
--          start: um.indices[0],
--          end: um.indices[1],
--          str: "@" + um.screen_name,
--          text: '@<span class="ib-person">' + um.screen_name + "</span>",
--          title: um.name,
--          href: "https://twitter.com/" + um.screen_name})));
--      }
--      entArray.sort((a, b) => a.start - b.start);
--      let offset = 0;
--      for each (let entity in entArray) {
--        let str = text.substring(offset + entity.start, offset + entity.end);
--        if (str[0] == "\uFF20") // @ - unicode character similar to @
--          str = "@" + str.substring(1);
--        if (str[0] == "\uFF03") // # - unicode character similar to #
--          str = "#" + str.substring(1);
--        if (str.toLowerCase() != entity.str.toLowerCase())
--          continue;
--
--        let html = "<a href=\"" + entity.href + "\"";
--        if ("title" in entity)
--          html += " title=\"" + entity.title + "\"";
--        html += ">" + ("text" in entity ? entity.text : entity.str) + "</a>";
--        text = text.slice(0, offset + entity.start) + html +
--               text.slice(offset + entity.end);
--        offset += html.length - (entity.end - entity.start);
--      }
--    }
-+    aMsg.displayMessage = twttr.txt.autoLink(text, {
-+      usernameClass: "ib-person",
-+      usernameIncludeSymbol: true,
-+      // Pass in the url entities so the t.co links are replaced.
-+      urlEntities: tweet.entities.urls.map(function(u) {
-+        let o = Object.assign(u);
-+        // But remove the indices so they apply in the face of modifications.
-+        delete o.indices;
-+        return o;
-+      })
-+    });
- 
--    return text;
-+    GenericConversationPrototype.prepareForDisplaying.apply(this, arguments);
-   },
--  displayTweet: function(aTweet) {
--    let name = aTweet.user.screen_name;
--    this._ensureParticipantExists(name);
--    let text = this.parseTweet(aTweet);
-+  displayTweet: function(aTweet, aUser) {
-+    let name = aUser.screen_name;
- 
--    let flags =
--      name == this._account.name ? {outgoing: true} : {incoming: true};
-+    let flags = name == this.nick ? {outgoing: true} : {incoming: true};
-     flags.time = Math.round(new Date(aTweet.created_at) / 1000);
--    flags._iconURL = aTweet.user.profile_image_url;
-+    flags._iconURL = aUser.profile_image_url;
-     if (aTweet.delayed)
-       flags.delayed = true;
-     if (aTweet.entities && aTweet.entities.user_mentions &&
-@@ -379,7 +276,138 @@ Conversation.prototype = {
-         aTweet.entities.user_mentions.some(mention => mention.screen_name == this.nick))
-       flags.containsNick = true;
- 
--    (new Tweet(aTweet, name, text, flags)).conversation = this;
-+    let tweet = new Tweet(aTweet, name, aTweet.text, flags);
-+    this._tweets.set(tweet.id, tweet);
-+    tweet.conversation = this;
-+  },
-+  _parseError: function(aData) {
-+    let error = "";
-+    try {
-+      let data = JSON.parse(aData);
-+      if ("error" in data)
-+        error = data.error;
-+      else if ("errors" in data)
-+        error = data.errors[0].message;
-+      if (error)
-+        error = "(" + error + ")";
-+    } catch(e) {}
-+    return error;
-+  },
-+  getNormalizedChatBuddyName: (aNick) => aNick.replace(/^@/, "")
-+};
-+
-+function TimelineConversation(aAccount)
-+{
-+  this._init(aAccount);
-+  this._ensureParticipantExists(aAccount.name);
-+  // We need the screen names for the IDs in _friends, but _userInfo is
-+  // indexed by name, so we build an ID -> name map.
-+  let entries = [];
-+  for (let [name, userInfo] of aAccount._userInfo) {
-+    entries.push([userInfo.id_str, name]);
-+  }
-+  let names = new Map(entries);
-+  for (let id_str of aAccount._friends)
-+    this._ensureParticipantExists(names.get(id_str));
-+
-+  // If the user's info has already been received, update the timeline topic.
-+  if (aAccount._userInfo.has(aAccount.name)) {
-+    let userInfo = aAccount._userInfo.get(aAccount.name);
-+    if ("description" in userInfo)
-+      this.setTopic(userInfo.description, aAccount.name, true);
-+  }
-+
-+  // Store messages by message id.
-+  this._tweets = new Map();
-+}
-+TimelineConversation.prototype = {
-+  __proto__: GenericConvChatPrototype,
-+  unInit: function() {
-+    delete this._account._timeline;
-+    GenericConvChatPrototype.unInit.call(this);
-+  },
-+  inReplyToStatusId: null,
-+  startReply: function(aTweet) {
-+    this.inReplyToStatusId = aTweet.id_str;
-+    let entities = aTweet.entities;
-+
-+    // Twitter replies go to all the users mentioned in the tweet.
-+    let nicks = [aTweet.user.screen_name];
-+    if ("user_mentions" in entities && Array.isArray(entities.user_mentions)) {
-+      nicks = nicks.concat(entities.user_mentions
-+                                   .map(um => um.screen_name));
-+    }
-+    // Ignore duplicates and the user's nick.
-+    let prompt =
-+      nicks.filter(function(aNick, aPos) {
-+             return nicks.indexOf(aNick) == aPos && aNick != this._account.name;
-+           }, this)
-+           .map(aNick => "@" + aNick)
-+           .join(" ") + " ";
-+
-+    this.notifyObservers(null, "replying-to-prompt", prompt);
-+    this.notifyObservers(null, "status-text-changed",
-+                         _("replyingToStatusText", aTweet.text));
-+  },
-+  reTweet: function(aTweet) {
-+    this._account.reTweet(aTweet, null, function(aException, aData) {
-+      this.systemMessage(_("error.retweet", this._parseError(aData),
-+                           aTweet.text), true);
-+    }, this);
-+  },
-+  sendMsg: function(aMsg) {
-+    if (this.getTweetLength(aMsg) > kMaxMessageLength) {
-+      this.systemMessage(_("error.tooLong"), true);
-+      throw Cr.NS_ERROR_INVALID_ARG;
-+    }
-+    this._account.tweet(aMsg, this.inReplyToStatusId,
-+                        this.onSentCallback.bind(this, aMsg),
-+                        function(aException, aData) {
-+      let error = this._parseError(aData);
-+      this.systemMessage(_("error.general", error, aMsg), true);
-+    }, this);
-+    this.sendTyping("");
-+  },
-+  like: function(aTweet, aRemoveLike = false) {
-+    this._account.like(aTweet, aRemoveLike, function() {
-+      aTweet.favorited = !aRemoveLike;
-+    }, function(aException, aData) {
-+      const messageName = aRemoveLike ? "unlike" : "like";
-+      this.systemMessage(_("error." + messageName,
-+                          this.parseError(aData), aTweet.text), true);
-+    }, this);
-+  },
-+  sendTyping: function(aString) {
-+    if (aString.length == 0 && this.inReplyToStatusId) {
-+      delete this.inReplyToStatusId;
-+      this.notifyObservers(null, "status-text-changed", "");
-+      return kMaxMessageLength;
-+    }
-+    return kMaxMessageLength - this.getTweetLength(aString);
-+  },
-+  displayMessages: function(aMessages) {
-+    let account = this._account;
-+    let lastMsgId = account._lastMsgId;
-+    for (let tweet of aMessages) {
-+      if (!("user" in tweet) || !("text" in tweet) || !("id_str" in tweet) ||
-+          account._knownMessageIds.has(tweet.id_str))
-+        continue;
-+      let id = tweet.id_str;
-+      // Update the last known message.
-+      // Compare the length of the ids first, and then the text.
-+      // This avoids converting tweet ids into rounded numbers.
-+      if (id.length > lastMsgId.length ||
-+          (id.length == lastMsgId.length && id > lastMsgId))
-+        lastMsgId = id;
-+      account._knownMessageIds.add(id);
-+      account.setUserInfo(tweet.user);
-+      this._ensureParticipantExists(tweet.user.screen_name);
-+      this.displayTweet(tweet, tweet.user);
-+    }
-+    if (lastMsgId != account._lastMsgId) {
-+      account._lastMsgId = lastMsgId;
-+      account.prefs.setCharPref("lastMessageId", account._lastMsgId);
-+    }
-   },
-   _ensureParticipantExists: function(aNick) {
-     if (this._participants.has(aNick))
-@@ -401,6 +429,44 @@ Conversation.prototype = {
-       this._account.setUserDescription(aTopic);
-   }
- };
-+Object.assign(TimelineConversation.prototype, GenericTwitterConversation);
-+
-+function DirectMessageConversation(aAccount, aName)
-+{
-+  this._init(aAccount, aName);
-+
-+  // Store messages by message id.
-+  this._tweets = new Map();
-+}
-+DirectMessageConversation.prototype = {
-+  __proto__: GenericConvIMPrototype,
-+  sendMsg: function(aMsg) {
-+    this._account.directMessage(aMsg, this.name,
-+                                this.onSentCallback.bind(this, aMsg),
-+                                function(aException, aData) {
-+      let error = this._parseError(aData);
-+      this.systemMessage(_("error.general", error, aMsg), true);
-+    }, this);
-+  },
-+  displayMessages: function(aMessages) {
-+    let account = this._account;
-+    for (let tweet of aMessages) {
-+      if (!("sender" in tweet) || !("recipient" in tweet) ||
-+          !("text" in tweet) || !("id_str" in tweet))
-+        continue;
-+      account.setUserInfo(tweet.sender);
-+      account.setUserInfo(tweet.recipient);
-+      this.displayTweet(tweet, tweet.sender);
-+    }
-+  },
-+  unInit: function() {
-+    this._account.removeConversation(this.name);
-+    GenericConvIMPrototype.unInit.call(this);
-+  },
-+  get nick() { return this._account.name; },
-+  set nick(aNick) {}
-+}
-+Object.assign(DirectMessageConversation.prototype, GenericTwitterConversation);
- 
- function Account(aProtocol, aImAccount)
- {
-@@ -408,6 +474,8 @@ function Account(aProtocol, aImAccount)
-   this._knownMessageIds = new Set();
-   this._userInfo = new Map();
-   this._friends = new Set();
-+  // Contains just `DirectMessageConversation`s
-+  this._conversations = new Map();
- }
- Account.prototype = {
-   __proto__: GenericAccountPrototype,
-@@ -535,7 +603,7 @@ Account.prototype = {
-     hmac.init(hmac.SHA1,
-               keyFactory.keyFromString(Ci.nsIKeyObject.HMAC, signatureKey));
-     // No UTF-8 encoding, special chars are already escaped.
--    let bytes = [b.charCodeAt() for each (b in signatureBase)];
-+    let bytes = [...signatureBase].map(b => b.charCodeAt());
-     hmac.update(bytes, bytes.length);
-     let signature = hmac.finish(true);
- 
-@@ -578,6 +646,17 @@ Account.prototype = {
-     let url = "1.1/statuses/destroy/" + aTweet.id_str + ".json";
-     this.signAndSend(url, null, [], aOnSent, aOnError, aThis);
-   },
-+  directMessage: function(aMsg, aName, aOnSent, aOnError, aThis) {
-+    let POSTData = [["text", aMsg], ["screen_name", aName]];
-+    this.signAndSend("1.1/direct_messages/new.json", null, POSTData, aOnSent,
-+                     aOnError, aThis);
-+  },
-+  like: function(aTweet, aRemoveLike, aOnSent, aOnError, aThis) {
-+    const action = aRemoveLike ? "destroy" : "create";
-+    const url = `1.1/favorites/${action}.json`;
-+    const POSTData = [["id", aTweet.id_str]];
-+    this.signAndSend(url, null, POSTData, aOnSent, aOnError, aThis);
-+  },
- 
-   _friends: null,
-   follow: function(aUserName) {
-@@ -640,29 +719,7 @@ Account.prototype = {
-     }
-   },
- 
--  get timeline() { return this._timeline || (this._timeline = new Conversation(this)); },
--  displayMessages: function(aMessages) {
--    let lastMsgId = this._lastMsgId;
--    for each (let tweet in aMessages) {
--      if (!("user" in tweet) || !("text" in tweet) || !("id_str" in tweet) ||
--          this._knownMessageIds.has(tweet.id_str))
--        continue;
--      let id = tweet.id_str;
--      // Update the last known message.
--      // Compare the length of the ids first, and then the text.
--      // This avoids converting tweet ids into rounded numbers.
--      if (id.length > lastMsgId.length ||
--          (id.length == lastMsgId.length && id > lastMsgId))
--        lastMsgId = id;
--      this._knownMessageIds.add(id);
--      this.setUserInfo(tweet.user);
--      this.timeline.displayTweet(tweet);
--    }
--    if (lastMsgId != this._lastMsgId) {
--      this._lastMsgId = lastMsgId;
--      this.prefs.setCharPref("lastMessageId", this._lastMsgId);
--    }
--  },
-+  get timeline() { return this._timeline || (this._timeline = new TimelineConversation(this)); },
- 
-   onTimelineError: function(aError, aResponseText, aRequest) {
-     this.ERROR(aError);
-@@ -710,7 +767,7 @@ Account.prototype = {
- 
-     this._timelineBuffer.sort(this.sortByDate);
-     this._timelineBuffer.forEach(aTweet => aTweet.delayed = true);
--    this.displayMessages(this._timelineBuffer);
-+    this.timeline.displayMessages(this._timelineBuffer);
- 
-     // Fetch userInfo for the user if we don't already have it.
-     this.requestBuddyInfo(this.name);
-@@ -765,7 +822,7 @@ Account.prototype = {
-       this.DEBUG("Received ping");
-     let messages = newText.split(/\r\n?/);
-     this._pendingData = messages.pop();
--    for each (let message in messages) {
-+    for (let message of messages) {
-       if (!message.trim())
-         continue;
-       let msg;
-@@ -775,13 +832,18 @@ Account.prototype = {
-         this.ERROR(e + " while parsing " + message);
-         continue;
-       }
--      if ("text" in msg)
--        this.displayMessages([msg]);
-+      if ("direct_message" in msg) {
-+        let dm = msg["direct_message"];
-+        if (dm.sender_screen_name !== this.name)  // These are displayed on send.
-+          this.getConversation(dm.sender_screen_name).displayMessages([dm]);
-+      }
-+      else if ("text" in msg)
-+        this.timeline.displayMessages([msg]);
-       else if ("friends" in msg) {
-         // Filter out the IDs that info has already been received from (e.g. a
-         // tweet has been received as part of the timeline request).
-         let userInfoIds = new Set();
--        for each (let userInfo in this._userInfo)
-+        for (let userInfo of this._userInfo.values())
-           userInfoIds.add(userInfo.id_str);
-         let ids = msg.friends.filter(
-           aId => !userInfoIds.has(aId.toString()));
-@@ -913,10 +975,11 @@ Account.prototype = {
-   finishAuthorizationRequest: function() {
-     // Clean up the cookies, so that several twitter OAuth dialogs can work
-     // during the same session (bug 954308).
--    let cookies = Services.cookies.getCookiesFromHost("twitter.com");
-+    let cookies = Services.cookies.getCookiesFromHost("twitter.com", {});
-     while (cookies.hasMoreElements()) {
-       let cookie = cookies.getNext().QueryInterface(Ci.nsICookie2);
--      Services.cookies.remove(cookie.host, cookie.name, cookie.path, false);
-+      Services.cookies.remove(cookie.host, cookie.name, cookie.path, false,
-+                              cookie.originAttributes);
-     }
- 
-     if (!("_browserRequest" in this))
-@@ -977,7 +1040,7 @@ Account.prototype = {
-   cleanUp: function() {
-     this.finishAuthorizationRequest();
-     if (this._pendingRequests.length != 0) {
--      for each (let request in this._pendingRequests)
-+      for (let request of this._pendingRequests)
-         request.abort();
-       delete this._pendingRequests;
-     }
-@@ -1114,7 +1177,7 @@ Account.prototype = {
-   // create the participant.
-   onLookupReceived: function(aData) {
-     let users = JSON.parse(aData);
--    for each (let user in users) {
-+    for (let user of users) {
-       this.setUserInfo(user);
-       this.timeline._ensureParticipantExists(user.screen_name);
-     }
-@@ -1129,6 +1192,19 @@ Account.prototype = {
-   joinChat: function(aComponents) {
-     // The 'timeline' getter opens a timeline conversation if none exists.
-     this.timeline;
-+  },
-+
-+  getConversation: function(aName) {
-+    if (!this._conversations.has(aName))
-+      this._conversations.set(aName, new DirectMessageConversation(this, aName));
-+    return this._conversations.get(aName);
-+  },
-+  removeConversation: function(aName) {
-+    if (this._conversations.has(aName))
-+      this._conversations.delete(aName);
-+  },
-+  createConversation: function(aName) {
-+    return this.getConversation(aName);
-   }
- };
- 
--- 
-2.12.2
-
diff --git a/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch b/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch
deleted file mode 100644
index c6e5d1c..0000000
--- a/projects/instantbird/0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From eccb5b4b6c09fa2fd8f6da0bfa915afe79ebddcf Mon Sep 17 00:00:00 2001
-From: Nihanth Subramanya <nhnt11 at gmail.com>
-Date: Sun, 9 Oct 2016 21:53:04 -0700
-Subject: [PATCH 06/28] Bug 1218193 - Fix tab strip background colour on OS X.
- r=aleth
-
----
- im/themes/tabbrowser-pinstripe/tabbrowser.css | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/im/themes/tabbrowser-pinstripe/tabbrowser.css b/im/themes/tabbrowser-pinstripe/tabbrowser.css
-index 76c5094e3..291545039 100644
---- a/im/themes/tabbrowser-pinstripe/tabbrowser.css
-+++ b/im/themes/tabbrowser-pinstripe/tabbrowser.css
-@@ -208,7 +208,7 @@ statusbarpanel#statusbar-display {
- }
- 
- .tabbrowser-strip {
--  -moz-appearance: -moz-mac-unified-toolbar;
-+  -moz-appearance: toolbar;
-   height: 26px;
-   background-repeat: repeat-x;
- }
--- 
-2.12.2
-
diff --git a/projects/instantbird/0011-Account-picture.patch b/projects/instantbird/0006-Remove-option-for-configuring-account-picture.patch
similarity index 81%
rename from projects/instantbird/0011-Account-picture.patch
rename to projects/instantbird/0006-Remove-option-for-configuring-account-picture.patch
index 88907e6..ddea539 100644
--- a/projects/instantbird/0011-Account-picture.patch
+++ b/projects/instantbird/0006-Remove-option-for-configuring-account-picture.patch
@@ -1,14 +1,14 @@
-From 70b53480506595d02d5b0ede56501ef9ec48919f Mon Sep 17 00:00:00 2001
+From 1e652fd4e70fd6ffce2dec9be8ed2826b2607406 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:24:09 -0700
-Subject: [PATCH 11/28] Account picture
+Subject: [PATCH 06/20] Remove option for configuring account picture
 
 ---
  im/content/blist.xul | 3 +--
  1 file changed, 1 insertion(+), 2 deletions(-)
 
 diff --git a/im/content/blist.xul b/im/content/blist.xul
-index b90fddadb..f29a48b99 100644
+index 843f1eef57..71ee2c9ef8 100644
 --- a/im/content/blist.xul
 +++ b/im/content/blist.xul
 @@ -114,8 +114,7 @@
@@ -22,5 +22,5 @@ index b90fddadb..f29a48b99 100644
          <panel id="changeUserIconPanel"
                 type="arrow" align="center"
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch b/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch
deleted file mode 100644
index 23a8716..0000000
--- a/projects/instantbird/0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch
+++ /dev/null
@@ -1,26 +0,0 @@
-From 22d64ca4c9ec08609cdcf78ed6b969522217c256 Mon Sep 17 00:00:00 2001
-From: Arlo Breault <arlolra at gmail.com>
-Date: Sun, 9 Oct 2016 21:57:07 -0700
-Subject: [PATCH 07/28] Bug 1246431 - XMPP createConversation should handle
- incoming messages from the server properly. r=aleth
-
----
- chat/protocols/xmpp/xmpp.jsm | 2 +-
- 1 file changed, 1 insertion(+), 1 deletion(-)
-
-diff --git a/chat/protocols/xmpp/xmpp.jsm b/chat/protocols/xmpp/xmpp.jsm
-index 282575938..71f777009 100644
---- a/chat/protocols/xmpp/xmpp.jsm
-+++ b/chat/protocols/xmpp/xmpp.jsm
-@@ -2108,7 +2108,7 @@ var XMPPAccountPrototype = {
- 
-     // Checking that the aName can be parsed and is not broken.
-     let jid = this._parseJID(convName);
--    if (!jid || !jid.node || (isMucParticipant && !jid.resource)) {
-+    if (!jid || !jid.domain || (isMucParticipant && (!jid.node || !jid.resource))) {
-       this.ERROR("Could not create conversation as jid is broken: " + convName);
-       throw "Invalid JID";
-     }
--- 
-2.12.2
-
diff --git a/projects/instantbird/0012-Modify-protocol-defaults.patch b/projects/instantbird/0007-Modify-top-protocol-defaults.patch
similarity index 70%
rename from projects/instantbird/0012-Modify-protocol-defaults.patch
rename to projects/instantbird/0007-Modify-top-protocol-defaults.patch
index 79ca55e..83428fa 100644
--- a/projects/instantbird/0012-Modify-protocol-defaults.patch
+++ b/projects/instantbird/0007-Modify-top-protocol-defaults.patch
@@ -1,21 +1,18 @@
-From 2d8c5549ba5c0aa71a166bc504c431edab8f755f Mon Sep 17 00:00:00 2001
+From 38a38fc162111ed0a9983ceefccbdbac81e73bcc Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Mon, 10 Oct 2016 19:25:34 -0700
-Subject: [PATCH 12/28] Modify protocol defaults
+Date: Wed, 26 Jul 2017 16:16:09 -0400
+Subject: [PATCH 07/20] Modify top protocol defaults
 
- * Top protocols
-
- * Hide get protocols
 ---
  im/content/accountWizard.xul                                 | 2 +-
- im/locales/en-US/chrome/instantbird/accountWizard.properties | 4 +++-
- 2 files changed, 4 insertions(+), 2 deletions(-)
+ im/locales/en-US/chrome/instantbird/accountWizard.properties | 2 ++
+ 2 files changed, 3 insertions(+), 1 deletion(-)
 
 diff --git a/im/content/accountWizard.xul b/im/content/accountWizard.xul
-index de9d0d809..cce8a1ba9 100644
+index 135b68386c..356321dbcc 100644
 --- a/im/content/accountWizard.xul
 +++ b/im/content/accountWizard.xul
-@@ -50,7 +50,7 @@
+@@ -51,7 +51,7 @@
      <listbox flex="1" id="protolist"
               ondblclick="document.getElementById('accountWizard').advance();"/>
      <hbox pack="end">
@@ -25,16 +22,10 @@ index de9d0d809..cce8a1ba9 100644
      </hbox>
    </wizardpage>
 diff --git a/im/locales/en-US/chrome/instantbird/accountWizard.properties b/im/locales/en-US/chrome/instantbird/accountWizard.properties
-index d552a232b..7d371bd21 100644
+index efb0b77aee..83f807181f 100644
 --- a/im/locales/en-US/chrome/instantbird/accountWizard.properties
 +++ b/im/locales/en-US/chrome/instantbird/accountWizard.properties
-@@ -8,11 +8,13 @@
- # Exceeding 4 protocols may cause scrolling. A list of the
- # available protocols can be found at
- #     https://wiki.instantbird.org/Protocol_Identifiers
--topProtocol.list=prpl-gtalk,prpl-twitter,prpl-aim,prpl-yahoo,prpl-irc
-+topProtocol.list=prpl-irc,prpl-jabber,prpl-twitter,prpl-gtalk
- 
+@@ -13,6 +13,8 @@ topProtocol.list=prpl-gtalk,prpl-twitter,prpl-aim,prpl-irc,prpl-jabber
  # LOCALIZATION NOTE
  # These are the descriptions of the top protocols specified above.
  # A description should be provided for each protocol ID listed above.
@@ -44,5 +35,5 @@ index d552a232b..7d371bd21 100644
  topProtocol.prpl-twitter.description=Stay up to date with your Twitter timeline
  topProtocol.prpl-aim.description=Chat with your buddies on AOL Instant Messenger
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0013-Modify-IRC-defaults.patch b/projects/instantbird/0008-Modify-IRC-defaults.patch
similarity index 89%
rename from projects/instantbird/0013-Modify-IRC-defaults.patch
rename to projects/instantbird/0008-Modify-IRC-defaults.patch
index 1ae35e4..3f2e33f 100644
--- a/projects/instantbird/0013-Modify-IRC-defaults.patch
+++ b/projects/instantbird/0008-Modify-IRC-defaults.patch
@@ -1,7 +1,7 @@
-From 37f684af18a7d1926960090bb3148d520312abbd Mon Sep 17 00:00:00 2001
+From a6b4c0169258cdbac8efe64456ac8d9fbe6bb468 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:31:58 -0700
-Subject: [PATCH 13/28] Modify IRC defaults
+Subject: [PATCH 08/20] Modify IRC defaults
 
  * ctcp ping
 
@@ -14,10 +14,10 @@ Subject: [PATCH 13/28] Modify IRC defaults
  2 files changed, 3 insertions(+), 15 deletions(-)
 
 diff --git a/chat/protocols/irc/irc.js b/chat/protocols/irc/irc.js
-index 35165e9a9..c2167a5ec 100644
+index 4f056274bd..d7d5db4a99 100644
 --- a/chat/protocols/irc/irc.js
 +++ b/chat/protocols/irc/irc.js
-@@ -1931,7 +1931,7 @@ ircProtocol.prototype = {
+@@ -1953,7 +1953,7 @@ ircProtocol.prototype = {
  
    usernameSplits: [
      {get label() { return _("options.server"); }, separator: "@",
@@ -27,7 +27,7 @@ index 35165e9a9..c2167a5ec 100644
  
    options: {
 diff --git a/chat/protocols/irc/ircCTCP.jsm b/chat/protocols/irc/ircCTCP.jsm
-index 28eb374f4..120be10ee 100644
+index 43ed2ced4b..c2f16bee84 100644
 --- a/chat/protocols/irc/ircCTCP.jsm
 +++ b/chat/protocols/irc/ircCTCP.jsm
 @@ -167,19 +167,7 @@ var ctcpBase = {
@@ -61,5 +61,5 @@ index 28eb374f4..120be10ee 100644
                   ". Sending TIME response: \"" + now + "\".");
          this.sendCTCPMessage(aMessage.origin, true, "TIME", ":" + now);
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0009-Do-not-set-default-XMPP-server.patch b/projects/instantbird/0009-Do-not-set-default-XMPP-server.patch
new file mode 100644
index 0000000..7be234d
--- /dev/null
+++ b/projects/instantbird/0009-Do-not-set-default-XMPP-server.patch
@@ -0,0 +1,25 @@
+From 8a766e365c6dca55dec95cae000f6c30054b8467 Mon Sep 17 00:00:00 2001
+From: Sukhbir Singh <sukhbir at torproject.org>
+Date: Fri, 28 Jul 2017 12:11:57 -0400
+Subject: [PATCH 09/20] Do not set default XMPP server
+
+---
+ chat/protocols/xmpp/xmpp.js | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/chat/protocols/xmpp/xmpp.js b/chat/protocols/xmpp/xmpp.js
+index 2afb15f059..1d2c167d3e 100644
+--- a/chat/protocols/xmpp/xmpp.js
++++ b/chat/protocols/xmpp/xmpp.js
+@@ -31,7 +31,7 @@ XMPPProtocol.prototype = {
+ 
+   usernameSplits: [
+     {get label() { return _("options.domain"); }, separator: "@",
+-     defaultValue: "jabber.org", reverse: true}
++     defaultValue: "", reverse: true}
+   ],
+ 
+   options: {
+-- 
+2.13.3
+
diff --git a/projects/instantbird/0014-Modify-themes.patch b/projects/instantbird/0010-Modify-themes.patch
similarity index 92%
rename from projects/instantbird/0014-Modify-themes.patch
rename to projects/instantbird/0010-Modify-themes.patch
index 1cc0b5e..4a036d6 100644
--- a/projects/instantbird/0014-Modify-themes.patch
+++ b/projects/instantbird/0010-Modify-themes.patch
@@ -1,9 +1,9 @@
-From 4fb4d944d10666356408cbb222b38344496dc71a Mon Sep 17 00:00:00 2001
+From bc8f0f3298a6c69f381ae1640ae93e770259e65a Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:36:38 -0700
-Subject: [PATCH 14/28] Modify themes
+Subject: [PATCH 10/20] Modify themes
 
- * theme extension updateh
+ * theme extension update
 
  * themes remove links
 ---
@@ -13,7 +13,7 @@ Subject: [PATCH 14/28] Modify themes
  3 files changed, 2 insertions(+), 19 deletions(-)
 
 diff --git a/im/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf b/im/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
-index a7e38bba4..c5c781a97 100644
+index a7e38bba47..c5c781a973 100644
 --- a/im/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 +++ b/im/app/profile/extensions/{972ce4c6-7e08-4474-a285-3208198ce6fd}/install.rdf
 @@ -26,6 +26,8 @@
@@ -26,7 +26,7 @@ index a7e38bba4..c5c781a97 100644
      <!-- EXTENSION AUTHORS!
           DO NOT COPY THIS PROPERTY INTO YOUR INSTALL RDF FILES
 diff --git a/im/content/preferences/themes.js b/im/content/preferences/themes.js
-index 5c5d594cb..4a9d6afd0 100644
+index 5c5d594cb5..4a9d6afd09 100644
 --- a/im/content/preferences/themes.js
 +++ b/im/content/preferences/themes.js
 @@ -31,21 +31,6 @@ var gThemePane = {
@@ -52,7 +52,7 @@ index 5c5d594cb..4a9d6afd0 100644
  
    /* Create the drop down list for emoticons and messagestyles;
 diff --git a/im/content/preferences/themes.xul b/im/content/preferences/themes.xul
-index 454e36696..18ba1f95c 100644
+index 454e366960..18ba1f95cc 100644
 --- a/im/content/preferences/themes.xul
 +++ b/im/content/preferences/themes.xul
 @@ -65,8 +65,6 @@
@@ -74,5 +74,5 @@ index 454e36696..18ba1f95c 100644
            <separator class="thin"/>
            <description>&emoticonsPreview.description;</description>
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0016-Remove-logging-UI.patch b/projects/instantbird/0011-Remove-logging-UI.patch
similarity index 91%
rename from projects/instantbird/0016-Remove-logging-UI.patch
rename to projects/instantbird/0011-Remove-logging-UI.patch
index 19d1145..822b86c 100644
--- a/projects/instantbird/0016-Remove-logging-UI.patch
+++ b/projects/instantbird/0011-Remove-logging-UI.patch
@@ -1,14 +1,14 @@
-From 2429558476e6e13af0a38789111e5b9c0494d73a Mon Sep 17 00:00:00 2001
+From 866ec2d04c3026066fca270667d4e3eba2e6ae88 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:50:48 -0700
-Subject: [PATCH 16/28] Remove logging UI
+Subject: [PATCH 11/20] Remove logging UI
 
 ---
  im/content/preferences/privacy.xul | 20 --------------------
  1 file changed, 20 deletions(-)
 
 diff --git a/im/content/preferences/privacy.xul b/im/content/preferences/privacy.xul
-index 7c9db1cdd..2d7b2701e 100644
+index 7c9db1cdd8..2d7b2701ea 100644
 --- a/im/content/preferences/privacy.xul
 +++ b/im/content/preferences/privacy.xul
 @@ -66,26 +66,6 @@
@@ -39,5 +39,5 @@ index 7c9db1cdd..2d7b2701e 100644
      <groupbox id="passwordsGroup" orient="vertical">
        <caption label="&passwords.label;"/>
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0017-Cert-override.patch b/projects/instantbird/0012-Cert-override.patch
similarity index 86%
rename from projects/instantbird/0017-Cert-override.patch
rename to projects/instantbird/0012-Cert-override.patch
index 7a7f6ef..86f5acf 100644
--- a/projects/instantbird/0017-Cert-override.patch
+++ b/projects/instantbird/0012-Cert-override.patch
@@ -1,7 +1,7 @@
-From 655a4f263afff106dc087fac917ae56c5720035b Mon Sep 17 00:00:00 2001
+From 6d7ae07b5b740fe9c00191c0fb747920ba7708de Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:56:46 -0700
-Subject: [PATCH 17/28] Cert override
+Subject: [PATCH 12/20] Cert override
 
 ---
  im/app/profile/cert_override.txt | 3 +++
@@ -13,7 +13,7 @@ Subject: [PATCH 17/28] Cert override
 
 diff --git a/im/app/profile/cert_override.txt b/im/app/profile/cert_override.txt
 new file mode 100644
-index 000000000..4e616f6cf
+index 0000000000..4e616f6cf1
 --- /dev/null
 +++ b/im/app/profile/cert_override.txt
 @@ -0,0 +1,3 @@
@@ -21,7 +21,7 @@ index 000000000..4e616f6cf
 +# This is a generated file!  Do not edit.
 +jabber.ccc.de:5222	OID.2.16.840.1.101.3.4.2.1	59:2F:46:18:35:27:AB:40:83:88:82:AB:4C:B4:AE:F4:E2:CF:91:60:74:AB:01:F9:BC:24:39:31:CA:5C:4E:D1	U	AAAAAAAAAAAAAAADAAAAexFL3TB5MRAwDgYDVQQKEwdSb290IENBMR4wHAYDVQQL  ExVodHRwOi8vd3d3LmNhY2VydC5vcmcxIjAgBgNVBAMTGUNBIENlcnQgU2lnbmlu  ZyBBdXRob3JpdHkxITAfBgkqhkiG9w0BCQEWEnN1cHBvcnRAY2FjZXJ0Lm9yZw==
 diff --git a/im/app/profile/moz.build b/im/app/profile/moz.build
-index 46bc16bd1..b7d4ebd4b 100644
+index 46bc16bd1b..b7d4ebd4b2 100644
 --- a/im/app/profile/moz.build
 +++ b/im/app/profile/moz.build
 @@ -9,6 +9,7 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('gtk2', 'gtk3', 'mac', 'cocoa'):
@@ -33,10 +33,10 @@ index 46bc16bd1..b7d4ebd4b 100644
      'mimeTypes.rdf',
  ]
 diff --git a/im/installer/Makefile.in b/im/installer/Makefile.in
-index 25dd67617..5f06e784c 100644
+index 88757c6756..54b8bcc1f4 100644
 --- a/im/installer/Makefile.in
 +++ b/im/installer/Makefile.in
-@@ -109,7 +109,9 @@ MOZ_PKG_MAC_ICON=branding/disk.icns
+@@ -121,7 +121,9 @@ MOZ_PKG_MAC_ICON=branding/disk.icns
  MOZ_PKG_MAC_EXTRA=--symlink "/Applications:/ "
  endif
  
@@ -48,10 +48,10 @@ index 25dd67617..5f06e784c 100644
  INSTALL_SDK = 1
  
 diff --git a/im/installer/package-manifest.in b/im/installer/package-manifest.in
-index 1174b3dfd..3e35a2e1b 100644
+index def78c809c..614d52bca2 100644
 --- a/im/installer/package-manifest.in
 +++ b/im/installer/package-manifest.in
-@@ -160,6 +160,7 @@
+@@ -161,6 +161,7 @@
  @RESPATH@/defaults/profile/localstore.rdf
  @RESPATH@/defaults/profile/prefs.js
  @RESPATH@/defaults/profile/mimeTypes.rdf
@@ -60,5 +60,5 @@ index 1174b3dfd..3e35a2e1b 100644
  #ifdef XP_MACOSX
  @RESPATH@/components/ibDockBadge.js
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0018-Display-all-traffic-over-Tor.patch b/projects/instantbird/0013-Display-all-traffic-over-Tor.patch
similarity index 87%
rename from projects/instantbird/0018-Display-all-traffic-over-Tor.patch
rename to projects/instantbird/0013-Display-all-traffic-over-Tor.patch
index c319138..5c4e60c 100644
--- a/projects/instantbird/0018-Display-all-traffic-over-Tor.patch
+++ b/projects/instantbird/0013-Display-all-traffic-over-Tor.patch
@@ -1,7 +1,7 @@
-From d5874c98daf8d4e7304876cd6fa6083c54c0c644 Mon Sep 17 00:00:00 2001
+From c128779e0d663506a06d15550597f4d52e45eda5 Mon Sep 17 00:00:00 2001
 From: Sukhbir Singh <sukhbir at torproject.org>
 Date: Mon, 10 Oct 2016 19:58:31 -0700
-Subject: [PATCH 18/28] Display all traffic over Tor
+Subject: [PATCH 13/20] Display all traffic over Tor
 
 ---
  im/content/accountWizard.xul                          | 2 ++
@@ -9,10 +9,10 @@ Subject: [PATCH 18/28] Display all traffic over Tor
  2 files changed, 3 insertions(+)
 
 diff --git a/im/content/accountWizard.xul b/im/content/accountWizard.xul
-index cce8a1ba9..fcc5eaa01 100644
+index 356321dbcc..73c9d93777 100644
 --- a/im/content/accountWizard.xul
 +++ b/im/content/accountWizard.xul
-@@ -39,6 +39,8 @@
+@@ -40,6 +40,8 @@
          <description class="top-proto-description" value="&accountProtocolShowMore.description;"/>
        </richlistitem>
      </richlistbox>
@@ -22,7 +22,7 @@ index cce8a1ba9..fcc5eaa01 100644
  
    <wizardpage id="accountprotocol" pageid="accountprotocol" next="accountusername"
 diff --git a/im/locales/en-US/chrome/instantbird/accountWizard.dtd b/im/locales/en-US/chrome/instantbird/accountWizard.dtd
-index c46fb2f95..6b49c84fa 100644
+index c46fb2f956..6b49c84fad 100644
 --- a/im/locales/en-US/chrome/instantbird/accountWizard.dtd
 +++ b/im/locales/en-US/chrome/instantbird/accountWizard.dtd
 @@ -6,6 +6,7 @@
@@ -34,5 +34,5 @@ index c46fb2f95..6b49c84fa 100644
  <!ENTITY accountProtocolShowMore.label  "Show all protocols">
  <!ENTITY accountProtocolShowMore.description  "Choose from the full list of protocols">
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0019-Trac-17480-Content-sink.patch b/projects/instantbird/0014-Trac-17480-Content-sink.patch
similarity index 93%
rename from projects/instantbird/0019-Trac-17480-Content-sink.patch
rename to projects/instantbird/0014-Trac-17480-Content-sink.patch
index e9ab1ee..9f0d48d 100644
--- a/projects/instantbird/0019-Trac-17480-Content-sink.patch
+++ b/projects/instantbird/0014-Trac-17480-Content-sink.patch
@@ -1,7 +1,7 @@
-From 30751b0288d46103956b395e68b906e5e4e40bfe Mon Sep 17 00:00:00 2001
+From 9e6b44bf88fc19991a927b93e57997dfb8265bd2 Mon Sep 17 00:00:00 2001
 From: Arlo Breault <arlolra at gmail.com>
 Date: Wed, 5 Oct 2016 11:09:25 -0700
-Subject: [PATCH 19/28] Trac 17480: Content sink
+Subject: [PATCH 14/20] Trac 17480: Content sink
 
 ---
  chat/modules/imContentSink.jsm     | 33 ++++++---------------------------
@@ -9,7 +9,7 @@ Subject: [PATCH 19/28] Trac 17480: Content sink
  2 files changed, 7 insertions(+), 28 deletions(-)
 
 diff --git a/chat/modules/imContentSink.jsm b/chat/modules/imContentSink.jsm
-index abd95fc71..fa32442e4 100644
+index 07ab18ce8d..b77678c3dc 100644
 --- a/chat/modules/imContentSink.jsm
 +++ b/chat/modules/imContentSink.jsm
 @@ -42,7 +42,7 @@ this.EXPORTED_SYMBOLS = [
@@ -94,7 +94,7 @@ index abd95fc71..fa32442e4 100644
    return kModes[baseNum];
  }
 diff --git a/im/content/preferences/content.xul b/im/content/preferences/content.xul
-index 3b8ccfa2b..ba41da76a 100644
+index 3b8ccfa2b3..ba41da76aa 100644
 --- a/im/content/preferences/content.xul
 +++ b/im/content/preferences/content.xul
 @@ -35,7 +35,7 @@
@@ -107,5 +107,5 @@ index 3b8ccfa2b..ba41da76a 100644
            <menuitem value="0" label="&filterLevelNone;"/>
          </menupopup>
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0015-Modify-XMPP-defaults.patch b/projects/instantbird/0015-Modify-XMPP-defaults.patch
deleted file mode 100644
index d7c7579..0000000
--- a/projects/instantbird/0015-Modify-XMPP-defaults.patch
+++ /dev/null
@@ -1,48 +0,0 @@
-From 7c0ab255fb151bf52479c6b4a6f9fe8d423155ac Mon Sep 17 00:00:00 2001
-From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Mon, 10 Oct 2016 19:38:49 -0700
-Subject: [PATCH 15/28] Modify XMPP defaults
-
- * xmpp-default-domain
-
- * xmpp-gtalk-resource
----
- chat/protocols/gtalk/gtalk.js | 2 +-
- chat/protocols/xmpp/xmpp.js   | 4 ++--
- 2 files changed, 3 insertions(+), 3 deletions(-)
-
-diff --git a/chat/protocols/gtalk/gtalk.js b/chat/protocols/gtalk/gtalk.js
-index 8bce0c9b4..642f4561d 100644
---- a/chat/protocols/gtalk/gtalk.js
-+++ b/chat/protocols/gtalk/gtalk.js
-@@ -96,7 +96,7 @@ GTalkProtocol.prototype = {
-   getAccount: function(aImAccount) { return new GTalkAccount(this, aImAccount); },
-   options: {
-     resource: {get label() { return _("options.resource"); },
--               get default() { return XMPPDefaultResource; }}
-+               default: "Instantbird"},
-   },
-   get chatHasTopic() { return true; },
-   classID: Components.ID("{38a224c1-6748-49a9-8ab2-efc362b1000d}")
-diff --git a/chat/protocols/xmpp/xmpp.js b/chat/protocols/xmpp/xmpp.js
-index 265445a18..a5635cae3 100644
---- a/chat/protocols/xmpp/xmpp.js
-+++ b/chat/protocols/xmpp/xmpp.js
-@@ -31,12 +31,12 @@ XMPPProtocol.prototype = {
- 
-   usernameSplits: [
-     {get label() { return _("options.domain"); }, separator: "@",
--     defaultValue: "jabber.org", reverse: true}
-+     defaultValue: "", reverse: true}
-   ],
- 
-   options: {
-     resource: {get label() { return _("options.resource"); },
--               get default() { return XMPPDefaultResource; }},
-+               default: "Instantbird"},
-     priority: {get label() { return _("options.priority"); }, default: 0},
-     connection_security: {
-       get label() { return _("options.connectionSecurity"); },
--- 
-2.12.2
-
diff --git a/projects/instantbird/0020-SASL-ECDSA-NIST256P-CHALLENGE.patch b/projects/instantbird/0015-SASL-ECDSA-NIST256P-CHALLENGE.patch
similarity index 99%
rename from projects/instantbird/0020-SASL-ECDSA-NIST256P-CHALLENGE.patch
rename to projects/instantbird/0015-SASL-ECDSA-NIST256P-CHALLENGE.patch
index 86a4dbb..34df8e0 100644
--- a/projects/instantbird/0020-SASL-ECDSA-NIST256P-CHALLENGE.patch
+++ b/projects/instantbird/0015-SASL-ECDSA-NIST256P-CHALLENGE.patch
@@ -1,7 +1,7 @@
-From 0a32b351472debfa5a80309eec7037889725164a Mon Sep 17 00:00:00 2001
+From 922ce3cce4c756d64e9e95f8a3b9876db04b0d0e Mon Sep 17 00:00:00 2001
 From: Arlo Breault <arlolra at gmail.com>
 Date: Sun, 2 Oct 2016 08:46:55 -0700
-Subject: [PATCH 20/28] SASL ECDSA-NIST256P-CHALLENGE
+Subject: [PATCH 15/20] SASL ECDSA-NIST256P-CHALLENGE
 
 ---
  chat/components/src/imAccounts.js |    1 +
@@ -12,7 +12,7 @@ Subject: [PATCH 20/28] SASL ECDSA-NIST256P-CHALLENGE
  create mode 100644 chat/protocols/irc/elliptic.jsm
 
 diff --git a/chat/components/src/imAccounts.js b/chat/components/src/imAccounts.js
-index 5bfea57f2..da8525ffd 100644
+index a1bf1a803f..7b5a3ab040 100644
 --- a/chat/components/src/imAccounts.js
 +++ b/chat/components/src/imAccounts.js
 @@ -193,6 +193,7 @@ function imAccount(aKey, aName, aPrplId)
@@ -25,7 +25,7 @@ index 5bfea57f2..da8525ffd 100644
    id: "",
 diff --git a/chat/protocols/irc/elliptic.jsm b/chat/protocols/irc/elliptic.jsm
 new file mode 100644
-index 000000000..bccab018c
+index 0000000000..bccab018ca
 --- /dev/null
 +++ b/chat/protocols/irc/elliptic.jsm
 @@ -0,0 +1,8748 @@
@@ -8779,7 +8779,7 @@ index 000000000..bccab018c
 +var elliptic = window.elliptic;
 \ No newline at end of file
 diff --git a/chat/protocols/irc/ircSASL.jsm b/chat/protocols/irc/ircSASL.jsm
-index 561f055e0..8a2bd70aa 100644
+index 561f055e0a..8a2bd70aad 100644
 --- a/chat/protocols/irc/ircSASL.jsm
 +++ b/chat/protocols/irc/ircSASL.jsm
 @@ -14,6 +14,43 @@ var Cu = Components.utils;
@@ -8903,7 +8903,7 @@ index 561f055e0..8a2bd70aa 100644
  
        return true;
 diff --git a/chat/protocols/irc/moz.build b/chat/protocols/irc/moz.build
-index bc2539687..e46815dfe 100644
+index bc25396873..e46815dfe3 100644
 --- a/chat/protocols/irc/moz.build
 +++ b/chat/protocols/irc/moz.build
 @@ -11,6 +11,7 @@ EXTRA_COMPONENTS += [
@@ -8915,5 +8915,5 @@ index bc2539687..e46815dfe 100644
      'ircCAP.jsm',
      'ircCommands.jsm',
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0025-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch b/projects/instantbird/0016-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
similarity index 87%
rename from projects/instantbird/0025-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
rename to projects/instantbird/0016-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
index 5a44508..51af131 100644
--- a/projects/instantbird/0025-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
+++ b/projects/instantbird/0016-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
@@ -1,7 +1,7 @@
-From 8479e9cddfebf6cde81f3ca0be615da48bb923a8 Mon Sep 17 00:00:00 2001
+From d1781352b4a94423900802fecd87e33e87e50cbd Mon Sep 17 00:00:00 2001
 From: Arlo Breault <arlolra at gmail.com>
-Date: Thu, 1 Dec 2016 13:25:42 -0800
-Subject: [PATCH 25/28] Bug 1321641 - Use built-in functions instead of an svg
+Date: Wed, 26 Jul 2017 17:14:19 -0400
+Subject: [PATCH 16/20] Bug 1321641 - Use built-in functions instead of an svg
  for bubbles filter
 
 ---
@@ -12,10 +12,10 @@ Subject: [PATCH 25/28] Bug 1321641 - Use built-in functions instead of an svg
  delete mode 100644 im/themes/messages/bubbles/bubbles.svg
 
 diff --git a/im/themes/jar.mn b/im/themes/jar.mn
-index e422619d4..e39f5dcd8 100644
+index fab7580e22..bfedd82546 100644
 --- a/im/themes/jar.mn
 +++ b/im/themes/jar.mn
-@@ -268,7 +268,6 @@ instantbird.jar:
+@@ -266,7 +266,6 @@ instantbird.jar:
  	skin/classic/instantbird/messages/bubbles/Bitmaps/minus.png             (messages/bubbles/Bitmaps/minus.png)
  	skin/classic/instantbird/messages/bubbles/Bitmaps/plus-hover.png        (messages/bubbles/Bitmaps/plus-hover.png)
  	skin/classic/instantbird/messages/bubbles/Bitmaps/plus.png              (messages/bubbles/Bitmaps/plus.png)
@@ -25,22 +25,22 @@ index e422619d4..e39f5dcd8 100644
  	skin/classic/instantbird/messages/bubbles/Incoming/Context.html         (messages/bubbles/Incoming/Context.html)
 diff --git a/im/themes/messages/bubbles/bubbles.svg b/im/themes/messages/bubbles/bubbles.svg
 deleted file mode 100644
-index 963521eca..000000000
+index 963521eca6..0000000000
 --- a/im/themes/messages/bubbles/bubbles.svg
 +++ /dev/null
 @@ -1,10 +0,0 @@
--<?xml version="1.0"?>
+-<?xml version="1.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/. -->
 -
--<svg xmlns="http://www.w3.org/2000/svg">
--  <filter id="desaturate">
--    <feColorMatrix type="saturate" values="0.4"/>
--  </filter>
--</svg>
+-<svg xmlns="http://www.w3.org/2000/svg">
+-  <filter id="desaturate">
+-    <feColorMatrix type="saturate" values="0.4"/>
+-  </filter>
+-</svg>
 diff --git a/im/themes/messages/bubbles/main.css b/im/themes/messages/bubbles/main.css
-index 15ba97346..4488c30bb 100644
+index 80421b8ca2..6520757ddd 100644
 --- a/im/themes/messages/bubbles/main.css
 +++ b/im/themes/messages/bubbles/main.css
 @@ -40,7 +40,7 @@ p {
@@ -53,5 +53,5 @@ index 15ba97346..4488c30bb 100644
  
  .indicator {
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0026-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch b/projects/instantbird/0017-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
similarity index 78%
rename from projects/instantbird/0026-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
rename to projects/instantbird/0017-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
index cc974ba..a336eb4 100644
--- a/projects/instantbird/0026-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
+++ b/projects/instantbird/0017-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
@@ -1,7 +1,7 @@
-From c3d0c1e82812698d6da4a5890860fd1b43e7fcbd Mon Sep 17 00:00:00 2001
+From be3edcf0ba689d39099053416d696312f09dc89e Mon Sep 17 00:00:00 2001
 From: Arlo Breault <arlolra at gmail.com>
-Date: Thu, 1 Dec 2016 14:34:51 -0800
-Subject: [PATCH 26/28] Bug 1321420 - Add a pref to disable JavaScript in
+Date: Wed, 26 Jul 2017 16:35:33 -0400
+Subject: [PATCH 17/20] Bug 1321420 - Add a pref to disable JavaScript in
  browser requests
 
 ---
@@ -10,20 +10,20 @@ Subject: [PATCH 26/28] Bug 1321420 - Add a pref to disable JavaScript in
  2 files changed, 9 insertions(+)
 
 diff --git a/chat/chat-prefs.js b/chat/chat-prefs.js
-index 60b9c1e8c..90a212e5c 100644
+index d6911dd9e9..4dc439b2f7 100644
 --- a/chat/chat-prefs.js
 +++ b/chat/chat-prefs.js
-@@ -86,6 +86,8 @@ pref("chat.prpls.prpl-skype.disable", true);
+@@ -88,6 +88,8 @@ pref("chat.prpls.prpl-skype.disable", true);
  pref("chat.prpls.prpl-facebook.disable", true);
  // Disable Yahoo Messenger as legacy Yahoo was shut down.
  pref("chat.prpls.prpl-yahoo.disable", true);
 +// Disable JavaScript in browser requests.
 +pref("chat.browserRequest.disableJavascript", false);
+ // Whether to disable SRV lookups that use the system DNS library.
+ pref("chat.dns.srv.disable", false);
  
- // loglevel is the minimum severity level that a libpurple message
- // must have to be reported in the Error Console.
 diff --git a/chat/content/browserRequest.js b/chat/content/browserRequest.js
-index c52c8c637..0069219fa 100644
+index c52c8c637d..0069219fa6 100644
 --- a/chat/content/browserRequest.js
 +++ b/chat/content/browserRequest.js
 @@ -2,6 +2,8 @@
@@ -48,5 +48,5 @@ index c52c8c637..0069219fa 100644
                                Components.interfaces.nsIWebProgress.NOTIFY_ALL);
    let url = request.url;
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0018-Trac-17517-Use-different-color-for-Add-Exception.patch b/projects/instantbird/0018-Trac-17517-Use-different-color-for-Add-Exception.patch
new file mode 100644
index 0000000..164e380
--- /dev/null
+++ b/projects/instantbird/0018-Trac-17517-Use-different-color-for-Add-Exception.patch
@@ -0,0 +1,23 @@
+From 18dbc6d30ed1707c89859aca360b59edf429169e Mon Sep 17 00:00:00 2001
+From: Vu Quoc Huy <huyvq.c633 at gmail.com>
+Date: Wed, 26 Jul 2017 16:38:19 -0400
+Subject: [PATCH 18/20] Trac 17517 - Use different color for Add Exception
+
+---
+ chat/content/accounts.css | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/chat/content/accounts.css b/chat/content/accounts.css
+index 807184209b..8ce7f9ad81 100644
+--- a/chat/content/accounts.css
++++ b/chat/content/accounts.css
+@@ -31,3 +31,6 @@ richlistitem:not([reconnectPending="true"]) description[anonid="reconnect"]
+ {
+   display: none;
+ }
++richlistitem[selected="true"] .addException {
++  color: #fff;
++}
+-- 
+2.13.3
+
diff --git a/projects/instantbird/0028-Trac-21736-Hide-account-timestamp-from-message.patch b/projects/instantbird/0019-Trac-21736-Hide-account-timestamp-from-message.patch
similarity index 92%
rename from projects/instantbird/0028-Trac-21736-Hide-account-timestamp-from-message.patch
rename to projects/instantbird/0019-Trac-21736-Hide-account-timestamp-from-message.patch
index 1546102..9ab4711 100644
--- a/projects/instantbird/0028-Trac-21736-Hide-account-timestamp-from-message.patch
+++ b/projects/instantbird/0019-Trac-21736-Hide-account-timestamp-from-message.patch
@@ -1,7 +1,7 @@
-From ef9ba3773fa442dd6b0d1b60056a2f07940cdc6c Mon Sep 17 00:00:00 2001
+From 9227ec7506dee6230c95f0f04d99fe694e2f8672 Mon Sep 17 00:00:00 2001
 From: Vu Quoc Huy <huyvq.c633 at gmail.com>
 Date: Sun, 2 Apr 2017 13:07:09 -0400
-Subject: [PATCH 28/28] Trac 21736 - Hide account/timestamp from message
+Subject: [PATCH 19/20] Trac 21736 - Hide account/timestamp from message
 
 ---
  chat/modules/imThemes.jsm         | 9 ++++-----
@@ -9,7 +9,7 @@ Subject: [PATCH 28/28] Trac 21736 - Hide account/timestamp from message
  2 files changed, 9 insertions(+), 5 deletions(-)
 
 diff --git a/chat/modules/imThemes.jsm b/chat/modules/imThemes.jsm
-index be6026c07..ad822cd86 100644
+index a723d742bf..95d917f0d7 100644
 --- a/chat/modules/imThemes.jsm
 +++ b/chat/modules/imThemes.jsm
 @@ -892,8 +892,7 @@ SelectedMessage.prototype = {
@@ -44,7 +44,7 @@ index be6026c07..ad822cd86 100644
      }
  
 diff --git a/im/app/profile/all-instantbird.js b/im/app/profile/all-instantbird.js
-index 89593abeb..3b31c61ee 100644
+index 454ca7ea1b..e23c93a4b3 100644
 --- a/im/app/profile/all-instantbird.js
 +++ b/im/app/profile/all-instantbird.js
 @@ -47,6 +47,11 @@ pref("extensions.systemAddon.update.url", "");
@@ -60,5 +60,5 @@ index 89593abeb..3b31c61ee 100644
  /* 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
 -- 
-2.12.2
+2.13.3
 
diff --git a/projects/instantbird/0020-Update-allowed-duplicated-files-for-Windows-and-Linu.patch b/projects/instantbird/0020-Update-allowed-duplicated-files-for-Windows-and-Linu.patch
new file mode 100644
index 0000000..dae7265
--- /dev/null
+++ b/projects/instantbird/0020-Update-allowed-duplicated-files-for-Windows-and-Linu.patch
@@ -0,0 +1,98 @@
+From b1714145c3e94877a6d0b6bf6a4592e1d3466745 Mon Sep 17 00:00:00 2001
+From: Sukhbir Singh <sukhbir at torproject.org>
+Date: Thu, 27 Jul 2017 15:16:54 -0400
+Subject: [PATCH 20/20] Update allowed duplicated files for Windows and Linux
+ builds
+
+---
+ im/installer/allowed-dupes.mn | 74 +++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 74 insertions(+)
+
+diff --git a/im/installer/allowed-dupes.mn b/im/installer/allowed-dupes.mn
+index 988dc2d35a..940418bc9d 100644
+--- a/im/installer/allowed-dupes.mn
++++ b/im/installer/allowed-dupes.mn
+@@ -10,6 +10,80 @@ chrome/instantbird/skin/classic/instantbird/messages/simple/Variants/Normal.css
+ chrome/instantbird/skin/classic/instantbird/messages/simple/Incoming/Context.html
+ chrome/instantbird/skin/classic/instantbird/messages/simple/Incoming/NextContext.html
+ chrome/chat/content/chat/conv.html
++chrome/instantbird/skin/classic/aero/instantbird/engineManager.css
++chrome/instantbird/skin/classic/instantbird/engineManager.css
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/tab-overflow-border.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/tab-overflow-border.png
++chrome/instantbird/skin/classic/aero/instantbird/alert.css
++chrome/instantbird/skin/classic/instantbird/alert.css
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/tab.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/tab.png
++chrome/instantbird/skin/classic/aero/instantbird/collapse.png
++chrome/instantbird/skin/classic/aero/instantbird/expand.png
++chrome/instantbird/skin/classic/aero/instantbird/menus.css
++chrome/instantbird/skin/classic/instantbird/menus.css
++chrome/instantbird/skin/classic/aero/instantbird/menulist.css
++chrome/instantbird/skin/classic/instantbird/menulist.css
++chrome/instantbird/skin/classic/aero/instantbird/richlistbox.css
++chrome/instantbird/skin/classic/instantbird/richlistbox.css
++chrome/instantbird/skin/classic/aero/instantbird/debugLogPanel.css
++chrome/instantbird/skin/classic/instantbird/debugLogPanel.css
++chrome/instantbird/skin/classic/aero/instantbird/newConversation.png
++chrome/instantbird/skin/classic/instantbird/newConversation.png
++chrome/instantbird/skin/classic/aero/instantbird/debugLog.css
++chrome/instantbird/skin/classic/instantbird/debugLog.css
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/tab-arrow-left.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/tab-arrow-left.png
++chrome/instantbird/skin/classic/aero/instantbird/actionicon-tab.png
++chrome/instantbird/skin/classic/instantbird/actionicon-tab.png
++chrome/instantbird/skin/classic/aero/instantbird/viewlog.css
++chrome/instantbird/skin/classic/instantbird/viewlog.css
++chrome/instantbird/skin/classic/aero/instantbird/userIcon.svg
++chrome/instantbird/skin/classic/instantbird/userIcon.svg
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/mainwindow-dropdown-arrow.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/mainwindow-dropdown-arrow.png
++chrome/instantbird/skin/classic/aero/instantbird/webcam.png
++chrome/instantbird/skin/classic/instantbird/webcam.png
++chrome/instantbird/skin/classic/aero/instantbird/select-file.png
++chrome/instantbird/skin/classic/instantbird/select-file.png
++chrome/instantbird/skin/classic/aero/instantbird/preferences/applications.css
++chrome/instantbird/skin/classic/instantbird/preferences/applications.css
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/newtab.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/newtab.png
++chrome/instantbird/skin/classic/aero/instantbird/founder.png
++chrome/instantbird/skin/classic/instantbird/founder.png
++chrome/instantbird/skin/classic/aero/instantbird/half-operator.png
++chrome/instantbird/skin/classic/instantbird/half-operator.png
++chrome/instantbird/skin/classic/aero/instantbird/userIcon.png
++chrome/instantbird/skin/classic/instantbird/userIcon.png
++chrome/instantbird/skin/classic/aero/instantbird/accountWizard.css
++chrome/instantbird/skin/classic/instantbird/accountWizard.css
++chrome/instantbird/skin/classic/aero/instantbird/operator.png
++chrome/instantbird/skin/classic/instantbird/operator.png
++chrome/instantbird/skin/classic/aero/instantbird/voice.png
++chrome/instantbird/skin/classic/instantbird/voice.png
++chrome/instantbird/skin/classic/aero/instantbird/newtab.css
++chrome/instantbird/skin/classic/instantbird/newtab.css
++chrome/instantbird/skin/classic/aero/instantbird/preferences/preferences.css
++chrome/instantbird/skin/classic/instantbird/preferences/preferences.css
++chrome/instantbird/skin/classic/aero/instantbird/newMessage.png
++chrome/instantbird/skin/classic/instantbird/newMessage.png
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser.css
++chrome/instantbird/skin/classic/instantbird/tabbrowser.css
++chrome/instantbird/skin/classic/aero/instantbird/tabbrowser/tabDragIndicator.png
++chrome/instantbird/skin/classic/instantbird/tabbrowser/tabDragIndicator.png
++chrome/instantbird/skin/classic/aero/instantbird/multiUserIcon.png
++chrome/instantbird/skin/classic/instantbird/multiUserIcon.png
++chrome/toolkit/skin/classic/global/icons/collapse.png
++chrome/instantbird/skin/classic/instantbird/collapse.png
++chrome/toolkit/skin/classic/global/icons/expand.png
++chrome/instantbird/skin/classic/instantbird/expand.png
++chrome/toolkit/skin/classic/global/icons/collapse.png
++chrome/instantbird/skin/classic/instantbird/collapse.png
++chrome/toolkit/skin/classic/global/icons/expand.png
++chrome/instantbird/skin/classic/instantbird/expand.png
++chrome/icons/default/default16.png
++icons/default16.png
+ 
+ # Variants of paths in mozilla/browser/installer/allowed-dupes.mn
+ # and mail/installer/allowed-dupes.mn:
+-- 
+2.13.3
+
diff --git a/projects/instantbird/0021-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch b/projects/instantbird/0021-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch
deleted file mode 100644
index e61301e..0000000
--- a/projects/instantbird/0021-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 57df7563fb512450b491f743a7cf070caaf63e6f Mon Sep 17 00:00:00 2001
-From: aleth <aleth at instantbird.org>
-Date: Wed, 26 Oct 2016 20:16:58 +0200
-Subject: [PATCH 21/28] Bug 1313137 - "msg is not defined" error in
- irc.js:changeBuddyNick. r=clokep
-
---HG--
-extra : rebase_source : 5752a69059ecd48b947809ef12de177ccab8528f
----
- chat/protocols/irc/irc.js | 3 ++-
- 1 file changed, 2 insertions(+), 1 deletion(-)
-
-diff --git a/chat/protocols/irc/irc.js b/chat/protocols/irc/irc.js
-index c2167a5ec..b58c2c2eb 100644
---- a/chat/protocols/irc/irc.js
-+++ b/chat/protocols/irc/irc.js
-@@ -1289,7 +1289,8 @@ ircAccount.prototype = {
-       this.conversations.set(aNewNick, conversation);
- 
-       conversation.updateNick(aNewNick);
--      conversation.writeMessage(aOldNick, msg, {system: true});
-+      conversation.writeMessage(aOldNick, _conv("nickSet", aOldNick, aNewNick),
-+                                {system: true});
-     }
-   },
- 
--- 
-2.12.2
-
diff --git a/projects/instantbird/0022-Bug-954368-Contact-list-entries-should-adapt-their-h.patch b/projects/instantbird/0022-Bug-954368-Contact-list-entries-should-adapt-their-h.patch
deleted file mode 100644
index b3548b6..0000000
--- a/projects/instantbird/0022-Bug-954368-Contact-list-entries-should-adapt-their-h.patch
+++ /dev/null
@@ -1,322 +0,0 @@
-From 366aa6588bf29cb0ecd1b63177a95d51fd803962 Mon Sep 17 00:00:00 2001
-From: aleth <aleth at instantbird.org>
-Date: Thu, 12 May 2016 15:10:43 +0200
-Subject: [PATCH 22/28] Bug 954368 - Contact list entries should adapt their
- height to the actual font size. r=florian
-
---HG--
-extra : rebase_source : 9820f3a68794f98260f3ac406772da6d176d02ec
----
- chat/themes/imtooltip.css                          |  1 +
- im/content/blist.css                               | 38 ++++++++++++---
- im/content/blist.js                                |  7 +++
- im/content/blist.xul                               |  4 ++
- im/content/contact.xml                             | 57 +++++++++++-----------
- im/content/conv.xml                                | 10 ++--
- .../en-US/chrome/instantbird/instantbird.dtd       |  6 +++
- im/themes/blist.css                                | 22 ++++-----
- 8 files changed, 92 insertions(+), 53 deletions(-)
-
-diff --git a/chat/themes/imtooltip.css b/chat/themes/imtooltip.css
-index c4525beb5..630da3983 100644
---- a/chat/themes/imtooltip.css
-+++ b/chat/themes/imtooltip.css
-@@ -31,6 +31,7 @@
- 
- .tooltipBuddies {
-   margin-left: -3px;
-+  --blist-item-height: 20px; /* 16px icon plus padding */
- }
- 
- .tooltipDisplayName {
-diff --git a/im/content/blist.css b/im/content/blist.css
-index d47e4f356..15b61b103 100644
---- a/im/content/blist.css
-+++ b/im/content/blist.css
-@@ -30,15 +30,28 @@ group {
-   -moz-box-align: center;
- }
- 
--/* The height is required for the animation to work. The skin can
-- * specify an additionnal min-height value if there are things of
-- * constant size (icons + padding) */
--contact,
--buddy,
-+/* The height is required for the animation to work. */
- group {
-   height: 1em;
- }
- 
-+conv,
-+contact,
-+buddy {
-+  /* Variable set from blist.js. This is necessary as CSS transitions don't
-+     work with height: auto.
-+     Usually 16+2+2px for the protocol icon, padding top and bottom. */
-+  height: var(--blist-item-height);
-+}
-+
-+contact[open],
-+contact[aliasing],
-+#buddylistbox:focus > contact[selected] {
-+  /* This is fine because height transitions in this state are on the
-+     buddies, and there is no transition on selection (it's instant). */
-+  height: auto;
-+}
-+
- /* Possible values of the |state| attribute:
-  - not set: the binding is not initialized yet,
-  - showing: during the expand animation,
-@@ -51,23 +64,24 @@ contact:not([state]),
- buddy:not([state]) {
-   height: 0;
- }
-+
- contact[state="showing"],
- buddy[state="showing"] {
-   /* Should match the transition effect for contact/buddy collapsing so
-      that reordering doesn't make the whole list jump. */
--  -moz-transition: height .2s ease-in;
-+  transition: height .2s ease-in;
- }
- 
- contact[state="fading"] {
-   opacity: 0;
--  -moz-transition: opacity .4s ease-in 1s;
-+  transition: opacity .4s ease-in 1s;
- }
- 
- contact[state="collapsing"],
- buddy[state="collapsing"],
- group[collapsing="true"] {
-   height: 0;
--  -moz-transition: height .2s ease-in;
-+  transition: height .2s ease-in;
- }
- 
- contact[state="collapsing"] *,
-@@ -78,6 +92,14 @@ group[collapsing="true"] * {
-   display: none;
- }
- 
-+#dummyContact {
-+  height: auto;
-+}
-+
-+#dummylistbox {
-+  visibility: hidden;
-+}
-+
- tooltip[type="im"] {
-   -moz-binding: url("chrome://chat/content/imtooltip.xml#tooltip");
- }
-diff --git a/im/content/blist.js b/im/content/blist.js
-index 9ec10e25c..ce76ffcd7 100644
---- a/im/content/blist.js
-+++ b/im/content/blist.js
-@@ -820,6 +820,13 @@ var buddyList = {
-               .setAttribute("checked", "true");
-     }
- 
-+    // Find the correct height of a contact list item. This can vary depending
-+    // on the platform font and font size.
-+    let dummyContact = document.getElementById("dummyContact");
-+    let contactHeight = dummyContact.getBoundingClientRect().height;
-+    document.getElementById("buddyListMsg")
-+            .style.setProperty("--blist-item-height", contactHeight + "px");
-+
-     let blistBox = document.getElementById("buddylistbox");
-     blistBox.removeGroup = function(aGroupElt) {
-       let index = buddyList._displayedGroups.indexOf(aGroupElt);
-diff --git a/im/content/blist.xul b/im/content/blist.xul
-index f29a48b99..71ee2c9ef 100644
---- a/im/content/blist.xul
-+++ b/im/content/blist.xul
-@@ -224,6 +224,10 @@
-                  onfocus="buddyList.buddylistboxFocus();"
-                  onselect="buddyList.listboxSelect(event);"
-                  tooltip="imTooltip"/>
-+    <richlistbox id="dummylistbox">
-+      <contact id="dummyContact" displayname="&dummyContact.label;"
-+               state="visible" status="unknown"/>
-+    </richlistbox>
-     <spacer id="listSpacer" flex="1"
-             onclick='document.getElementById("buddylistbox").focus();'/>
-   </notificationbox>
-diff --git a/im/content/contact.xml b/im/content/contact.xml
-index 5fc36dd6e..f2b464182 100644
---- a/im/content/contact.xml
-+++ b/im/content/contact.xml
-@@ -16,11 +16,11 @@
- 
-   <binding id="contact" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
-     <content>
--      <xul:stack class="prplBuddyIcon" mousethrough="always">
--        <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
--        <xul:image class="statusIcon" xbl:inherits="status"/>
--      </xul:stack>
--      <xul:hbox flex="1" class="contact-hbox" mousethrough="always">
-+      <xul:hbox flex="1" class="contact-hbox" mousethrough="always" align="center">
-+        <xul:stack class="prplBuddyIcon" mousethrough="always">
-+          <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
-+          <xul:image class="statusIcon" xbl:inherits="status"/>
-+        </xul:stack>
-         <xul:label crop="end" flex="1" mousethrough="always"
-                    anonid="displayname" class="contactDisplayName blistDisplayName"
-                    xbl:inherits="value=displayname,status"/>
-@@ -529,30 +529,29 @@
- 
-   <binding id="contact-big" extends="chrome://instantbird/content/contact.xml#contact">
-     <content>
--      <xul:hbox flex="1" mousethrough="always">
--        <xul:stack class="prplBuddyIcon" mousethrough="always">
--          <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
--          <xul:image class="statusIcon" xbl:inherits="status"/>
--        </xul:stack>
--        <xul:vbox flex="1" class="contact-vbox" mousethrough="always">
--          <xul:hbox class="contact-hbox" mousethrough="always">
--            <xul:label crop="end" flex="1" mousethrough="always"
--                       anonid="displayname" class="contactDisplayName blistDisplayName"
--                       xbl:inherits="value=displayname,status"/>
--            <xul:button anonid="startChatBubble" class="startChatBubble"
--                        tooltiptext="&openConversationCmd.label;"/>
--          </xul:hbox>
--          <xul:hbox class="contact-hbox" mousethrough="always">
--            <xul:label crop="end" flex="1" mousethrough="always"
--                       anonid="statusText" class="contactStatusText"
--                       xbl:inherits="value=statusText"/>
--            <xul:button anonid="expander" class="expander-down"
--                        tooltiptextexpand="&expandContactTooltip;"
--                        tooltiptextcollapse="&collapseContactTooltip;"
--                        tooltiptext="&expandContactTooltip;"/>
--          </xul:hbox>
--        </xul:vbox>
--      </xul:hbox>
-+      <xul:vbox flex="1" class="contact-vbox" mousethrough="always">
-+        <xul:hbox flex="1" class="contact-hbox" mousethrough="always" align="center">
-+          <xul:stack class="prplBuddyIcon" mousethrough="always">
-+            <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
-+            <xul:image class="statusIcon" xbl:inherits="status"/>
-+          </xul:stack>
-+          <xul:label crop="end" flex="1" mousethrough="always"
-+                     anonid="displayname" class="contactDisplayName blistDisplayName"
-+                     xbl:inherits="value=displayname,status"/>
-+          <xul:button anonid="startChatBubble" class="startChatBubble"
-+                      tooltiptext="&openConversationCmd.label;"/>
-+        </xul:hbox>
-+
-+        <xul:hbox flex="1" class="contact-hbox" mousethrough="always" align="center">
-+          <xul:label crop="end" flex="1" mousethrough="always"
-+                     anonid="statusText" class="contactStatusText contactIconSpace"
-+                     xbl:inherits="value=statusText"/>
-+          <xul:button anonid="expander" class="expander-down"
-+                      tooltiptextexpand="&expandContactTooltip;"
-+                      tooltiptextcollapse="&collapseContactTooltip;"
-+                      tooltiptext="&expandContactTooltip;"/>
-+        </xul:hbox>
-+      </xul:vbox>
-       <xul:vbox anonid="contactBuddies" class="contactBuddies">
-         <children/>
-       </xul:vbox>
-diff --git a/im/content/conv.xml b/im/content/conv.xml
-index 96a33af64..c41da6fb4 100644
---- a/im/content/conv.xml
-+++ b/im/content/conv.xml
-@@ -16,11 +16,11 @@
- 
-   <binding id="conv" extends="chrome://global/content/bindings/richlistbox.xml#richlistitem">
-     <content>
--      <xul:stack class="prplBuddyIcon" mousethrough="always">
--        <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
--        <xul:image class="statusIcon" xbl:inherits="status"/>
--      </xul:stack>
--      <xul:hbox flex="1" class="conv-hbox" mousethrough="always">
-+      <xul:hbox flex="1" class="conv-hbox" mousethrough="always" align="center">
-+        <xul:stack class="prplBuddyIcon" mousethrough="always">
-+          <xul:image class="protoIcon" xbl:inherits="src=iconPrpl,status"/>
-+          <xul:image class="statusIcon" xbl:inherits="status"/>
-+        </xul:stack>
-         <xul:label crop="end" flex="1" mousethrough="always"
-                    anonid="displayname" class="convDisplayName blistDisplayName"
-                    xbl:inherits="value=displayname,status"/>
-diff --git a/im/locales/en-US/chrome/instantbird/instantbird.dtd b/im/locales/en-US/chrome/instantbird/instantbird.dtd
-index 80b894862..fce965bb1 100644
---- a/im/locales/en-US/chrome/instantbird/instantbird.dtd
-+++ b/im/locales/en-US/chrome/instantbird/instantbird.dtd
-@@ -95,6 +95,12 @@
- <!ENTITY userIcon.label                "Change your icon">
- <!ENTITY contactsHeader.label          "Contacts">
- <!ENTITY convsHeader.label             "Conversations on hold">
-+<!-- LOCALIZATION NOTE (dummyContact.label):
-+     This string is not displayed anywhere, but it is used to calculate
-+     the height of an item in the contact list. Therefore you should
-+     set it to a string which contains characters that cover all
-+     vertical sizes that occur in your language. -->
-+<!ENTITY dummyContact.label            "SgFyWp">
- 
- <!ENTITY openConversationCmd.label     "Start a conversation">
- <!ENTITY openConversationCmd.accesskey "c">
-diff --git a/im/themes/blist.css b/im/themes/blist.css
-index 992267405..c033b51bc 100644
---- a/im/themes/blist.css
-+++ b/im/themes/blist.css
-@@ -100,14 +100,7 @@ group {
-   padding: 0 2px;
- }
- 
--conv,
--contact,
--buddy {
--  height: 20px; /* 16+2+2px for the protocol icon, padding top and bottom */
--}
--
- /* The vertical padding directly on the binding would not be animated. */
--.prplBuddyIcon,
- group>* {
-   padding-top: 2px;
-   padding-bottom: 2px;
-@@ -153,21 +146,28 @@ contact[droptarget] > buddy[dummy] {
-   margin: 0;
- }
- 
-+.contactDisplayName,
- .buddyDisplayName {
-   -moz-margin-start: 2px;
- }
- 
-+/* Used for the second line of a contact-big to add space on the left
-+   where the .prplBuddyIcon sits on the first line. */
-+.contactIconSpace {
-+  /* .prplBuddyIcon width+margins (16+3+3) + .contactStatusText margin (2) */
-+  margin-inline-start: 24px;
-+}
-+
- .contact-hbox,
- .conv-hbox {
-   margin: 2px 0;
--  -moz-margin-start: 2px;
-   min-height: 16px;
-   overflow-x: hidden;
- }
- 
- /* Avoid a strange jumping bug when hovering and the startChatBubble appears */
- .contact-vbox {
--  min-height: 40px;
-+  min-height: calc(var(--blist-item-height) * 2);
- }
- 
- .hideGroupButton,
-@@ -240,8 +240,8 @@ contact[droptarget] > buddy[dummy] {
- .startChatBubble,
- .expander-up,
- .expander-down {
--  width: 16px;
--  height: 16px;
-+  max-width: 16px;
-+  max-height: 16px;
-   min-height: 16px;
-   min-width: 16px;
- }
--- 
-2.12.2
-
diff --git a/projects/instantbird/0023-Bug-1187281-Only-show-close-button-on-Windows.patch b/projects/instantbird/0023-Bug-1187281-Only-show-close-button-on-Windows.patch
deleted file mode 100644
index e8f2b59..0000000
--- a/projects/instantbird/0023-Bug-1187281-Only-show-close-button-on-Windows.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From a7a2bff864f3e6a79062dd2da95c0464c818d45e Mon Sep 17 00:00:00 2001
-From: Arlo Breault <arlolra at gmail.com>
-Date: Sat, 5 Nov 2016 14:55:20 -0700
-Subject: [PATCH 23/28] Bug 1187281 - Only show "close" button on Windows
-
----
- im/content/accounts.xul | 2 ++
- 1 file changed, 2 insertions(+)
-
-diff --git a/im/content/accounts.xul b/im/content/accounts.xul
-index f3f1c6bbb..d683562cb 100644
---- a/im/content/accounts.xul
-+++ b/im/content/accounts.xul
-@@ -142,6 +142,8 @@
-   <windowdragbox id="bottombuttons" align="center">
-     <button id="newaccount" command="cmd_new"/>
-     <spacer flex="1"/>
-+#ifdef XP_WIN
-     <button id="close" command="cmd_close"/>
-+#endif
-   </windowdragbox>
- </window>
--- 
-2.12.2
-
diff --git a/projects/instantbird/0024-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch b/projects/instantbird/0024-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch
deleted file mode 100644
index c5f3582..0000000
--- a/projects/instantbird/0024-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch
+++ /dev/null
@@ -1,2398 +0,0 @@
-From ec5d00df9f1e5d5f00e239e57bbf730fb280aa65 Mon Sep 17 00:00:00 2001
-From: Patrick Cloke <clokep at gmail.com>
-Date: Wed, 9 Nov 2016 09:03:49 -0800
-Subject: [PATCH 24/28] Bug 1316000 - Remove old Yahoo! Messenger support.
- r=aleth
-
----
- chat/chat-prefs.js                                 |    2 +
- chat/locales/en-US/facebook.properties             |    3 +-
- chat/locales/en-US/yahoo.properties                |   34 +-
- chat/protocols/facebook/facebook.js                |   13 +-
- chat/protocols/yahoo/moz.build                     |    6 -
- chat/protocols/yahoo/test/test_yahooAccount.js     |   98 --
- chat/protocols/yahoo/test/test_yahooLoginHelper.js |   89 --
- chat/protocols/yahoo/test/test_yahoopacket.js      |  217 ----
- chat/protocols/yahoo/test/xpcshell.ini             |    7 -
- chat/protocols/yahoo/yahoo-session.jsm             | 1156 --------------------
- chat/protocols/yahoo/yahoo.js                      |  552 +---------
- im/content/conversation.xml                        |    3 +-
- .../chrome/instantbird/accountWizard.properties    |    3 +-
- im/test/xpcshell.ini                               |    1 -
- mail/components/im/content/imconversation.xml      |    3 +-
- 15 files changed, 18 insertions(+), 2169 deletions(-)
- delete mode 100644 chat/protocols/yahoo/test/test_yahooAccount.js
- delete mode 100644 chat/protocols/yahoo/test/test_yahooLoginHelper.js
- delete mode 100644 chat/protocols/yahoo/test/test_yahoopacket.js
- delete mode 100644 chat/protocols/yahoo/test/xpcshell.ini
- delete mode 100644 chat/protocols/yahoo/yahoo-session.jsm
-
-diff --git a/chat/chat-prefs.js b/chat/chat-prefs.js
-index fb769163d..60b9c1e8c 100644
---- a/chat/chat-prefs.js
-+++ b/chat/chat-prefs.js
-@@ -84,6 +84,8 @@ pref("chat.irc.automaticList", true);
- pref("chat.prpls.prpl-skype.disable", true);
- // Disable Facebook as the XMPP gateway no longer exists.
- pref("chat.prpls.prpl-facebook.disable", true);
-+// Disable Yahoo Messenger as legacy Yahoo was shut down.
-+pref("chat.prpls.prpl-yahoo.disable", true);
- 
- // loglevel is the minimum severity level that a libpurple message
- // must have to be reported in the Error Console.
-diff --git a/chat/locales/en-US/facebook.properties b/chat/locales/en-US/facebook.properties
-index aaf7cdc9c..2e00cbcb2 100644
---- a/chat/locales/en-US/facebook.properties
-+++ b/chat/locales/en-US/facebook.properties
-@@ -2,6 +2,5 @@
- # 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/.
- 
--connection.error.useUsernameNotEmailAddress=Please use your Facebook username, not an email address
--
- facebook.chat.name=Facebook Chat
-+facebook.disabled=Facebook Chat is no longer supported due to Facebook disabling their XMPP gateway.
-diff --git a/chat/locales/en-US/yahoo.properties b/chat/locales/en-US/yahoo.properties
-index 727faa6ee..89ee0093c 100644
---- a/chat/locales/en-US/yahoo.properties
-+++ b/chat/locales/en-US/yahoo.properties
-@@ -2,36 +2,4 @@
- # 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/.
- 
--login.error.badCredentials=Username or password is incorrect.
--login.error.accountLockedFailed=Account locked due to too many failed login attempts.
--login.error.accountLockedGeneral=Account locked due to too many login attempts.
--login.error.accountDeactivated=Account has been deactivated.
--login.error.usernameNotExist=The username does not exist.
--# The %S will be an error code returned by the server.
--login.error.unknown=Unknown error: %S
--network.error.http=HTTP connection error.
--
--conference.invite.message=Join my conference.
--
--# Some options are commented out because they aren't used. We do the same thing
--# to their description strings.
--options.pagerPort=Port
--options.transferHost=File transfer server
--options.transferPort=File transfer port
--options.chatEncoding=Encoding
--options.ignoreInvites=Ignore conference invitations
--
--# In this message, %S is replaced with the username of the user who left.
--system.message.conferenceLogoff=%S has left the conference.
--system.message.conferenceLogon=%S has joined the conference.
--
--# LOCALZIATION NOTE (command.*):
--#   These are the help messages for each command, the %S is the command name
--#   Each command first gives the parameter it accepts and then a description of
--#   the command.
--command.help.invite2=%S <user1>[,<user2>,...] [<invite message>]: invite one or more users into this conference chat.
--command.help.conference=%S: Create a new conference room in which you can later invite other users.
--
--# LOCALIZATION NOTE (command.feedback.invite):
--#   %S is the user, or comma separated list of users, invited to the conference.
--command.feedback.invite=You have invited %S to the conference.
-+yahoo.disabled=Yahoo Messenger is no longer supported due to Yahoo disabling their legacy protocol.
-diff --git a/chat/protocols/facebook/facebook.js b/chat/protocols/facebook/facebook.js
-index 7b5b3b86e..9d90eacdb 100644
---- a/chat/protocols/facebook/facebook.js
-+++ b/chat/protocols/facebook/facebook.js
-@@ -6,33 +6,26 @@ var {interfaces: Ci, utils: Cu} = Components;
- 
- Cu.import("resource:///modules/imXPCOMUtils.jsm");
- Cu.import("resource:///modules/jsProtoHelper.jsm");
--Cu.import("resource:///modules/xmpp.jsm");
--Cu.import("resource:///modules/xmpp-session.jsm");
- 
- XPCOMUtils.defineLazyGetter(this, "_", () =>
-   l10nHelper("chrome://chat/locale/facebook.properties")
- );
--XPCOMUtils.defineLazyGetter(this, "_irc", () =>
--  l10nHelper("chrome://chat/locale/irc.properties")
--);
- 
- function FacebookAccount(aProtoInstance, aImAccount) {
-   this._init(aProtoInstance, aImAccount);
- }
- FacebookAccount.prototype = {
--  __proto__: XMPPAccountPrototype,
--  get canJoinChat() { return false; },
-+  __proto__: GenericAccountPrototype,
-   connect: function() {
-     this.WARN("As Facebook deprecated its XMPP gateway, it is currently not " +
-               "possible to connect to Facebook Chat. See bug 1141674.");
-     this.reportDisconnecting(Ci.prplIAccount.ERROR_OTHER_ERROR,
--                             _irc("error.unavailable", _("facebook.chat.name")));
-+                             _("facebook.disabled"));
-     this.reportDisconnected();
-   }
- };
- 
--function FacebookProtocol() {
--}
-+function FacebookProtocol() {}
- FacebookProtocol.prototype = {
-   __proto__: GenericProtocolPrototype,
-   get normalizedName() { return "facebook"; },
-diff --git a/chat/protocols/yahoo/moz.build b/chat/protocols/yahoo/moz.build
-index f14434732..ea378535a 100644
---- a/chat/protocols/yahoo/moz.build
-+++ b/chat/protocols/yahoo/moz.build
-@@ -3,15 +3,9 @@
- # 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']
--
- EXTRA_COMPONENTS += [
-     'yahoo.js',
-     'yahoo.manifest',
- ]
- 
--EXTRA_JS_MODULES += [
--    'yahoo-session.jsm',
--]
--
- JAR_MANIFESTS += ['jar.mn']
-diff --git a/chat/protocols/yahoo/test/test_yahooAccount.js b/chat/protocols/yahoo/test/test_yahooAccount.js
-deleted file mode 100644
-index 51df00bb9..000000000
---- a/chat/protocols/yahoo/test/test_yahooAccount.js
-+++ /dev/null
-@@ -1,98 +0,0 @@
--/* Any copyright is dedicated to the Public Domain.
-- * http://creativecommons.org/publicdomain/zero/1.0/ */
--
--Components.utils.import("resource://gre/modules/Services.jsm");
--var yahoo = {};
--Services.scriptloader.loadSubScript("resource:///components/yahoo.js", yahoo);
--
--function run_test()
--{
--  add_test(test_cleanUsername);
--  add_test(test_fixFontSize);
--  run_next_test();
--}
--
--// Test the stripping of @yahoo.* domains from usernames.
--function test_cleanUsername()
--{
--  // These are just a few of the many possible domains.
--  let domains = ["yahoo.com.ar", "yahoo.com.au", "yahoo.com", "yahoo.co.jp",
--                 "yahoo.it", "yahoo.cn", "yahoo.co.in"];
--  let userId = "user";
--
--  // We must provide a mimimal fake implementation of a protocol object, to keep
--  // the YahooAccount constructor happy.
--  let fakeProtocol = {
--    id: "fake-proto",
--    options: {
--      local_charset: "UTF-8"
--    },
--    _getOptionDefault: function(aOption) { return this.options[aOption]; }
--  };
--  let fakeImAccount = {};
--
--  for each(let domain in domains) {
--    fakeImAccount.name = userId + "@" + domain;
--    let yahooAccount = new yahoo.YahooAccount(fakeProtocol, fakeImAccount);
--    do_check_eq(userId, yahooAccount.cleanUsername);
--  }
--  run_next_test();
--}
--
--// Test the _fixFontSize() method and ensure that it correctly fixes font sizes
--// in <font> tags while keeping any mention of size= in conversation untouched.
--function test_fixFontSize()
--{
--  // This is an array of two-element arrays. Each inner two-element array
--  // contains a message with a badly formed font size as the first element,
--  // and a message with a well-formed font size as the second element. We test
--  // to ensure that the badly formed message is converted to the well-formed
--  // one.
--  let testMessages = [
--    // Single font tag.
--    ["<font face=\"Arial\" size=\"12\">Test message 1",
--     "<font face=\"Arial\" size=\"3\">Test message 1"],
--    // Single font tag with size="<digit>" in innner message.
--    ["<font face=\"Arial\" size=\"9\">size=\"30\" is a big size.</font>",
--     "<font face=\"Arial\" size=\"2\">size=\"30\" is a big size.</font>"],
--    // Single font tag with no face attribute.
--    ["<font size=\"12\">This message has no font face attribute.",
--     "<font size=\"3\">This message has no font face attribute."],
--    // Single font tag with no size attribute.
--    ["<font face=\"Arial\">This message has no font size attribute.",
--     "<font face=\"Arial\">This message has no font size attribute."],
--    // Single font tag with rearranged attribute order.
--    ["<font size=\"9\" face=\"Arial\">size=\"30\" is a big size.</font>",
--     "<font size=\"2\" face=\"Arial\">size=\"30\" is a big size.</font>"],
--    // Multiple font tags.
--    ["<font face=\"Arial\" size=\"12\">Hello. <font face=\"Consolas\" size=\"40\">World",
--     "<font face=\"Arial\" size=\"3\">Hello. <font face=\"Consolas\" size=\"7\">World"]
--  ];
--
--  let fakeProtocol = {
--    id: "fake-proto",
--    options: {
--      local_charset: "UTF-8"
--    },
--    _getOptionDefault: function(aOption) { return this.options[aOption]; }
--  };
--  let fakeImAccount = {name: "test-user"};
--  // We create a fake conversation object so we can obtain the cleaned up
--  // message from the conv.writeMessage() call.
--  let messagePair;
--  let fakeConversation = {
--    writeMessage: function(aName, aMessage, aProperties) {
--      do_check_eq(aMessage, messagePair[1]); // Compare to the good message.
--    },
--    updateTyping: function(aStatus, aName) { }
--  };
--
--  let yahooAccount = new yahoo.YahooAccount(fakeProtocol, fakeImAccount);
--  yahooAccount._conversations.set("test-user", fakeConversation);
--  for each(let pair in testMessages) {
--    messagePair = pair;
--    // Send in the badly formed message.
--    yahooAccount.receiveMessage("test-user", messagePair[0]);
--  }
--  run_next_test();
--}
-diff --git a/chat/protocols/yahoo/test/test_yahooLoginHelper.js b/chat/protocols/yahoo/test/test_yahooLoginHelper.js
-deleted file mode 100644
-index e4d8bc1b8..000000000
---- a/chat/protocols/yahoo/test/test_yahooLoginHelper.js
-+++ /dev/null
-@@ -1,89 +0,0 @@
--/* 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/yahoo-session.jsm");
--var yahoo = {};
--Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo);
--
--// Preset test values.
--var kUsername = "testUser";
--var kPassword = "instantbird";
--var kPagerIp = "123.456.78.9";
--var kCrumb = "MG-Z/jNG+Q==";
--var kChallengeString = "AEF08DBAC33F9EEDABCFEA==";
--var kYCookie = "OTJmMTQyOTU1ZGQ4MDA3Y2I2ODljMTU5";
--var kTCookie = "NTdlZmIzY2Q4ODI3ZTc3NTIxYTk1MDhm";
--var kToken = "MThmMzg3OWM3ODcxMW";
--
--var kPagerAddressResponse = "COLO_CAPACITY=1\r\nCS_IP_ADDRESS=" + kPagerIp;
--var kTokenResponse = "0\r\n" + kToken + "\r\npartnerid=dummyValue";
--var kCookieResponse = "0\r\ncrumb=" + kCrumb + "\r\nY=" + kYCookie +
--                        "\r\nT=" + kTCookie + "\r\ncookievalidfor=86400";
--
--/* In each test, we override the function that would normally be called next in
-- * the login process. We do this so that we can intercept the login process,
-- * preventing calls to real Yahoo! servers, and do equality testing. */
--function run_test()
--{
--  add_test(test_pagerAddress);
--  add_test(test_challengeString);
--  add_test(test_loginToken);
--  add_test(test_cookies);
--  run_next_test();
--}
--
--function test_pagerAddress()
--{
--  let helper = new yahoo.YahooLoginHelper({}, {});
--
--  helper._getChallengeString = function() {
--    do_check_eq(kPagerIp, helper._session.pagerAddress);
--    run_next_test();
--  };
--
--  helper._onPagerAddressResponse(kPagerAddressResponse, null);
--}
--
--function test_challengeString()
--{
--  let helper = new yahoo.YahooLoginHelper({}, {});
--
--  helper._getLoginToken = function() {
--    do_check_eq(kChallengeString, helper._challengeString);
--    run_next_test();
--  };
--
--  let response = new yahoo.YahooPacket(yahoo.kPacketType.AuthResponse, 0, 0);
--  response.addValue(1, helper._username);
--  response.addValue(94, kChallengeString);
--  response.addValue(13, 0);
--  helper._onChallengeStringResponse(response.toArrayBuffer());
--}
--
--function test_loginToken()
--{
--  let helper = new yahoo.YahooLoginHelper({}, {});
--
--  helper._getCookies = function() {
--    do_check_eq(kToken, helper._loginToken);
--    run_next_test();
--  };
--
--  helper._onLoginTokenResponse(kTokenResponse, null);
--}
--
--function test_cookies()
--{
--  let helper = new yahoo.YahooLoginHelper({}, {});
--
--  helper._sendPagerAuthResponse = function() {
--    do_check_eq(kCrumb, helper._crumb);
--    do_check_eq(kYCookie, helper._session.yCookie);
--    do_check_eq(kTCookie, helper._session.tCookie);
--    run_next_test();
--  };
--
--  helper._onLoginCookiesResponse(kCookieResponse, null);
--}
-diff --git a/chat/protocols/yahoo/test/test_yahoopacket.js b/chat/protocols/yahoo/test/test_yahoopacket.js
-deleted file mode 100644
-index 7908c4429..000000000
---- a/chat/protocols/yahoo/test/test_yahoopacket.js
-+++ /dev/null
-@@ -1,217 +0,0 @@
--/* 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/yahoo-session.jsm");
--var yahoo = {};
--Services.scriptloader.loadSubScript("resource:///modules/yahoo-session.jsm", yahoo);
--
--var kPacketIdBytes = StringToBytes(yahoo.kPacketIdentfier);
--var kHelloKey = 1;
--var kHelloValue = "Hello";
--var kWorldKey = 20;
--var kWorldValue = "World";
--var kNumberKey = 4;
--var kNumberValue = 32;
--var kParamsKey = 60;
--var kParam1Value = "param1";
--var kParam2Value = "param2";
--var kPacketDataString = "1\xC0\x80Hello\xC0\x8020\xC0\x80World\xC0\x80" +
--                          "4\xC0\x8032\xC0\x8060\xC0\x80param1\xC0\x80" +
--                          "60\xC0\x80param2\xC0\x80";
--
--function run_test()
--{
--  add_test(test_headerCreation);
--  add_test(test_fullPacketCreation);
--  add_test(test_packetDecoding);
--  add_test(test_extractPackets);
--  add_test(test_malformedPacketExtraction);
--
--  run_next_test();
--}
--
--function test_headerCreation()
--{
--  let packetLength = 0;
--  // Random numbers.
--  let serviceNumber = 0x57;
--  let status = 0x04;
--  let sessionId = 0x57842390;
--
--  let packet = new yahoo.YahooPacket(serviceNumber, status, sessionId);
--  let buf = packet.toArrayBuffer();
--  let view = new DataView(buf);
--
--  // Ensure that the first 4 bytes contain the YMSG identifier.
--  for (let i = 0; i < kPacketIdBytes.length; ++i)
--    do_check_eq(kPacketIdBytes[i], view.getUint8(i));
--
--  do_check_eq(yahoo.kProtocolVersion, view.getUint16(4));
--  do_check_eq(yahoo.kVendorId, view.getUint16(6));
--  do_check_eq(packetLength, view.getUint16(8));
--  do_check_eq(serviceNumber, view.getUint16(10));
--  do_check_eq(status, view.getUint32(12));
--  do_check_eq(sessionId, view.getUint32(16));
--
--  run_next_test();
--}
--
--function test_fullPacketCreation()
--{
--  packetLength = kPacketDataString.length;
--  // Random numbers.
--  let serviceNumber = 0x55;
--  let status = 0x02;
--  let sessionId = 0x12567800;
--
--  let packet = new yahoo.YahooPacket(serviceNumber, status, sessionId);
--  packet.addValue(kHelloKey, kHelloValue);
--  packet.addValue(kWorldKey, kWorldValue);
--  packet.addValue(kNumberKey, kNumberValue);
--  packet.addValues(kParamsKey, [kParam1Value, kParam2Value]);
--  let buf = packet.toArrayBuffer();
--  let view = new DataView(buf);
--
--  // Header check.
--
--  // Ensure that the first 4 bytes contain the YMSG identifier.
--  for (let i = 0; i < kPacketIdBytes.length; ++i)
--    do_check_eq(kPacketIdBytes[i], view.getUint8(i));
--
--  do_check_eq(yahoo.kProtocolVersion, view.getUint16(4));
--  do_check_eq(yahoo.kVendorId, view.getUint16(6));
--  do_check_eq(packetLength, view.getUint16(8));
--  do_check_eq(serviceNumber, view.getUint16(10));
--  do_check_eq(status, view.getUint32(12));
--  do_check_eq(sessionId, view.getUint32(16));
--
--  // Packet data check.
--  let dataBytes = StringToBytes(kPacketDataString);
--  for (let i = 0; i < dataBytes.length; ++i)
--    do_check_eq(dataBytes[i], view.getUint8(yahoo.kPacketHeaderSize + i));
--  run_next_test()
--}
--
--function test_packetDecoding()
--{
--  let packetLength = kPacketDataString.length;
--  // Random numbers.
--  let serviceNumber = 0x20;
--  let status = 0x06;
--  let sessionId = 0x13319AB2;
--
--  let buf = new ArrayBuffer(yahoo.kPacketHeaderSize + packetLength);
--  let view = new DataView(buf);
--
--  for (let i = 0; i < kPacketIdBytes.length; ++i)
--    view.setUint8(i, kPacketIdBytes[i]);
--
--  view.setUint16(4, yahoo.kProtocolVersion);
--  view.setUint16(6, yahoo.kVendorId);
--  view.setUint16(8, packetLength);
--  view.setUint16(10, serviceNumber);
--  view.setUint32(12, status);
--  view.setUint32(16, sessionId);
--
--  let dataBuf = BytesToArrayBuffer(StringToBytes(kPacketDataString));
--  copyBytes(buf, dataBuf, 20);
--
--  // Now we decode and test.
--  let packet = new yahoo.YahooPacket();
--  packet.fromArrayBuffer(buf);
--
--  // Test header information.
--  do_check_eq(serviceNumber, packet.service);
--  do_check_eq(status, packet.status);
--  do_check_eq(sessionId, packet.sessionId);
--
--  // Test the getting of single packet data values.
--  do_check_eq(kHelloValue, packet.getValue(kHelloKey));
--  do_check_eq(kWorldValue, packet.getValue(kWorldKey));
--  do_check_eq(kNumberValue, packet.getValue(kNumberKey));
--
--  // Test the getting of multiple values with a single key.
--  let multiValue = packet.getValues(kParamsKey);
--  do_check_eq(2, multiValue.length);
--  do_check_eq(kParam1Value, multiValue[0]);
--  do_check_eq(kParam2Value, multiValue[1]);
--
--  // Test if certain keys are non-existant.
--  do_check_true(packet.hasKey(kHelloKey));
--  do_check_false(packet.hasKey(500)); // There is no key 500.
--
--  run_next_test();
--}
--
--function test_extractPackets()
--{
--  // Some constants for each packet.
--  const kP1Service = 0x47;
--  const kP1Status = 0;
--  const kP1SessionId = 0x12345678;
--  // Used for testing packet verification.
--  const kP1FuzzerKey = 42;
--  const kP1FuzzerValue = "I am using the YMSG protocol!";
--
--  const kP2Service = 0x57;
--  const kP2Status = 5;
--  const kP2SessionId = 0x87654321;
--
--  // First, create two packets and obtain their buffers.
--  let packet1 = new yahoo.YahooPacket(kP1Service, kP1Status, kP1SessionId);
--  packet1.addValue(kHelloKey, kHelloValue);
--  packet1.addValue(kP1FuzzerKey, kP1FuzzerValue);
--  let packet1Buffer = packet1.toArrayBuffer();
--
--  let packet2 = new yahoo.YahooPacket(kP2Service, kP2Status, kP2SessionId);
--  packet2.addValue(kWorldKey, kWorldValue);
--  let packet2Buffer = packet2.toArrayBuffer();
--
--  // Create one full buffer with both packets inside.
--  let fullBuffer = new ArrayBuffer(packet1Buffer.byteLength +
--                                   packet2Buffer.byteLength);
--  copyBytes(fullBuffer, packet1Buffer);
--  copyBytes(fullBuffer, packet2Buffer, packet1Buffer.byteLength);
--
--  // Now, run the packets through the extractPackets() method.
--  let [extractedPackets, bytesHandled] =
--      yahoo.YahooPacket.extractPackets(fullBuffer);
--  do_check_eq(2, extractedPackets.length);
--
--  // Packet 1 checks.
--  let p1 = extractedPackets[0];
--  do_check_eq(kP1Service, p1.service);
--  do_check_eq(kP1Status, p1.status);
--  do_check_eq(kP1SessionId, p1.sessionId);
--  do_check_true(p1.hasKey(kHelloKey));
--  do_check_eq(kHelloValue, p1.getValue(kHelloKey));
--
--  // Packet 2 checks.
--  let p2 = extractedPackets[1];
--  do_check_eq(kP2Service, p2.service);
--  do_check_eq(kP2Status, p2.status);
--  do_check_eq(kP2SessionId, p2.sessionId);
--  do_check_true(p2.hasKey(kWorldKey));
--  do_check_eq(kWorldValue, p2.getValue(kWorldKey));
--
--  // Check if all the bytes were handled.
--  do_check_eq(fullBuffer.byteLength, bytesHandled);
--
--  run_next_test();
--}
--
--function test_malformedPacketExtraction()
--{
--  const kInvalidPacketData = "MSYG1\xC0\x80Hello\xC0\x8020\xC0\x80World\xC0\x80";
--  let buffer = BytesToArrayBuffer(StringToBytes(kInvalidPacketData));
--  let malformed = false;
--  try {
--    yahoo.YahooPacket.extractPackets(buffer);
--  } catch(e) {
--    malformed = true;
--  }
--  do_check_true(malformed);
--  run_next_test();
--}
-diff --git a/chat/protocols/yahoo/test/xpcshell.ini b/chat/protocols/yahoo/test/xpcshell.ini
-deleted file mode 100644
-index f4b464e61..000000000
---- a/chat/protocols/yahoo/test/xpcshell.ini
-+++ /dev/null
-@@ -1,7 +0,0 @@
--[DEFAULT]
--head =
--tail =
--
--[test_yahooAccount.js]
--[test_yahooLoginHelper.js]
--[test_yahoopacket.js]
-diff --git a/chat/protocols/yahoo/yahoo-session.jsm b/chat/protocols/yahoo/yahoo-session.jsm
-deleted file mode 100644
-index cc9612036..000000000
---- a/chat/protocols/yahoo/yahoo-session.jsm
-+++ /dev/null
-@@ -1,1156 +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/. */
--
--this.EXPORTED_SYMBOLS = ["YahooSession"];
--
--var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
--
--Cu.import("resource://gre/modules/FileUtils.jsm");
--Cu.import("resource://gre/modules/Http.jsm");
--Cu.import("resource://gre/modules/NetUtil.jsm");
--Cu.import("resource:///modules/ArrayBufferUtils.jsm");
--Cu.import("resource:///modules/imServices.jsm");
--Cu.import("resource:///modules/imXPCOMUtils.jsm");
--Cu.import("resource:///modules/socket.jsm");
--
--XPCOMUtils.defineLazyGetter(this, "_", () =>
--  l10nHelper("chrome://chat/locale/yahoo.properties")
--);
--
--XPCOMUtils.defineLazyServiceGetter(this, "imgTools",
--                                   "@mozilla.org/image/tools;1", "imgITools");
--
--var kProtocolVersion = 16;
--var kVendorId = 0;
--
--var kPacketDataDelimiter = "\xC0\x80";
--var kPacketIdentifier = "YMSG";
--var kPacketHeaderSize = 20;
--var kProfileIconWidth = 96;
--
--// These constants are used by the icon uploading code since the Yahoo! file
--// transfer server is used for user icon uploads.
--var kFileTransferHost = "filetransfer.msg.yahoo.com";
--var kFileTransferPort = 80;
--
--var kPacketType = {
--  // Sent by a client when logging off of the Yahoo! network.
--  Logoff:         0x02,
--  // Sent by a client when a message is sent to a buddy.
--  Message:        0x06,
--  // Sent to the pager server once per hour.
--  Ping:           0x12,
--  // Used for inviting others to a conference.
--  ConfInvite:     0x18,
--  // Used as a notification when you or someone else joins a conference room.
--  ConfLogon:      0x19,
--  // Used as a notification when you or someone else leaves a conference room.
--  ConfLogoff:     0x1b,
--  // This is sent by the client when additional users are invited to the
--  // conference, but it can be sent as the first invite as well.
--  ConfAddInvite:  0x1c,
--  // Broadcast to all users in a conference room when someone posts a message.
--  ConfMessage:    0x1d,
--  // Used for typing notifications.
--  Notify:         0x4b,
--  // These two are used during initial authentication with the pager server.
--  AuthResponse:   0x54,
--  Auth:           0x57,
--  // Buddy list controls.
--  AddBuddy:       0x83,
--  RemoveBuddy:    0x84,
--  // This is sent when you reject a Yahoo! user's buddy request.
--  BuddyReqReject: 0x86,
--  // Sent to the server once every minute, telling it here are still alive.
--  KeepAlive:      0x8A,
--  // This is sent when we request a buddy icon.
--  Picture:        0xbe,
--  // This is sent after a profile picture has been successfully uploaded.
--  PictureUpload:  0xc2,
--  // This is sent whenever a buddy changes their status.
--  StatusUpdate:   0xc6,
--  // This is sent when we update our icon.
--  AvatarUpdate:   0xc7,
--  // This is sent when someone wishes to become your buddy.
--  BuddyAuth:      0xd6,
--  // Holds the initial status of all buddies when a user first logs in.
--  StatusInitial:  0xf0,
--  // Contains the buddy list sent from the server.
--  List:           0xf1,
--  // Sent back to the pager server after each received message. Sending this
--  // prevents echoed messages when chatting with the official Yahoo! client.
--  MessageAck:     0xfb
--};
--
--var kPacketStatuses = {
--  ServerAck: 0x1,
--  Typing: 0x16
--};
--
--// Each Yahoo! error code is mapped to a two-element array. The first element
--// contains the last part of the name of its localized string. This is appended
--// to "login.error." to obtain the string. The second element is the
--// Instantbird error that is given to the error handler.
--var kLoginStatusErrors = {
--  "1212" : ["badCredentials",
--            Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED],
--  "1213" : ["accountLockedFailed",
--            Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED],
--  "1218" : ["accountDeactivated",
--            Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED],
--  "1235" : ["usernameNotExist",
--            Ci.prplIAccount.ERROR_INVALID_USERNAME],
--  "1236" : ["accountLockedGeneral",
--            Ci.prplIAccount.ERROR_AUTHENTICATION_FAILED]
--};
--
--// These are the status codes that buddies can send us.
--var kBuddyStatuses = {
--  // Available.
--  "0"   : Ci.imIStatusInfo.STATUS_AVAILABLE,
--  // Be right back.
--  "1"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // Busy.
--  "2"   : Ci.imIStatusInfo.STATUS_UNAVAILABLE,
--    // Not at home.
--  "3"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // Not at desk.
--  "4"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // Not in office.
--  "5"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // On phone.
--  "6"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // On vacation.
--  "7"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // Out to lunch.
--  "8"   : Ci.imIStatusInfo.STATUS_AWAY,
--  // Stepped out.
--  "9"   : Ci.imIStatusInfo.STATUS_AWAY,
--    // Invisible.
--  "12"  : Ci.imIStatusInfo.STATUS_INVISIBLE,
--  // Custom status.
--  "99"  : Ci.imIStatusInfo.STATUS_AWAY,
--  // Idle.
--  "999" : Ci.imIStatusInfo.STATUS_IDLE
--};
--
--/* The purpose of the YahooSession object is to serve as a gateway between the
-- * protocol plug-in and the Yahoo! Messenger servers. Anytime an object outside
-- * of this file wishes to communicate with the servers, it should do it through
-- * one of the methods provided by YahooSession. By centralizing such network
-- * access, we can easily catch errors, and ensure that communication is handled
-- * correctly. */
--function YahooSession(aAccount)
--{
--  this._account = aAccount;
--  this.binaryMode = true;
--}
--YahooSession.prototype = {
--  __proto__: Socket,
--  _account: null,
--  _socket: null,
--  _username: null,
--  // This is the IPv4 address to the pager server which is the gateway into the
--  // Yahoo! Messenger network.
--  pagerAddress: null,
--  // The session ID is obtained during the login process and is maintained
--  // throughout the session. This helps the pager server identify the client.
--  sessionId: null,
--  // The T and Y cookies obtained by the YahooLoginHelper during login.
--  tCookie: null,
--  yCookie: null,
--
--  // Public methods.
--  login: function() {
--    this._account.reportConnecting();
--    new YahooLoginHelper(this).login(this._account);
--  },
--
--  sendPacket: function(aPacket) {
--    this.sendBinaryData(aPacket.toArrayBuffer(), aPacket.toString());
--  },
--
--  addBuddyToServer: function(aBuddy) {
--    let packet = new YahooPacket(kPacketType.AddBuddy, 0, this.sessionId);
--    // We leave this invite message empty. Any message placed here will
--    // annoyingly be sent to the invitee when they accept the invite.
--    packet.addValue(14, "");
--    packet.addValue(65, aBuddy.tag.name);
--    packet.addValue(97, "1"); // UTF-8 encoding.
--    packet.addValue(1, this._account.cleanUsername);
--    // The purpose of these two values are unknown.
--    packet.addValue(302, "319");
--    packet.addValue(300, "319");
--    packet.addValue(7, aBuddy.userName);
--    // The purpose of these three values are also unknown.
--    packet.addValue(334, "0");
--    packet.addValue(301, "319");
--    packet.addValue(303, "319");
--    this.sendPacket(packet);
--  },
--
--  removeBuddyFromServer: function(aBuddy) {
--    let packet = new YahooPacket(kPacketType.RemoveBuddy, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(7, aBuddy.userName);
--    packet.addValue(65, aBuddy.tag.name);
--    this.sendPacket(packet);
--  },
--
--  setStatus: function(aStatus, aMessage) {
--    let packet = new YahooPacket(kPacketType.StatusUpdate, 0, this.sessionId);
--
--    // When a custom status message is used, key 10 is set to 99, and key 97
--    // is set to 1. Otherwise, key 10 is set to our current status code.
--    if (aMessage && aMessage.length > 0) {
--      packet.addValue(10, "99");
--      packet.addValue(97, "1");
--    } else {
--      let statusCode;
--      switch(aStatus) {
--        // Available
--        case Ci.imIStatusInfo.STATUS_AVAILABLE:
--        case Ci.imIStatusInfo.STATUS_MOBILE:
--          statusCode = "0";
--          break;
--        // Away
--        case Ci.imIStatusInfo.STATUS_AWAY:
--          statusCode = "1";
--          break;
--        // Busy
--        case Ci.imIStatusInfo.STATUS_UNAVAILABLE:
--          statusCode = "2";
--          break;
--        // Invisible
--        case Ci.imIStatusInfo.STATUS_INVISIBLE:
--          statusCode = "12";
--          break;
--        // Idle
--        case Ci.imIStatusInfo.STATUS_IDLE:
--          statusCode = "999";
--          break;
--      }
--      packet.addValue(10, statusCode);
--    }
--
--    // Key 19 is always set as the status messgae, even when the message is
--    // empty. If key 10 is set to 99, the message is used.
--    packet.addValue(19, aMessage);
--
--    // Key 47 is always set to either 0, if we are available, or 1, if we are
--    // not available. The value is used by the server if key 10 is set to 99.
--    // Otherwise, the value of key 10 is used to determine our status.
--    packet.addValue(47, (aStatus == Ci.imIStatusInfo.STATUS_AVAILABLE) ?
--                    "0" : "1");
--    this.sendPacket(packet);
--  },
--
--  sendChatMessage: function(aName, aMessage) {
--    let packet = new YahooPacket(kPacketType.Message, 0, this.sessionId);
--    // XXX Key 0 is the user ID, and key 1 is the active ID. We need to find
--    // the difference between these two. Alias maybe?
--    packet.addValue(0, this._account.cleanUsername);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(5, aName);
--    packet.addValue(14, aMessage);
--    this.sendPacket(packet);
--  },
--
--  sendConferenceMessage: function(aRecipients, aRoom, aMessage) {
--    let packet = new YahooPacket(kPacketType.ConfMessage, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValues(53, aRecipients);
--    packet.addValue(57, aRoom);
--    packet.addValue(14, aMessage);
--    packet.addValue(97, "1"); // Use UTF-8 encoding.
--    this.sendPacket(packet);
--  },
--
--  sendTypingStatus: function(aBuddyName, aIsTyping) {
--    let packet = new YahooPacket(kPacketType.Notify, kPacketStatuses.Typing,
--                                 this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(5, aBuddyName);
--    packet.addValue(13, aIsTyping ? "1" : "0");
--    packet.addValue(14, " "); // Key 14 contains a single space.
--    packet.addValue(49, "TYPING");
--    this.sendPacket(packet);
--  },
--
--  acceptConferenceInvite: function(aOwner, aRoom, aParticipants) {
--    let packet = new YahooPacket(kPacketType.ConfLogon, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(57, aRoom);
--    packet.addValues(3, aParticipants);
--    this.sendPacket(packet);
--  },
--
--  createConference: function(aRoom) {
--    let packet = new YahooPacket(kPacketType.ConfLogon, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(3, this._account.cleanUsername);
--    packet.addValue(57, aRoom);
--    this.sendPacket(packet);
--  },
--
--  inviteToConference: function(aInvitees, aRoom, aParticipants, aMessage) {
--    let packet = new YahooPacket(kPacketType.ConfAddInvite, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValues(51, aInvitees);
--    packet.addValues(53, aParticipants);
--    packet.addValue(57, aRoom);
--    packet.addValue(58, aMessage);
--    packet.addValue(13, "0");
--    this.sendPacket(packet);
--  },
--
--  sendConferenceLogoff: function(aName, aParticipants, aRoom) {
--    let packet = new YahooPacket(kPacketType.ConfLogoff, 0, this.sessionId);
--    packet.addValue(1, aName);
--    packet.addValues(3, aParticipants);
--    packet.addValue(57, aRoom);
--    this.sendPacket(packet);
--  },
--
--  setProfileIcon: function(aFileName) {
--    // If we have an empty filename, remove the icon from the server.
--    if (!aFileName) {
--      let packet = new YahooPacket(kPacketType.AvatarUpdate, 0, this.sessionId);
--      packet.addValue(3, this._account.cleanUsername);
--      packet.addValue(213, 0);
--      this.sendPacket(packet);
--      return;
--    }
--    // Try to get a handle to the icon file.
--    let file = FileUtils.getFile("ProfD", [aFileName]);
--    let type = Cc["@mozilla.org/mime;1"].getService(Ci.nsIMIMEService)
--                                        .getTypeFromFile(file);
--    NetUtil.asyncFetch({
--        uri: NetUtil.newURI(file),
--        contentPolicyType: Ci.nsIContentPolicy.TYPE_IMAGE,
--        securityFlags: Ci.nsILoadInfo.SEC_NORMAL,
--        loadUsingSystemPrincipal: true
--      }, (aStream, aStatus) => {
--        if (!Components.isSuccessCode(aStatus)) {
--          throw "Could not access icon file.";
--          return;
--        }
--        let image = imgTools.decodeImage(aStream, type);
--        let uploader = new YahooProfileIconUploader(this._account, this,
--                                                    aFileName, image);
--        uploader.uploadIcon();
--      });
--  },
--
--  requestBuddyIcon: function(aName) {
--    let packet = new YahooPacket(kPacketType.Picture, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(5, aName); // The name of the buddy.
--    packet.addValue(13, "1"); // "1" means we wish to request an icon.
--    this.sendPacket(packet);
--  },
--
--  acceptBuddyRequest: function(aRequest) {
--    let packet = new YahooPacket(kPacketType.BuddyAuth, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(5, aRequest.userName);
--    // Misc. Unknown flags.
--    packet.addValue(13, 1);
--    packet.addValue(334, 0);
--    this.sendPacket(packet);
--
--    // If someone wants to add us as a buddy, place them under the default
--    // tag. Also, we make sure that the buddy doesn't already exist in the
--    // list in case of a server acknowledgement.
--    if (!this._account.hasBuddy(aRequest.userName))
--      this._account.addBuddy(Services.tags.defaultTag, aRequest.userName);
--  },
--
--  denyBuddyRequest: function(aRequest) {
--    let packet = new YahooPacket(kPacketType.BuddyReqReject, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(7, aRequest.userName);
--    packet.addValue(14, "");
--    this.sendPacket(packet);
--  },
--
--  sendKeepAlive: function() {
--    let packet = new YahooPacket(kPacketType.KeepAlive, 0, this.sessionId);
--    packet.addValue(0, this._account.cleanUsername);
--    this.sendBinaryData(packet.toArrayBuffer());
--  },
--
--  sendPing: function() {
--    let packet = new YahooPacket(kPacketType.Ping, 0, this.sessionId);
--    this.sendBinaryData(packet.toArrayBuffer());
--  },
--
--  // Callbacks.
--  onLoginComplete: function() {
--    this._account.reportConnected();
--    this._account.onLoginComplete();
--  },
--
--  onSessionError: function(aError, aMessage) {
--    this._account.reportDisconnecting(aError, aMessage);
--    if (!this.disconnected)
--      this.disconnect();
--    this._account.reportDisconnected();
--  },
--
--  // Private methods.
--
--  // Socket Event Callbacks.
--  LOG: function(aString) { return this._account.LOG(aString); },
--
--  DEBUG: function(aString) { return this._account.DEBUG(aString); },
--
--  onConnection: function() {
--    // We send an authentication request packet as soon as we connect to the
--    // pager server.
--    let packet = new YahooPacket(kPacketType.Auth, 0, 0);
--    packet.addValue(1, this._account.cleanUsername);
--    this.sendPacket(packet);
--  },
--
--  onConnectionTimedOut: function() {
--    this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, "");
--  },
--
--  onConnectionReset: function() {
--    this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, "");
--  },
--
--  // Called when the other end has closed the connection.
--  onConnectionClosed: function() {
--    if (!this._account.connected)
--      return;
--    this._account.reportDisconnecting(Ci.prplIAccount.NO_ERROR, "");
--    this._account.reportDisconnected();
--  },
--
--  onBinaryDataReceived: function(aData) {
--    let packets;
--    let bytesHandled;
--    try {
--      [packets, bytesHandled] = YahooPacket.extractPackets(aData);
--    } catch(e) {
--      this._account.ERROR(e);
--      this.onSessionError(Ci.prplIAccount.NETWORK_ERROR, "");
--      return 0;
--    }
--
--    for each (let packet in packets) {
--      this._account.LOG("Received Packet:\n" + packet.toString());
--      if (YahooPacketHandler.hasOwnProperty(packet.service)) {
--        try {
--          YahooPacketHandler[packet.service].call(this._account, packet);
--        } catch(e) {
--          this._account.ERROR(e);
--        }
--      } else {
--        this._account.WARN("No handler for Yahoo! packet " +
--                           packet.service.toString(16) + ".");
--      }
--    }
--    return bytesHandled;
--  }
--};
--
--/* The purpose of YahooLoginHelper is to separate the complicated login logic
-- * from the YahooSession object. Logging in on Yahoo!'s network is the most
-- * complicated stage of a session due to the authentication system that is
-- * employed. The login steps are listed below.
-- *
-- * 1) Get the address of a "pager" server. This pager will be our gateway to
-- *    the network.
-- *
-- * 2) Obtain the challenge string from the pager. This string is used to help
-- *    create the base64 response string needed for the final step.
-- *
-- * 3) Obtain a token from the login server via HTTP.
-- *
-- * 4) Obtain the login crumb, Y-Cookie, and T-Cookie from the login server via
-- *    HTTP. These will also be used in the final response packet to the pager.
-- *
-- * 5) Create the base64 response string from the MD5 hash of the crumb and
-- *    challenge string, and build a packet containing the username, password,
-- *    response string, version numbers, crumb, and cookies, sending it to the
-- *    pager for a final authenticatcation.
-- *
-- * If all goes well after the 5th step, the user is considered logged in. */
--function YahooLoginHelper(aSession)
--{
--  this._session = aSession;
--}
--YahooLoginHelper.prototype = {
--  // YahooSession object passed in constructor.
--  _session: null,
--  // YahooAccount object passed to login().
--  _account: null,
--  // The username, stripped of any @yahoo.com or @yahoo.co.jp suffix.
--  _username: null,
--  // The authentication challenge string sent from the Yahoo!'s login server.
--  _challengeString: null,
--  // The authentication token sent from Yahoo!'s login server.
--  _loginToken: null,
--  // Crumb sent from Yahoo!'s login server, and used in the final authentication
--  // request to the pager server.
--  _crumb: null,
--
--  // Public methods.
--  login: function(aAccount) {
--    this._account = aAccount;
--    this._getPagerAddress();
--  },
--
--  // Private methods.
--  _getPagerAddress: function() {
--    let options = {
--      onLoad: this._onPagerAddressResponse.bind(this),
--      onError: this._onHttpError.bind(this)
--    }
--    httpRequest(this._account._protocol.pagerRequestUrl, options);
--  },
--
--  _getChallengeString: function() {
--    let port = this._account.getInt("port");
--    this._session.connect(this._session.pagerAddress, port);
--    // We want to handle a challenge string when the server responds.
--    this._session.onBinaryDataReceived =
--      this._onChallengeStringResponse.bind(this);
--  },
--
--  _getLoginToken: function() {
--    // TODO - Simplify this using map and join.
--    let url = this._account._protocol.loginTokenGetUrl;
--    url += "?src=ymsgr&";
--    url += "login=" + percentEncode(this._account.cleanUsername) + "&";
--    url += "passwd=" + percentEncode(this._account.imAccount.password) + "&";
--    url += "chal=" + percentEncode(this._challengeString);
--
--    let options = {
--      onLoad: this._onLoginTokenResponse.bind(this),
--      onError: this._onHttpError.bind(this)
--    }
--    httpRequest(url, options);
--  },
--
--  _getCookies: function() {
--    // TODO - Simplify this using map and join.
--    let url = this._account._protocol.loginTokenLoginUrl;
--    url += "?src=ymsgr&";
--    url += "token=" + this._loginToken;
--
--    let options = {
--      onLoad: this._onLoginCookiesResponse.bind(this),
--      onError: this._onHttpError.bind(this)
--    }
--    httpRequest(url, options);
--  },
--
--  _sendPagerAuthResponse: function() {
--    let response = this._calculatePagerResponse();
--    let packet = new YahooPacket(kPacketType.AuthResponse, 0,
--                                 this._session.sessionId);
--    // Build the key/value pairs.
--    packet.addValue(1, this._account.cleanUsername);
--    packet.addValue(0, this._account.cleanUsername);
--    packet.addValue(277, this._session.yCookie);
--    packet.addValue(278, this._session.tCookie);
--    packet.addValue(307, response);
--    packet.addValue(244, this._account.protocol.buildId);
--    packet.addValue(2, this._account.cleanUsername);
--    packet.addValue(2, "1");
--    packet.addValue(98, "us");
--    this._session.sendPacket(packet);
--    // We want to handle a final login confirmation packet when the server
--    // responds.
--    this._session.onBinaryDataReceived = this._onFinalLoginResponse.bind(this);
--  },
--
--  _calculatePagerResponse: function() {
--    let hasher = Cc["@mozilla.org/security/hash;1"]
--                   .createInstance(Ci.nsICryptoHash);
--    hasher.init(hasher.MD5);
--
--    let crypt = this._crumb + this._challengeString;
--    let cryptData = StringToBytes(crypt);
--    hasher.update(cryptData, cryptData.length);
--
--    // The protocol requires replacing + with ., / with _, and = with - within
--    // the base64 response string.
--    return btoa(hasher.finish(false)).replace(/\+/g, ".").replace(/\//g, "_")
--                                     .replace(/=/g, "-");
--  },
--
--  _handleLoginError: function(aErrorCode) {
--    let errorInfo = kLoginStatusErrors[aErrorCode];
--    let errorMessage;
--    let error;
--
--    // If we find information on the error code we received, we will use that
--    // information. If the error wasn't found in our error table, just throw a
--    // generic error with the code included.
--    if (errorInfo) {
--      errorMessage = _("login.error." + errorInfo[0]);
--      error = errorInfo[1];
--    } else {
--      errorMessage = _("login.error.unknown", aErrorCode);
--      error = Ci.prplIAccount.ERROR_OTHER_ERROR;
--      // We also throw a console error because we didn't expect
--      // this error code.
--      this._account.ERROR("Received unknown error from pager server. Code: " +
--                          aErrorCode);
--    }
--    this._session.onSessionError(error, errorMessage);
--  },
--
--  _onHttpError: function(aError, aStatusText, aXHR) {
--    this._session.onSessionError(Ci.prplIAccount.NETWORK_ERROR,
--                                 _("network.error.http"));
--  },
--
--  // HTTP Response Callbacks.
--  _onPagerAddressResponse: function(aResponse, aXHR) {
--    this._session.pagerAddress =
--      aResponse.substring(aResponse.lastIndexOf("=") + 1);
--    this._getChallengeString();
--  },
--
--  _onLoginTokenResponse: function(aResponse, aXHR) {
--    let responseParams = aResponse.split("\r\n");
--    // Status code "0" means success.
--    let statusCode = responseParams[0];
--    if (statusCode != "0") {
--      this._handleLoginError(statusCode);
--      return;
--    }
--
--    this._loginToken = responseParams[1].replace("ymsgr=", "");
--    this._getCookies();
--  },
--
--  _onLoginCookiesResponse: function(aResponse, aXHR) {
--    let responseParams = aResponse.split("\r\n");
--    // Status code "0" means success.
--    let statusCode = responseParams[0];
--    if (statusCode != "0") {
--      this._handleLoginError(statusCode);
--      return;
--    }
--
--    this._crumb = responseParams[1].replace("crumb=", "");
--    // Remove the "Y=" bit.
--    this._session.yCookie = responseParams[2].substring(2);
--    // Remove the "T=" bit.
--    this._session.tCookie = responseParams[3].substring(2);
--    this._sendPagerAuthResponse();
--  },
--
--  // TCP Response Callbacks.
--  _onChallengeStringResponse: function(aData) {
--    let packet = new YahooPacket();
--    packet.fromArrayBuffer(aData);
--    // The value of the challenge string is associated with key 94.
--    this._challengeString = packet.getValue(94);
--    this._session.sessionId = packet.sessionId;
--    this._getLoginToken();
--  },
--
--  _onFinalLoginResponse: function(aData) {
--    this._session.onLoginComplete();
--    // We need to restore data handling to the YahooSession object since our
--    // login steps are complete.
--    this._session.onBinaryDataReceived =
--      YahooSession.prototype.onBinaryDataReceived.bind(this._session);
--  }
--};
--
--/* The YahooPacket class represents a single Yahoo! Messenger data packet.
-- * Using this class allows you to easily create packets, stuff them with
-- * required data, and convert them to/from ArrayBuffer objects. */
--function YahooPacket(aService, aStatus, aSessionId)
--{
--  this.service = aService;
--  this.status = aStatus;
--  this.sessionId = aSessionId;
--  this.keyValuePairs = [];
--}
--YahooPacket.prototype = {
--  service: null,
--  status: null,
--  sessionId: null,
--  keyValuePairs: null,
--
--  // Public methods.
--
--  // Add a single key/value pair.
--  addValue: function(aKey, aValue) {
--    let pair = {
--      key: aKey.toString(), // The server handles keys as ASCII number values.
--      value: aValue
--    };
--
--    this.keyValuePairs.push(pair);
--  },
--
--  // Add multiple key/value pairs with the same key but different values
--  // stored in an array.
--  addValues: function(aKey, aValues) {
--    for each (let value in aValues)
--      this.addValue(aKey, value);
--  },
--
--  // This method returns the first value found with the given key.
--  getValue: function(aKey) {
--    for (let i = 0; i < this.keyValuePairs.length; ++i) {
--      let pair = this.keyValuePairs[i];
--      // The server handles keys as ASCII number values.
--      if (pair.key == aKey.toString())
--        return pair.value;
--    }
--
--    // Throw an error if the key wasn't found.
--    throw "Required key " + aKey + " wasn't found. Packet Service: " +
--          this.service.toString(16);
--  },
--
--  // This method returns all of the values found with the given key. In some
--  // packets, one key is associated with multiple values. If that is the case,
--  // use this method to retrieve all of them instead of just the first one.
--  getValues: function(aKey) {
--    let values = [];
--    for (let i = 0; i < this.keyValuePairs.length; ++i) {
--      let pair = this.keyValuePairs[i];
--      // The server handles keys as ASCII number values.
--      if (pair.key == aKey.toString())
--        values.push(pair.value);
--    }
--
--    // Throw an error if no keys were found.
--    if (values.length == 0) {
--      throw "Required key " + aKey + " wasn't found. Packet Service: " +
--            this.service.toString(16);
--    }
--    return values;
--  },
--
--  hasKey: function(aKey) {
--    for (let i = 0; i < this.keyValuePairs.length; ++i) {
--      // The server handles keys as ASCII number values.
--      if (this.keyValuePairs[i].key == aKey.toString())
--        return true;
--    }
--    return false;
--  },
--
--  toArrayBuffer: function() {
--    let dataString = "";
--    for (let i = 0; i < this.keyValuePairs.length; ++i) {
--      let pair = this.keyValuePairs[i];
--      dataString += pair.key + kPacketDataDelimiter;
--      dataString += pair.value + kPacketDataDelimiter;
--    }
--
--    let packetLength = dataString.length;
--    let buffer = new ArrayBuffer(kPacketHeaderSize + packetLength);
--
--    // Build header.
--    let view = new DataView(buffer);
--    let idBytes = StringToBytes(kPacketIdentifier);
--    view.setUint8(0, idBytes[0]);
--    view.setUint8(1, idBytes[1]);
--    view.setUint8(2, idBytes[2]);
--    view.setUint8(3, idBytes[3]);
--    view.setUint16(4, kProtocolVersion);
--    view.setUint16(6, 0); // Vendor ID
--    view.setUint16(8, packetLength);
--    view.setUint16(10, this.service);
--    view.setUint32(12, this.status);
--    view.setUint32(16, this.sessionId);
--
--    // Copy in data.
--    copyBytes(buffer, BytesToArrayBuffer(StringToBytes(dataString)), kPacketHeaderSize);
--
--    return buffer;
--  },
--
--  fromArrayBuffer: function(aBuffer) {
--    let view = new DataView(aBuffer);
--    this.length = view.getUint16(8) + kPacketHeaderSize;
--    this.service = view.getUint16(10);
--    this.status = view.getUint32(12);
--    this.sessionId = view.getUint32(16);
--
--    let dataString = ArrayBufferToString(aBuffer).substring(kPacketHeaderSize);
--    let delimitedData = dataString.split(kPacketDataDelimiter);
--    // Since the data should also end with a trailing delmiter, split() will
--    // add an empty element at the end. We need to pop this element off.
--    delimitedData.pop();
--
--    // If we don't have an even number of delimitedData elements, that means
--    // we are either missing a key or a value.
--    if (delimitedData.length % 2 != 0) {
--      throw "Odd number of data elements. Either a key or value is missing. "
--            "Num of elements: " + delimitedData.length;
--    }
--
--    for (let i = 0; i < delimitedData.length; i += 2) {
--      let key = delimitedData[i];
--      let value = delimitedData[i + 1];
--      if (key && value) {
--        let pair = {
--          key: key,
--          value: value
--        };
--        this.keyValuePairs.push(pair);
--      }
--    }
--  },
--
--  toString: function() {
--    // First, add packet header information.
--    let s = "Service: 0x" + this.service.toString(16) + "\n";
--    s += "Status: 0x" + this.status.toString(16) + "\n";
--    s += "Session ID: 0x" + this.sessionId.toString(16);
--    // Now we add the packet data, if there is some.
--    if (this.keyValuePairs.length) {
--      // Add two preceding newlines for space to make reading easier.
--      s += "\n\nPacket Key-Value Data:\n";
--      for each (let pair in this.keyValuePairs)
--        s += pair.key + ":\t" + pair.value + "\n";
--    }
--    return s;
--  }
--};
--YahooPacket.extractPackets = function(aData, aOnNetworkError) {
--  let packets = [];
--  let bytesHandled = 0;
--
--  while (aData.byteLength >= kPacketHeaderSize) {
--    if (ArrayBufferToString(aData.slice(0, kPacketIdentifier.length)) !=
--        kPacketIdentifier) {
--      throw "Malformed packet received. Packet content: " +
--            ArrayBufferToHexString(aData);
--    }
--
--    let packetView = new DataView(aData);
--    let packetLength = packetView.getUint16(8) + kPacketHeaderSize;
--    // Don't process half packets.
--    if (packetLength > aData.byteLength)
--      break;
--    let packet = new YahooPacket();
--    packet.fromArrayBuffer(aData.slice(0, packetLength));
--    packets.push(packet);
--    bytesHandled += packetLength;
--    aData = aData.slice(packetLength);
--  }
--  return [packets, bytesHandled];
--}
--
--/* In YahooPacketHandler, each handler function is assosiated with a packet
-- * service number. You can use the kPacketType enumeration to understand
-- * what kind of packet each number is linked to.
-- *
-- * Keep in mind too that "this" in each function will be bound to a
-- * YahooAccount object, since they are all invoked using call(). */
--var YahooPacketHandler = {
--  // Buddy logoff.
--  0x02: function(aPacket) {
--    let name = aPacket.getValue(7);
--    this.setBuddyStatus(name, Ci.imIStatusInfo.STATUS_OFFLINE, "");
--  },
--
--  // Incoming chat message.
--  0x06: function(aPacket) {
--    let from = aPacket.getValue(4);
--    let to = aPacket.getValue(5);
--    let message = aPacket.getValue(14);
--    this.receiveMessage(from, message);
--
--    // The official Yahoo! Messenger desktop client requires message ACKs to be
--    // sent back to the server. The web client doesn't require this. A good
--    // indication of when an ACK is required is when key 429 is sent, which
--    // contains the ID of the message. When a message is sent from the official
--    // desktop client, and no ACK is sent back, the message is resent seconds
--    // later.
--    if (aPacket.hasKey(429)) {
--      let messageId = aPacket.getValue(429);
--      let packet = new YahooPacket(kPacketType.MessageAck, 0, aPacket.sessionId);
--      // Some keys have an unknown purpose, so we set a constant value.
--      packet.addValue(1, to);
--      packet.addValue(5, from);
--      packet.addValue(302, "430");
--      packet.addValue(430, messageId);
--      packet.addValue(303, 430);
--      packet.addValue(450, 0);
--      this._session.sendPacket(packet);
--    }
--  },
--
--  // New mail notification.
--  // TODO: Implement this handler when mail notifications are handled in the
--  // base code.
--  0x0b: function(aPacket) {},
--
--  // Server ping.
--  // TODO: Add support for ping replies.
--  0x12: function(aPacket) {},
--
--  // Conference invitation.
--  0x18: function(aPacket) {
--    let owner = aPacket.getValue(50);
--    let roomName = aPacket.getValue(57);
--    let participants = aPacket.getValues(53);
--    // The owner is also a participant.
--    participants.push(owner);
--    let message = aPacket.getValue(58);
--    this.receiveConferenceInvite(owner, roomName, participants, message);
--  },
--
--  // Conference logon.
--  0x19: function(aPacket) {
--    let userName = aPacket.getValue(53);
--    let room = aPacket.getValue(57);
--    this.receiveConferenceLogon(room, userName);
--  },
--
--  // Conference logoff
--  0x1b: function(aPacket) {
--    let userName = aPacket.getValue(56);
--    let roomName = aPacket.getValue(57);
--    this.receiveConferenceLogoff(roomName, userName);
--  },
--
--  // Conference additional invitation. NOTE: Since this packet has the same
--  // structure as the normal conference invite (packet 0x18), we simply
--  // reuse that handler.
--  0x1c: function(aPacket) { return YahooPacketHandler[0x18].call(this, aPacket); },
--
--  // Conference message.
--  0x1d: function(aPacket) {
--    let from = aPacket.getValue(3);
--    let room = aPacket.getValue(57);
--    let message = aPacket.getValue(14);
--    this.receiveConferenceMessage(from, room, message);
--  },
--
--  // Typing notification.
--  0x4b: function(aPacket) {
--    let name = aPacket.getValue(4);
--    let isTyping = (aPacket.getValue(13) == "1");
--    this.receiveTypingNotification(name, isTyping);
--  },
--
--  // Legacy Yahoo! buddy list. Packet 0xf1 has replaced this.
--  0x55: function(aPacket) {},
--
--  // Authentication acknowledgement. We can ignore this since we are known
--  // to be authenticated if we are receiving other packets anyway.
--  0x57: function(aPacket) {},
--
--  // AddBuddy ack packets can be ignored. They do not depend on whether or not
--  // the buddy accepted the invite.
--  0x83: function(aPacket) {},
--
--  // RemoveBuddy ack packets let us know when we should actually remove the
--  // buddy from the list, keeping us in sync with the server.
--  0x84: function(aPacket) {
--   let buddy = this.getBuddy(aPacket.getValue(7));
--   // The buddy is off the server, so remove it locally.
--   this.removeBuddy(buddy, false);
--  },
--
--  // Picture upload.
--  0xc2: function(aPacket) {
--    let onlineBuddies = this.getOnlineBuddies();
--    // Send a notification to each online buddy that your icon has changed.
--    // Those offline will automatically pick up the change when they log in.
--    for each (let buddy in onlineBuddies) {
--      let packet = new YahooPacket(kPacketType.AvatarUpdate, 0,
--                                   this._session.sessionId);
--      packet.addValue(3, buddy.userName);
--      packet.addValue(213, 2); // A value of 2 means we are using an icon.
--      this._session.sendPacket(packet);
--    }
--  },
--
--  // Buddy icon checksum.
--  // TODO - Make use of the icon checksum to allow icon caching.
--  0xbd: function(aPacket) {
--    // Extract the checksum from the URL parameter chksum.
--    let buddyName = aPacket.getValue(4);
--    let url = aPacket.getValue(20);
--    let parameter = "chksum=";
--    // The "chksum" parameter is the only parameter in the URL.
--    let checksum = url.substring(url.indexOf(parameter) + parameter.length);
--
--    let buddy = this.getBuddy(buddyName);
--    // We only download the new icon if no older checksum exists, or if the
--    // older checksum differs, indicating an updated icon.
--    if (buddy && buddy.iconChecksum !== checksum) {
--      buddy.buddyIconFilename = url;
--      buddy.iconChecksum = checksum;
--    }
--  },
--
--  // Buddy icon request reply. This can be handled in the same way as a buddy
--  // icon checksum packet, so we simply reuse the handler.
--  0xbe: function (aPacket) { return YahooPacketHandler[0xbd].call(this, aPacket); },
--
--  // Buddy status update.
--  0xc6: function (aPacket) {
--    let name = aPacket.getValue(7);
--    // If the user is mobile, use the mobile status.
--    let status = aPacket.hasKey(60) ? Ci.imIStatusInfo.STATUS_MOBILE :
--                                      kBuddyStatuses[aPacket.getValue(10)];
--
--    let message = aPacket.hasKey(19) ? aPacket.getValue(19) : "";
--    this.setBuddyStatus(name, status, message);
--  },
--
--  // Buddy avatar (icon) update.
--  0xc7: function(aPacket) {
--    // Strangely, in some non-official clients, when someone updates their
--    // profile icon we are sent two avatar update packets: one with a default
--    // status containing little information, and another with a Server Ack
--    // status containing the info we need. So we only accept packets with a
--    // Server Ack status to prevent errors.
--    if (aPacket.status != kPacketStatuses.ServerAck)
--      return;
--    // Key 4 contains the name of the buddy who updated their icon.
--    this._session.requestBuddyIcon(aPacket.getValue(4));
--  },
--
--  // Buddy authorization request.
--  0xd6: function(aPacket) {
--    // Whenever we authorize someone to be our buddy, the server will send an
--    // acknowledgement packet. We ignore the ack to prevent the auth request
--    // from showing again.
--    if (aPacket.status == kPacketStatuses.ServerAck)
--      return;
--
--    let session = this._session;
--    let userName = aPacket.getValue(4);
--    this.addBuddyRequest(userName, session.acceptBuddyRequest.bind(session),
--                         session.denyBuddyRequest.bind(session));
--  },
--
--  // XXX: What does this packet do?
--  0xef: function(aPacket) {},
--
--  // Initial user status.
--  0xf0: function (aPacket) {
--    // Return early if we find no buddy names.
--    if (!aPacket.hasKey(7))
--      return;
--
--    // The key/value pairs are in order as sent by the server. So we must
--    // iterate though them to find out information about each buddy. Each
--    // buddy section starts with key 7.
--    let currentBuddy;
--    for (let i = 0; i < aPacket.keyValuePairs.length; ++i) {
--      let {key: key, value: value} = aPacket.keyValuePairs[i];
--
--      if (key == 7) { // Buddy name.
--        currentBuddyName = value;
--        this._session.requestBuddyIcon(currentBuddyName);
--      } else if (key == 10) // Buddy status.
--        this.setBuddyStatus(currentBuddyName, kBuddyStatuses[value]);
--      else if (key == 19) // Buddy status message.
--        this.setBuddyStatus(currentBuddyName, undefined, value);
--      else if (key == 60) // Mobile status.
--        this.setBuddyStatus(currentBuddyName, Ci.imIStatus.STATUS_MOBILE);
--    }
--  },
--
--  // Friends and groups list.
--  0xf1: function(aPacket) {
--    let tagName = "";
--    for each (let pair in aPacket.keyValuePairs) {
--      if (pair.key == "65")
--        tagName = pair.value;
--      else if (pair.key == "7") {
--        let buddyName = pair.value;
--        this.addBuddyFromServer(Services.tags.createTag(tagName), buddyName);
--      }
--    }
--  }
--};
--
--/* The YahooProfileIconUploader class is specifically designed to set a profile
-- * image on a Yahoo! Messenger account. The reason this functionality is split
-- * into a separate class is because of the complexity of the operation. Because
-- * of special protocol requirements, it is easier to use raw TCP communication
-- * instead of the httpRequest() method. */
--function YahooProfileIconUploader(aAccount, aSession, aFileName, aImage)
--{
--  this._account = aAccount;
--  this._session = aSession;
--  this._fileName = aFileName;
--  this._image = aImage;
--}
--YahooProfileIconUploader.prototype = {
--  __proto__: Socket,
--  _account: null,
--  _session: null,
--  _fileName: null,
--  _image: null,
--  _host: null,
--  _port: null,
--
--  uploadIcon: function() {
--    // Connect to the file transfer server, and the onConnection callback
--    // will do the rest.
--    this.connect(kFileTransferHost, kFileTransferPort);
--  },
--
--  // Socket callbacks.
--  onConnection: function() {
--    // Scale the image down, and make it a PNG. Icon widths are constant, but
--    // their height varies depending on the aspect ratio of the original image.
--    let aspectRatio = this._image.width / this._image.height;
--    let scaledHeight = kProfileIconWidth / aspectRatio;
--    let scaledImage = imgTools.encodeScaledImage(this._image, "image/png",
--                                                 kProfileIconWidth,
--                                                 scaledHeight);
--    let imageData = NetUtil.readInputStreamToString(scaledImage,
--                                                    scaledImage.available());
--
--    // Build the Yahoo packet.
--    let packet = new YahooPacket(kPacketType.Picture, 0, this.sessionId);
--    packet.addValue(1, this._account.cleanUsername);
--    // TODO - Look into how expiration time works for profile icons, and its
--    // purpose. We aren't sure if this refers to seconds, days, years, etc.
--    packet.addValue(38, "604800"); // Expiration time.
--    packet.addValue(0, this._account.cleanUsername);
--    packet.addValue(28, imageData.length); // Picture size in bytes.
--    packet.addValue(27, this._fileName); // Picture filename.
--    packet.addValue(14, ""); // Null string.
--    let packetBuffer = packet.toArrayBuffer();
--
--    // Build the request header.
--    let headers = [
--      ["User-Agent", "Mozilla/5.0"],
--      ["Cookie", "T=" + this._session.tCookie + "; Y=" + this._session.yCookie],
--      ["Host", kFileTransferHost + ":" + kFileTransferPort],
--      ["Content-Length", packetBuffer.byteLength + 4 + imageData.length],
--      ["Cache-Control", "no-cache"],
--    ];
--    let headerString = "POST /notifyft HTTP/1.1\r\n";
--    headers.forEach(function(header) {
--      headerString += header[0] + ": " + header[1] + "\r\n";
--    });
--
--    // The POST request uses a special delimeter between the end of the included
--    // Yahoo binary packet, and the image data.
--    let requestPacketEnd = "29" + kPacketDataDelimiter;
--    // Build the complete POST request data.
--    let requestData = headerString + "\r\n" +
--                      ArrayBufferToString(packetBuffer) + requestPacketEnd +
--                      imageData;
--    this.sendData(requestData);
--  }
--};
-diff --git a/chat/protocols/yahoo/yahoo.js b/chat/protocols/yahoo/yahoo.js
-index 8beadb504..86a258969 100644
---- a/chat/protocols/yahoo/yahoo.js
-+++ b/chat/protocols/yahoo/yahoo.js
-@@ -2,575 +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/. */
- 
--var {classes: Cc, interfaces: Ci, utils: Cu} = Components;
-+var {interfaces: Ci, utils: Cu} = Components;
- 
--Cu.import("resource:///modules/imServices.jsm");
- Cu.import("resource:///modules/imXPCOMUtils.jsm");
- Cu.import("resource:///modules/jsProtoHelper.jsm");
--Cu.import("resource:///modules/yahoo-session.jsm");
- 
- XPCOMUtils.defineLazyGetter(this, "_", () =>
-   l10nHelper("chrome://chat/locale/yahoo.properties")
- );
- 
--// These timeouts are in milliseconds.
--var kKeepAliveTimeout = 60 * 1000; // One minute.
--var kPingTimeout = 3600 * 1000; // One hour.
--
--function YahooConversation(aAccount, aName)
--{
--  this._buddyUserName = aName;
--  this._account = aAccount;
--  this.buddy = aAccount.getBuddy(aName);
--  this._init(aAccount);
--}
--YahooConversation.prototype = {
--  __proto__: GenericConvIMPrototype,
--  _account: null,
--  _buddyUserName: null,
--  _typingTimer: null,
--
--  close: function() {
--    this._account.deleteConversation(this._buddyUserName);
--    GenericConvChatPrototype.close.call(this);
--  },
--
--  sendMsg: function (aMsg) {
--    // Deliver the message, then write it to the window.
--    this._account._session.sendChatMessage(this._buddyUserName,
--                                           this._account.encodeMessage(aMsg));
--    this.finishedComposing();
--    this.writeMessage(this._account.cleanUsername, aMsg,
--                      {outgoing: true, _alias: this._account.imAccount.alias});
--  },
--
--  sendTyping: function(aString) {
--    if (aString.length) {
--      if (!this._typingTimer)
--        this._account._session.sendTypingStatus(this._buddyUserName, true);
--      this._refreshTypingTimer();
--    }
--    return Ci.prplIConversation.NO_TYPING_LIMIT;
--  },
--
--  finishedComposing: function() {
--    this._account._session.sendTypingStatus(this._buddyUserName, false);
--    this._cancelTypingTimer();
--  },
--
--  _refreshTypingTimer: function() {
--    this._cancelTypingTimer();
--    this._typingTimer = setTimeout(this.finishedComposing.bind(this), 10000);
--  },
--
--  _cancelTypingTimer: function() {
--    if (!this._typingTimer)
--      return;
--    clearTimeout(this._typingTimer);
--    delete this._typingTimer
--    this._typingTimer = null;
--  },
--
--  get name() { return this._buddyUserName; }
--};
--
--function YahooConference(aAccount, aRoom, aOwner)
--{
--  this._account = aAccount;
--  this._roomName = aRoom;
--  this._owner = aOwner;
--  this._init(aAccount, aRoom, aAccount.cleanUsername);
--}
--YahooConference.prototype = {
--  __proto__: GenericConvChatPrototype,
--  _account: null,
--  _roomName: null,
--  _owner: null,
--
--  close: function() {
--    this.reportLogoff();
--    this._account.deleteConference(this._roomName);
--    GenericConvChatPrototype.close.call(this);
--  },
--
--  reportLogoff: function() {
--    if (this.left)
--      return;
--    this._account._session.sendConferenceLogoff(this._account.cleanUsername,
--                                                this.getParticipantNames(),
--                                                this._roomName);
--    this.left = true;
--  },
--
--  sendMsg: function(aMsg) {
--    this._account._session.sendConferenceMessage(this.getParticipantNames(),
--                                                 this._roomName,
--                                                 this._account.encodeMessage(aMsg));
--  },
--
--  addParticipant: function(aName) {
--    // In case we receive multiple conference logon packets, prevent adding
--    // duplicate buddies.
--    if (this._participants.get(aName))
--      return;
--    let buddy = new YahooConferenceBuddy(aName, this);
--    this._participants.set(aName, buddy);
--    this.notifyObservers(new nsSimpleEnumerator([buddy]), "chat-buddy-add");
--    this.writeMessage(this._roomName,
--                      _("system.message.conferenceLogon", aName),
--                      {system: true});
--  },
--
--  getParticipantNames: function() { return [for (p of this._participants.values()) p.name]; }
--};
--
--function YahooConferenceBuddy(aName, aConference)
--{
--  this._name = aName;
--  this._conference = aConference;
--}
--YahooConferenceBuddy.prototype = {
--  __proto__: GenericConvChatBuddyPrototype,
--  _conference: null,
--
--  get founder() { return this._conference._owner == this._name; }
--};
--
--function YahooAccountBuddy(aAccount, aBuddy, aTag, aUserName)
--{
--  this._init(aAccount, aBuddy, aTag, aUserName);
--}
--YahooAccountBuddy.prototype = {
--  __proto__: GenericAccountBuddyPrototype,
--  iconChecksum: null,
--
--  // This removes the buddy locally, and from the Yahoo! servers.
--  remove: function() { return this._account.removeBuddy(this, true); },
--  // This removes the buddy locally, but keeps him on the servers.
--  removeLocal: function() { return this._account.removeBuddy(this, false); },
--  createConversation: function() { return this._account.createConversation(this.userName); }
--}
--
- function YahooAccount(aProtoInstance, aImAccount)
- {
-   this._init(aProtoInstance, aImAccount);
--  this._buddies = new Map();
--  this._conversations = new Map();
--  this._conferences = new Map();
--  this._protocol = aProtoInstance;
--  this._converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]
--      .createInstance(Ci.nsIScriptableUnicodeConverter);
--  this._converter.charset = this.getString("local_charset") || "UTF-8";
--
--  // The username stripped of any @yahoo.* domain.
--  this.cleanUsername = this.name.replace(/@yahoo\..+$/, "");
- }
- YahooAccount.prototype = {
-   __proto__: GenericAccountPrototype,
--  // YahooSession object passed in constructor.
--  _session: null,
--  // A Map holding the list of buddies associated with their usernames.
--  _buddies: null,
--  // A Map holding the list of open buddy conversations associated with the
--  // username of the buddy.
--  _conversations: null,
--  // A Map holding the list of open conference rooms associated with the room
--  // name.
--  _conferences: null,
--  // YahooProtocol object passed in the constructor.
--  _protocol: null,
--  // An nsIScriptableUnicodeConverter used to convert incoming/outgoing chat
--  // messages to the correct charset.
--  _converter: null,
--  // This is simply incremented by one everytime a new conference room is
--  // created. It is appened to the end of the room name when a new room is
--  // created, ensuring name uniqueness.
--  _roomsCreated: 0,
--  // The username stripped of any @yahoo.* domain.
--  cleanUsername: null,
--  // The timers used to send keepalive and ping packets to the server to ensrue
--  // the server that the user is still connected.
--  _keepAliveTimer: null,
--  _pingTimer: null,
- 
-   connect: function() {
--    this._session = new YahooSession(this);
--    this._session.login(this.imAccount.name, this.imAccount.password);
--  },
--
--  disconnect: function(aSilent) {
--    // Log out of all of the conferences the user is in.
--    for (let conf of this._conferences)
--      conf[1].reportLogoff();
--
--    if (this.connected) {
--      this.reportDisconnecting(Ci.prplIAccount.NO_ERROR, "");
--      if (this._session.isConnected)
--        this._session.disconnect();
--      this.reportDisconnected();
--    }
--    // buddy[1] is the actual object.
--    for (let buddy of this._buddies)
--      buddy[1].setStatus(Ci.imIStatusInfo.STATUS_UNKNOWN, "");
--
--    // Clear and delete the timers to avoid memory leaks.
--    if (this._keepAliveTimer) {
--      this._keepAliveTimer.cancel();
--      delete this._keepAliveTimer;
--    }
--
--    if (this._pingTimer) {
--      this._pingTimer.cancel();
--      delete this._pingTimer;
--    }
--  },
--
--  observe: function(aSubject, aTopic, aData) {
--    if (aTopic == "status-changed")
--      this._session.setStatus(aSubject.statusType, aData);
--    else if (aTopic == "user-icon-changed")
--      this._session.setProfileIcon(aData);
--  },
--
--  remove: function() {
--    for each(let conv in this._conversations)
--      conv.close();
--    delete this._conversations;
--    for (let buddy of this._buddies)
--      buddy[1].removeLocal(); // buddy[1] is the actual object.
--  },
--
--  unInit: function() {
--    this.disconnect(true);
--    delete this.imAccount;
--  },
--
--  createConversation: function(aName) {
--    let conv = new YahooConversation(this, aName);
--    this._conversations.set(aName, conv);
--    return conv;
--  },
--
--  deleteConversation: function(aName) {
--    if (this._conversations.has(aName))
--      this._conversations.delete(aName);
--  },
--
--  receiveConferenceInvite: function(aOwner, aRoom, aParticipants, aMessage) {
--    // Do nothing if we wish to ignore invites.
--    if (!Services.prefs.getIntPref("messenger.conversations.autoAcceptChatInvitations") ||
--        this.getBool("ignore_invites"))
--      return;
--
--    let conf = new YahooConference(this, aRoom, aOwner);
--    this._conferences.set(aRoom, conf);
--
--    for each (let participant in aParticipants)
--      conf.addParticipant(participant);
--
--    // Add ourselves to the conference room as well.
--    conf.addParticipant(this.imAccount.name);
--
--    this._session.acceptConferenceInvite(aOwner, aRoom,
--                                         conf.getParticipantNames());
--  },
--
--  receiveConferenceLogon: function(aRoom, aUsername) {
--    if (!this._conferences.has(aRoom))
--      return;
--    let conf = this._conferences.get(aRoom);
--    conf.addParticipant(aUsername);
--  },
--
--  receiveConferenceLogoff: function(aRoom, aUsername) {
--    if (!this._conferences.has(aRoom))
--      return;
--    let conf = this._conferences.get(aRoom);
--    conf.removeParticipant(aUsername);
--    conf.writeMessage(this._roomName,
--                      _("system.message.conferenceLogoff", aName),
--                      {system: true});
--  },
--
--  deleteConference: function(aName) {
--    if (this._conferences.has(aName))
--      this._conferences.delete(aName);
--  },
--
--  // Called when the user adds or authorizes a new contact.
--  addBuddy: function(aTag, aName) {
--    let buddy = new YahooAccountBuddy(this, null, aTag, aName);
--    this._buddies.set(buddy.userName, buddy);
--    this._session.addBuddyToServer(buddy);
--    Services.contacts.accountBuddyAdded(buddy);
--  },
--
--  hasBuddy: function(aName) {
--    return this._buddies.has(aName);
--  },
--
--  // Called for each buddy that is sent in a list packet from Yahoo! on login.
--  addBuddyFromServer: function(aTag, aName) {
--    let buddy;
--    if (this._buddies.has(aName))
--      buddy = this._buddies.get(aName);
--    else {
--      buddy = new YahooAccountBuddy(this, null, aTag, aName);
--      Services.contacts.accountBuddyAdded(buddy);
--      this._buddies.set(aName, buddy);
--    }
--
--    // Set all new buddies as offline because a following status packet will
--    // tell their status if they are online.
--    buddy.setStatus(Ci.imIStatusInfo.STATUS_OFFLINE, "");
--
--    // Request the buddy's picture.
--    this._session.requestBuddyIcon(aName);
--  },
--
--  // Called when a user removes a contact from within Instantbird.
--  removeBuddy: function(aBuddy, aRemoveFromServer) {
--    if (aRemoveFromServer) {
--      // We will remove the buddy locally when we get a server ack packet.
--      this._session.removeBuddyFromServer(aBuddy);
--      return;
--    }
--
--    this._buddies.delete(aBuddy.userName);
--    Services.contacts.accountBuddyRemoved(aBuddy);
--  },
--
--  loadBuddy: function(aBuddy, aTag) {
--    let buddy = new YahooAccountBuddy(this, aBuddy, aTag);
--    this._buddies.set(buddy.userName, buddy);
--
--    return buddy;
--  },
--
--  // Both the status and message can be defined, or only one can be defined.
--  // When defining just the message, set aStatus to undefined.
--  setBuddyStatus: function(aName, aStatus, aMessage) {
--    if (!this._buddies.has(aName))
--      return;
--    let buddy = this._buddies.get(aName);
--    // If the message is set as undefined, use the existing message.
--    if (aMessage === undefined)
--      aMessage = buddy.statusText;
--    // If the status is undefined, use the existing status.
--    if (aStatus === undefined)
--      aStatus = buddy.statusType;
--    buddy.setStatus(aStatus, aMessage);
--  },
--
--  getBuddy: function(aName) {
--    if (this._buddies.has(aName))
--      return this._buddies.get(aName);
--    return null;
--  },
--
--  getOnlineBuddies: function() {
--    let onlineBuddies = [];
--    for (let buddy of this._buddies) {
--      if (buddy[1].statusType != Ci.imIStatusInfo.STATUS_OFFLINE)
--        onlineBuddies.push(buddy[1]);
--    }
--    return onlineBuddies;
--  },
--
--  receiveMessage: function(aName, aMessage) {
--    let conv;
--    // Check if we have an existing converstaion open with this user. If not,
--    // create one and add it to the list.
--    if (!this._conversations.has(aName))
--      conv = this.createConversation(aName);
--    else
--      conv = this._conversations.get(aName);
--
--    // Certain Yahoo clients, such as the official web client, sends formatted
--    // messages, but the size value is the actual pt size, not the 1 - 7 size
--    // expected from the HTML <font> tag. We replace it with the correct size.
--    let message = this.decodeMessage(aMessage)
--                      .replace(/(<font[^>]+)size=\"(\d+)\"/g, this._fixFontSize);
--
--    conv.writeMessage(aName, message, {incoming: true});
--    conv.updateTyping(Ci.prplIConvIM.NOT_TYPING, conv.name);
--  },
--
--  receiveConferenceMessage: function(aName, aRoom, aMessage) {
--    if (!this._conferences.has(aRoom))
--      return;
--
--    this._conferences.get(aRoom).writeMessage(aName,
--                                              this.decodeMessage(aMessage),
--                                              {incoming: true});
--  },
--
--  receiveTypingNotification: function(aName, aIsTyping) {
--    if (!this._conversations.has(aName))
--      return;
--
--    let conv = this._conversations.get(aName);
--    if (aIsTyping)
--      conv.updateTyping(Ci.prplIConvIM.TYPING, conv.name);
--    else
--      conv.updateTyping(Ci.prplIConvIM.NOT_TYPING, conv.name);
--  },
--
--  encodeMessage: function(aMessage) {
--    // Try to perform a convertion from JavaScript UTF-16 into the charset
--    // specified in the options. If the conversion fails, just leave
--    // the message as it is.
--    let encodedMsg;
--    try {
--      encodedMsg = this._converter.ConvertFromUnicode(aMessage);
--    } catch (e) {
--      encodedMsg = aMessage;
--      this.WARN("Could not encode UTF-16 message into " +
--                this._converter.charset + ". Message: " + aMessage);
--    }
--    return encodedMsg;
--  },
--
--  decodeMessage: function(aMessage) {
--    // Try to perform a convertion from the charset specified in the options
--    // to JavaScript UTF-16. If the conversion fails, just leave the message
--    // as it is.
--    let decodedMsg;
--    try {
--      decodedMsg = this._converter.ConvertToUnicode(aMessage);
--    } catch (e) {
--      decodedMsg = aMessage;
--      this.WARN("Could not decode " + this._converter.charset +
--                " message into UTF-16. Message: " + aMessage);
--    }
--    return decodedMsg;
--  },
--
--  get canJoinChat() { return true; },
--  chatRoomFields: {},
--  joinChat: function(aComponents) {
--    // Use _roomsCreated to append a unique number to the room name.
--    let roomName = this.cleanUsername + "-" + ++this._roomsCreated;
--    let conf = new YahooConference(this, roomName, this.cleanUsername);
--    this._conferences.set(roomName, conf);
--    this._session.createConference(roomName);
--  },
--
--  // Callbacks.
--  onLoginComplete: function() {
--    // Now that we are connected, get ready to start to sending pings and
--    // keepalive packets.
--    this._keepAliveTimer = Cc["@mozilla.org/timer;1"]
--                             .createInstance(Ci.nsITimer);
--    this._pingTimer = Cc["@mozilla.org/timer;1"]
--                        .createInstance(Ci.nsITimer);
--
--    // We use slack timers since we don't need millisecond precision when
--    // sending the keepalive and ping packets.
--    let s = this._session;
--    this._keepAliveTimer
--        .initWithCallback(s.sendKeepAlive.bind(s), kKeepAliveTimeout,
--                          this._keepAliveTimer.TYPE_REPEATING_SLACK);
--
--    this._pingTimer
--        .initWithCallback(s.sendPing.bind(s), kPingTimeout,
--                          this._pingTimer.TYPE_REPEATING_SLACK);
--
--  },
--
--  // Private methods.
--
--  // This method is used to fix font sizes given by formatted messages. This
--  // method is designed to be used as a method for a string replace() call.
--  _fixFontSize: function(aMatch, aTagAttributes, aFontSize, aOffset, aString) {
--    // Approximate the font size.
--    let newSize;
--    if (aFontSize <= 8)
--      newSize = "1";
--    else if (aFontSize <= 10)
--      newSize = "2";
--    else if (aFontSize <= 12)
--      newSize = "3";
--    else if (aFontSize <= 14)
--      newSize = "4";
--    else if (aFontSize <= 20)
--      newSize = "5";
--    else if (aFontSize <= 30)
--      newSize = "6";
--    else if (aFontSize <= 40)
--      newSize = "7";
--    else // If we get some gigantic size, just default to the standard 3 size.
--      newSize = "3";
--
--    let sizeAttribute = "size=\"" + newSize + "\"";
--    // We keep any preceding attributes, but replace the size attribute.
--    return aTagAttributes + sizeAttribute;
-+    this.WARN("The legacy versions of Yahoo Messenger was disabled on August " +
-+              "5, 2016. It is currently not possible to connect to Yahoo " +
-+              "Messenger. See bug 1316000");
-+    this.reportDisconnecting(Ci.prplIAccount.ERROR_OTHER_ERROR,
-+                             _("yahoo.disabled"));
-+    this.reportDisconnected();
-   }
- };
- 
--function YahooProtocol() {
--  this.registerCommands();
--}
-+function YahooProtocol() {}
- YahooProtocol.prototype = {
-   __proto__: GenericProtocolPrototype,
--  // Protocol specific connection parameters.
--  pagerRequestUrl: "http://scsa.msg.yahoo.com/capacity",
--  loginTokenGetUrl: "https://login.yahoo.com/config/pwtoken_get",
--  loginTokenLoginUrl: "https://login.yahoo.com/config/pwtoken_login",
--  buildId: "4194239",
- 
-   get id() { return "prpl-yahoo"; },
-   get name() { return "Yahoo"; },
-   get iconBaseURI() { return "chrome://prpl-yahoo/skin/"; },
--  options: {
--    port: {get label() { return _("options.pagerPort"); }, default: 5050},
--    local_charset: {get label() { return _("options.chatEncoding"); }, default: "UTF-8"},
--    ignore_invites: {get label() { return _("options.ignoreInvites"); }, default: false}
--  },
--  commands: [
--    {
--      name: "invite",
--      get helpString() { return _("command.help.invite2", "invite"); },
--      usageContext: Ci.imICommand.CMD_CONTEXT_ALL,
--      run: function(aMsg, aConv) {
--        if (aMsg.trim().length == 0)
--          return false;
--
--        let splitPosition = aMsg.indexOf(" "); // Split at first space.
--        let invitees;
--        let message;
--
--        // If we have an invite message.
--        if (splitPosition > 0) {
--          invitees = aMsg.substring(0, splitPosition).split(",");
--          message = aMsg.substring(splitPosition);
--        } else {
--          invitees = aMsg.split(",");
--          message = _("conference.invite.message"); // Use default message.
--        }
--
--        let conf = aConv.wrappedJSObject;
--        conf._account._session.inviteToConference(invitees, conf._roomName,
--                                                  conf.getParticipantNames(),
--                                                  message);
--        conf.writeMessage(conf._roomName,
--                          _("command.feedback.invite", invitees.join(", ")),
--                          {system: true, noLog: true});
--        conf._account.LOG("Sending conference invite to " + invitees);
--        return true;
--      },
--    },
--
--    {
--      name: "conference",
--      get helpString() { return _("command.help.conference", "conference"); },
--      usageContext: Ci.imICommand.CMD_CONTEXT_CHAT,
--      run: function(aMsg, aConv) {
--        aConv.account.joinChat(null);
--        return true;
--      }
--    }
--  ],
-   getAccount: function(aImAccount) { return new YahooAccount(this, aImAccount); },
-   classID: Components.ID("{50ea817e-5d79-4657-91ae-aa0a52bdb98c}")
- };
-diff --git a/im/content/conversation.xml b/im/content/conversation.xml
-index 6f00c8d39..c93dab00f 100644
---- a/im/content/conversation.xml
-+++ b/im/content/conversation.xml
-@@ -342,8 +342,7 @@
-                   msg = "<font face=\"" + style.fontFamily + "\">" + msg + "</font>";
-                 // MSN doesn't support font size info in messages...
-               }
--              else if (proto == "prpl-aim" || proto == "prpl-icq" ||
--                       proto == "prpl-yahoo" || proto == "prpl-yahoojp") {
-+              else if (proto == "prpl-aim" || proto == "prpl-icq") {
-                 let styleAttributes = ""
-                 if ("color" in style)
-                   styleAttributes += " color=\"" + style.color + "\"";
-diff --git a/im/locales/en-US/chrome/instantbird/accountWizard.properties b/im/locales/en-US/chrome/instantbird/accountWizard.properties
-index 7d371bd21..1d6fd48e1 100644
---- a/im/locales/en-US/chrome/instantbird/accountWizard.properties
-+++ b/im/locales/en-US/chrome/instantbird/accountWizard.properties
-@@ -14,9 +14,8 @@ topProtocol.list=prpl-irc,prpl-jabber,prpl-twitter,prpl-gtalk
- # These are the descriptions of the top protocols specified above.
- # A description should be provided for each protocol ID listed above.
- topProtocol.prpl-irc.description=Connect to your favourite IRC network
--topProtocol.prpl-jabber.description=Chat with friends using XMPP
- topProtocol.prpl-gtalk.description=Talk to your Gmail contacts
- topProtocol.prpl-twitter.description=Stay up to date with your Twitter timeline
- topProtocol.prpl-aim.description=Chat with your buddies on AOL Instant Messenger
--topProtocol.prpl-yahoo.description=Chat with friends using Yahoo! Messenger
- topProtocol.prpl-irc.description=Join IRC channels
-+topProtocol.prpl-jabber.description=Chat using the open Jabber/XMPP protocol
-diff --git a/im/test/xpcshell.ini b/im/test/xpcshell.ini
-index 5f7dd70fc..578122a2a 100644
---- a/im/test/xpcshell.ini
-+++ b/im/test/xpcshell.ini
-@@ -6,5 +6,4 @@
- [include:chat/components/src/test/xpcshell.ini]
- [include:chat/protocols/irc/test/xpcshell.ini]
- [include:chat/protocols/skype/test/xpcshell.ini]
--[include:chat/protocols/yahoo/test/xpcshell.ini]
- #[include:extensions/purple/purplexpcom/src/test/xpcshell.ini]
-diff --git a/mail/components/im/content/imconversation.xml b/mail/components/im/content/imconversation.xml
-index 16c665ab4..a4b9fc638 100644
---- a/mail/components/im/content/imconversation.xml
-+++ b/mail/components/im/content/imconversation.xml
-@@ -285,8 +285,7 @@
-                 msg = "<font face=\"" + style.fontFamily + "\">" + msg + "</font>";
-               // MSN doesn't support font size info in messages...
-             }
--            else if (proto == "prpl-aim" || proto == "prpl-icq" ||
--                     proto == "prpl-yahoo" || proto == "prpl-yahoojp") {
-+            else if (proto == "prpl-aim" || proto == "prpl-icq") {
-               let styleAttributes = ""
-               if ("color" in style)
-                 styleAttributes += " color=\"" + style.color + "\"";
--- 
-2.12.2
-
diff --git a/projects/instantbird/0027-Trac-17517-Use-different-color-for-Add-Exception.patch b/projects/instantbird/0027-Trac-17517-Use-different-color-for-Add-Exception.patch
deleted file mode 100644
index c063927..0000000
--- a/projects/instantbird/0027-Trac-17517-Use-different-color-for-Add-Exception.patch
+++ /dev/null
@@ -1,25 +0,0 @@
-From d8da579110668bc37caf42e9e8e88e66fb3aa566 Mon Sep 17 00:00:00 2001
-From: Vu Quoc Huy <huyvq.c633 at gmail.com>
-Date: Tue, 27 Dec 2016 08:31:36 +0700
-Subject: [PATCH 27/28] Trac 17517 - Use different color for Add Exception
-
----
- im/content/accounts.css | 4 ++++
- 1 file changed, 4 insertions(+)
-
-diff --git a/im/content/accounts.css b/im/content/accounts.css
-index 7820b5aaf..bc555acce 100644
---- a/im/content/accounts.css
-+++ b/im/content/accounts.css
-@@ -31,3 +31,7 @@ richlistitem:not([reconnectPending="true"]) description[anonid="reconnect"]
- {
-   display: none;
- }
-+
-+richlistitem[selected="true"] .addException {
-+  color: #fff;
-+}
-\ No newline at end of file
--- 
-2.12.2
-
diff --git a/projects/instantbird/0029-Add-duplicated-files-to-allowed-dupes.mn.patch b/projects/instantbird/0029-Add-duplicated-files-to-allowed-dupes.mn.patch
deleted file mode 100644
index 98ea665..0000000
--- a/projects/instantbird/0029-Add-duplicated-files-to-allowed-dupes.mn.patch
+++ /dev/null
@@ -1,29 +0,0 @@
-From 788fb16fed2bb0910a2385b1b315312c42b9f369 Mon Sep 17 00:00:00 2001
-From: Sukhbir Singh <sukhbir at torproject.org>
-Date: Wed, 28 Jun 2017 16:49:51 -0400
-Subject: [PATCH] Add duplicated files to allowed-dupes.mn
-
----
- im/installer/allowed-dupes.mn | 6 ++++++
- 1 file changed, 6 insertions(+)
-
-diff --git a/im/installer/allowed-dupes.mn b/im/installer/allowed-dupes.mn
-index 988dc2d35a..ed26b72f97 100644
---- a/im/installer/allowed-dupes.mn
-+++ b/im/installer/allowed-dupes.mn
-@@ -10,6 +10,12 @@ chrome/instantbird/skin/classic/instantbird/messages/simple/Variants/Normal.css
- chrome/instantbird/skin/classic/instantbird/messages/simple/Incoming/Context.html
- chrome/instantbird/skin/classic/instantbird/messages/simple/Incoming/NextContext.html
- chrome/chat/content/chat/conv.html
-+chrome/toolkit/skin/classic/global/icons/collapse.png
-+chrome/instantbird/skin/classic/instantbird/collapse.png
-+chrome/toolkit/skin/classic/global/icons/expand.png
-+chrome/instantbird/skin/classic/instantbird/expand.png
-+chrome/icons/default/default16.png
-+icons/default16.png
- 
- # Variants of paths in mozilla/browser/installer/allowed-dupes.mn
- # and mail/installer/allowed-dupes.mn:
--- 
-2.11.0
-
diff --git a/projects/instantbird/config b/projects/instantbird/config
index 3f1b3db..d0b5a52 100644
--- a/projects/instantbird/config
+++ b/projects/instantbird/config
@@ -51,34 +51,24 @@ targets:
 input_files:
   - filename: 0001-Set-Tor-Messenger-preferences.patch
   - filename: 0002-Trac-21634-Autologin-default-should-be-false.patch
-  - filename: 0003-Trac-17896-Support-Special-Characters-input-prompt-o.patch
-  - filename: 0004-Trac-17494-Better-error-reporting-for-failed-outgoin.patch
-  - filename: 0005-Trac-13312-OTR-over-Twitter-DMs.patch
-  - filename: 0006-Bug-1218193-Fix-tab-strip-background-colour-on-OS-X..patch
-  - filename: 0007-Bug-1246431-XMPP-createConversation-should-handle-in.patch
-  - filename: 0008-XMPP-in-band-registration.patch
-  - filename: 0009-Remove-search-from-UI.patch
-  - filename: 0010-Add-Tor-Messenger-branding.patch
-  - filename: 0011-Account-picture.patch
-  - filename: 0012-Modify-protocol-defaults.patch
-  - filename: 0013-Modify-IRC-defaults.patch
-  - filename: 0014-Modify-themes.patch
-  - filename: 0015-Modify-XMPP-defaults.patch
-  - filename: 0016-Remove-logging-UI.patch
-  - filename: 0017-Cert-override.patch
-  - filename: 0018-Display-all-traffic-over-Tor.patch
-  - filename: 0019-Trac-17480-Content-sink.patch
-  - filename: 0020-SASL-ECDSA-NIST256P-CHALLENGE.patch
-  - filename: 0021-Bug-1313137-msg-is-not-defined-error-in-irc.js-chang.patch
-  - filename: 0022-Bug-954368-Contact-list-entries-should-adapt-their-h.patch
-  - filename: 0023-Bug-1187281-Only-show-close-button-on-Windows.patch
-  - filename: 0024-Bug-1316000-Remove-old-Yahoo-Messenger-support.-r-al.patch
-  - filename: 0025-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
-  - filename: 0026-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
-  - filename: 0027-Trac-17517-Use-different-color-for-Add-Exception.patch
-  - filename: 0028-Trac-21736-Hide-account-timestamp-from-message.patch
-  - filename: 0029-Add-duplicated-files-to-allowed-dupes.mn.patch
-    enable: '[% c("var/linux") %]'
+  - filename: 0003-XMPP-in-band-registration.patch
+  - filename: 0004-Remove-search-from-UI.patch
+  - filename: 0005-Add-Tor-Messenger-branding.patch
+  - filename: 0006-Remove-option-for-configuring-account-picture.patch
+  - filename: 0007-Modify-top-protocol-defaults.patch
+  - filename: 0008-Modify-IRC-defaults.patch
+  - filename: 0009-Do-not-set-default-XMPP-server.patch
+  - filename: 0010-Modify-themes.patch
+  - filename: 0011-Remove-logging-UI.patch
+  - filename: 0012-Cert-override.patch
+  - filename: 0013-Display-all-traffic-over-Tor.patch
+  - filename: 0014-Trac-17480-Content-sink.patch
+  - filename: 0015-SASL-ECDSA-NIST256P-CHALLENGE.patch
+  - filename: 0016-Bug-1321641-Use-built-in-functions-instead-of-an-svg.patch
+  - filename: 0017-Bug-1321420-Add-a-pref-to-disable-JavaScript-in-brow.patch
+  - filename: 0018-Trac-17517-Use-different-color-for-Add-Exception.patch
+  - filename: 0019-Trac-21736-Hide-account-timestamp-from-message.patch
+  - filename: 0020-Update-allowed-duplicated-files-for-Windows-and-Linu.patch
   - filename: mozconfig-common
   - filename: 'mozconfig-[% c("var/osname") %]'
     name: mozconfig





More information about the tor-commits mailing list