Bug 970734 - Part 1: When ICE fails, log a pointer to about:webrtc in the JS console. r=jib
authorByron Campen [:bwc] <docfaraday@gmail.com>
Thu, 10 Apr 2014 10:33:08 -0700
changeset 180062 1e1d541b2f3c3cd532f6ed8ade50336e998d2db6
parent 180061 b68c399920f06d78e82476fc578139e948ad445c
child 180063 039b15c9b84e10c738f47c81ff03deb4fabd0a66
push id272
push userpvanderbeken@mozilla.com
push dateMon, 05 May 2014 16:31:18 +0000
reviewersjib
bugs970734
milestone31.0a1
Bug 970734 - Part 1: When ICE fails, log a pointer to about:webrtc in the JS console. r=jib
dom/media/PeerConnection.js
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -345,17 +345,17 @@ RTCPeerConnection.prototype = {
           "RTCPeerConnection is gone (did you enter Offline mode?)");
     }
     return this._pc;
   },
 
   _initIdp: function() {
     let prefName = "media.peerconnection.identity.timeout";
     let idpTimeout = Services.prefs.getIntPref(prefName);
-    let warningFunc = this.reportWarning.bind(this);
+    let warningFunc = this.logWarning.bind(this);
     this._localIdp = new PeerConnectionIdp(this._win, idpTimeout, warningFunc,
                                            this.dispatchEvent.bind(this));
     this._remoteIdp = new PeerConnectionIdp(this._win, idpTimeout, warningFunc,
                                             this.dispatchEvent.bind(this));
   },
 
   /**
    * Add a function to the queue or run it immediately if the queue is empty.
@@ -495,51 +495,48 @@ RTCPeerConnection.prototype = {
     }
   },
 
   dispatchEvent: function(event) {
     this.__DOM_IMPL__.dispatchEvent(event);
   },
 
   // Log error message to web console and window.onerror, if present.
-  reportError: function(msg, file, line) {
-    this.reportMsg(msg, file, line, Ci.nsIScriptError.exceptionFlag);
+  logErrorAndCallOnError: function(msg, file, line) {
+    this.logMsg(msg, file, line, Ci.nsIScriptError.exceptionFlag);
+
+    // Safely call onerror directly if present (necessary for testing)
+    try {
+      if (typeof this._win.onerror === "function") {
+        this._win.onerror(msg, file, line);
+      }
+    } catch(e) {
+      // If onerror itself throws, service it.
+      try {
+        this.logError(e.message, e.fileName, e.lineNumber);
+      } catch(e) {}
+    }
   },
 
-  reportWarning: function(msg, file, line) {
-    this.reportMsg(msg, file, line, Ci.nsIScriptError.warningFlag);
+  logError: function(msg, file, line) {
+    this.logMsg(msg, file, line, Ci.nsIScriptError.errorFlag);
   },
 
-  reportMsg: function(msg, file, line, flag) {
+  logWarning: function(msg, file, line) {
+    this.logMsg(msg, file, line, Ci.nsIScriptError.warningFlag);
+  },
+
+  logMsg: function(msg, file, line, flag) {
     let scriptErrorClass = Cc["@mozilla.org/scripterror;1"];
     let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
     scriptError.initWithWindowID(msg, file, null, line, 0, flag,
                                  "content javascript", this._winID);
     let console = Cc["@mozilla.org/consoleservice;1"].
       getService(Ci.nsIConsoleService);
     console.logMessage(scriptError);
-
-    if (flag != Ci.nsIScriptError.warningFlag) {
-      // Safely call onerror directly if present (necessary for testing)
-      try {
-        if (typeof this._win.onerror === "function") {
-          this._win.onerror(msg, file, line);
-        }
-      } catch(e) {
-        // If onerror itself throws, service it.
-        try {
-          let scriptError = scriptErrorClass.createInstance(Ci.nsIScriptError);
-          scriptError.initWithWindowID(e.message, e.fileName, null, e.lineNumber,
-                                       0, Ci.nsIScriptError.exceptionFlag,
-                                       "content javascript",
-                                       this._winID);
-          console.logMessage(scriptError);
-        } catch(e) {}
-      }
-    }
   },
 
   getEH: function(type) {
     return this.__DOM_IMPL__.getEventHandler(type);
   },
 
   setEH: function(type, handler) {
     this.__DOM_IMPL__.setEventHandler(type, handler);
@@ -658,17 +655,17 @@ RTCPeerConnection.prototype = {
         throw new this._win.DOMError("",
             "Invalid type " + desc.type + " provided to setRemoteDescription");
     }
 
     try {
       let processIdentity = this._processIdentity.bind(this);
       this._remoteIdp.verifyIdentityFromSDP(desc.sdp, processIdentity);
     } catch (e) {
-      this.reportWarning(e.message, e.fileName, e.lineNumber);
+      this.logWarning(e.message, e.fileName, e.lineNumber);
       // only happens if processing the SDP for identity doesn't work
       // let _setRemoteDescription do the error reporting
     }
 
     this._queueOrRun({
       func: this._setRemoteDescription,
       args: [type, desc.sdp, onSuccess, onError],
       wait: true,
@@ -858,30 +855,30 @@ RTCPeerConnection.prototype = {
 
   createDataChannel: function(label, dict) {
     this._checkClosed();
     if (dict == undefined) {
       dict = {};
     }
     if (dict.maxRetransmitNum != undefined) {
       dict.maxRetransmits = dict.maxRetransmitNum;
-      this.reportWarning("Deprecated RTCDataChannelInit dictionary entry maxRetransmitNum used!", null, 0);
+      this.logWarning("Deprecated RTCDataChannelInit dictionary entry maxRetransmitNum used!", null, 0);
     }
     if (dict.outOfOrderAllowed != undefined) {
       dict.ordered = !dict.outOfOrderAllowed; // the meaning is swapped with
                                               // the name change
-      this.reportWarning("Deprecated RTCDataChannelInit dictionary entry outOfOrderAllowed used!", null, 0);
+      this.logWarning("Deprecated RTCDataChannelInit dictionary entry outOfOrderAllowed used!", null, 0);
     }
     if (dict.preset != undefined) {
       dict.negotiated = dict.preset;
-      this.reportWarning("Deprecated RTCDataChannelInit dictionary entry preset used!", null, 0);
+      this.logWarning("Deprecated RTCDataChannelInit dictionary entry preset used!", null, 0);
     }
     if (dict.stream != undefined) {
       dict.id = dict.stream;
-      this.reportWarning("Deprecated RTCDataChannelInit dictionary entry stream used!", null, 0);
+      this.logWarning("Deprecated RTCDataChannelInit dictionary entry stream used!", null, 0);
     }
 
     if (dict.maxRetransmitTime != undefined &&
         dict.maxRetransmits != undefined) {
       throw new this._win.DOMError("",
           "Both maxRetransmitTime and maxRetransmits cannot be provided");
     }
     let protocol;
@@ -970,17 +967,19 @@ PeerConnectionObserver.prototype = {
   callCB: function(callback, arg) {
     if (callback) {
       try {
         callback(arg);
       } catch(e) {
         // A content script (user-provided) callback threw an error. We don't
         // want this to take down peerconnection, but we still want the user
         // to see it, so we catch it, report it, and move on.
-        this._dompc.reportError(e.message, e.fileName, e.lineNumber);
+        this._dompc.logErrorAndCallOnError(e.message,
+                                           e.fileName,
+                                           e.lineNumber);
       }
     }
   },
 
   onCreateOfferSuccess: function(sdp) {
     let pc = this._dompc;
     let fp = pc._impl.fingerprint;
     pc._localIdp.appendIdentityToSDP(sdp, fp, function(sdp, assertion) {
@@ -1111,16 +1110,17 @@ PeerConnectionObserver.prototype = {
   //   closed        The ICE Agent has shut down and is no longer responding to
   //                 STUN requests.
 
   handleIceConnectionStateChange: function(iceConnectionState) {
     var histogram = Services.telemetry.getHistogramById("WEBRTC_ICE_SUCCESS_RATE");
 
     if (iceConnectionState === 'failed') {
       histogram.add(false);
+      this._dompc.logError("ICE failed, see about:webrtc for more details", null, 0);
     }
     if (this._dompc.iceConnectionState === 'checking' &&
         (iceConnectionState === 'completed' ||
          iceConnectionState === 'connected')) {
           histogram.add(true);
     }
     this._dompc.changeIceConnectionState(iceConnectionState);
   },
@@ -1181,17 +1181,17 @@ PeerConnectionObserver.prototype = {
         // No-op
         break;
 
       case "SipccState":
         // No-op
         break;
 
       default:
-        this._dompc.reportWarning("Unhandled state type: " + state, null, 0);
+        this._dompc.logWarning("Unhandled state type: " + state, null, 0);
         break;
     }
   },
 
   onGetStatsSuccess: function(dict) {
     let chromeobj = new RTCStatsReport(this._dompc._win, dict);
     let webidlobj = this._dompc._win.RTCStatsReport._create(this._dompc._win,
                                                             chromeobj);