Bug 795296 - Include the string that couldn't be parsed in XML parse errors of the XMPP stream, r=clokep, a=Standard8.
authorFlorian Quèze <florian@queze.net>
Fri, 28 Sep 2012 15:38:19 +0200
changeset 13458 f0fc137009027780bc9e001b4de25799384af314
parent 13457 583b589da03e19dc13d005dac50ab945bf6fc726
child 13459 5bcf3c0c71b5533840f5c992a46830a2d92c72fc
push id701
push userbugzilla@standard8.plus.com
push dateMon, 08 Oct 2012 19:06:59 +0000
treeherdercomm-beta@c9696e33af8e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersclokep, Standard8
bugs795296
Bug 795296 - Include the string that couldn't be parsed in XML parse errors of the XMPP stream, r=clokep, a=Standard8.
chat/protocols/xmpp/xmpp-session.jsm
--- a/chat/protocols/xmpp/xmpp-session.jsm
+++ b/chat/protocols/xmpp/xmpp-session.jsm
@@ -1,15 +1,15 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const EXPORTED_SYMBOLS = ["XMPPSession", "XMPPDefaultResource"];
 
-const {interfaces: Ci, utils: Cu} = Components;
+const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource:///modules/imXPCOMUtils.jsm");
 Cu.import("resource:///modules/socket.jsm");
 Cu.import("resource:///modules/xmpp-xml.jsm");
 Cu.import("resource:///modules/xmpp-authmechs.jsm");
 
 initLogModule("xmpp-session", this);
 
@@ -69,21 +69,16 @@ XMPPSession.prototype = {
   disconnect: function() {
     if (this.onXmppStanza == this.stanzaListeners.accountListening)
       this.send("</stream:stream>");
     delete this.onXmppStanza;
     Socket.disconnect.call(this);
     if (this._parser) {
       this._parser.destroy();
       delete this._parser;
-      if (this._oldParsers) {
-        for each (let parser in this._oldParsers)
-          parser.destroy();
-        delete this._oldParsers;
-      }
     }
   },
 
   /* Report errors to the account */
   onError: function(aError, aException) {
     this._account.onError(aError, aException);
   },
 
@@ -118,28 +113,18 @@ XMPPSession.prototype = {
       return false;
     this._handlers[aId](aStanza);
     this.removeHandler(aId);
     return true;
   },
 
   /* Start the XMPP stream */
   startStream: function() {
-    if (this._parser) {
-      // nsSAXXMLReader (inside XMPPParser) leaks if we don't clean up.
-      // Unfortunately, calling onStopRequest on nsSAXXMLReader damages
-      // something that causes a crash the next time we call onDataAvailable
-      // on another parser instance for the same input stream buffer.
-      // Workaround: keep references to all previous parsers used
-      // for this socket, and call destroy on each of them when we are
-      // done reading from that socket.
-      if (!this._oldParsers)
-        this._oldParsers = [];
-      this._oldParsers.push(this._parser);
-    }
+    if (this._parser)
+      this._parser.destroy();
     this._parser = new XMPPParser(this);
     this.send('<?xml version="1.0"?><stream:stream to="' + this._domain +
               '" xmlns="jabber:client" xmlns:stream="http://etherx.jabber.org/streams" version="1.0">');
   },
 
   startSession: function() {
     this.sendStanza(Stanza.iq("set", null, null,
                               Stanza.node("session", Stanza.NS.session)));
@@ -174,24 +159,29 @@ XMPPSession.prototype = {
       this._encrypted = true;
     }
     else
       this.onXmppStanza = this.stanzaListeners.initStream;
     this._account.reportConnecting(_("connection.initializingStream"));
     this.startStream();
   },
 
-  /* When incoming data is available to be read */
-  onDataAvailable: function(aRequest, aContext, aInputStream, aOffset, aCount) {
+  /* When incoming data is available to be parsed */
+  onDataReceived: function(aData) {
+    let istream = Cc["@mozilla.org/io/string-input-stream;1"]
+                    .createInstance(Ci.nsIStringInputStream);
+    istream.setData(aData, aData.length);
+    this._lastReceivedData = aData;
     try {
-      this._parser.onDataAvailable(aInputStream, aOffset, aCount);
+      this._parser.onDataAvailable(istream, 0, aData.length);
     } catch(e) {
       Cu.reportError(e);
       this.onXMLError("parser-exception", e);
     }
+    delete this._lastReceivedData;
   },
 
   /* The connection got disconnected without us closing it. */
   onConnectionClosed: function() {
     this._networkError(_("connection.error.serverClosedConnection"));
   },
   onBadCertificate: function(aNSSErrorMessage) {
     this.onError(Ci.prplIAccount.ERROR_CERT_OTHER_ERROR, aNSSErrorMessage);
@@ -205,19 +195,19 @@ XMPPSession.prototype = {
   _networkError: function(aMessage) {
     this.onError(Ci.prplIAccount.ERROR_NETWORK_ERROR, aMessage);
   },
 
 
   /* Methods called by the XMPPParser instance */
   onXMLError: function(aError, aException) {
     if (aError == "parsing-characters")
-      WARN(aError + ": " + aException);
+      WARN(aError + ": " + aException + "\n" + this._lastReceivedData);
     else
-      ERROR(aError + ": " + aException);
+      ERROR(aError + ": " + aException + "\n" + this._lastReceivedData);
     if (aError != "parse-warning" && aError != "parsing-characters")
       this._networkError(_("connection.error.receivedUnexpectedData"));
   },
 
   // All the functions in stanzaListeners are used as onXmppStanza
   // implementations at various steps of establishing the session.
   stanzaListeners: {
     initStream: function(aStanza) {