Bug 1213056 - change getStats to be maplike. draft
authorJan-Ivar Bruaroey <jib@mozilla.com>
Thu, 07 Apr 2016 10:40:37 -0400
changeset 348536 9673a94b75c7c6e282b9dff6881ffebfb3b59718
parent 347760 17a0ded9bb99c05c25729c306b91771483109067
child 348537 88396de99d5f7bfb465b7d169af384f665f33071
push id14838
push userjbruaroey@mozilla.com
push dateThu, 07 Apr 2016 17:14:14 +0000
bugs1213056
milestone48.0a1
Bug 1213056 - change getStats to be maplike. MozReview-Commit-ID: 3nkMtbFfGR2
dom/media/PeerConnection.js
dom/webidl/RTCStatsReport.webidl
--- a/dom/media/PeerConnection.js
+++ b/dom/media/PeerConnection.js
@@ -272,54 +272,44 @@ function RTCStatsReport(win, dict) {
   this._report = convertToRTCStatsReport(dict);
 }
 RTCStatsReport.prototype = {
   classDescription: "RTCStatsReport",
   classID: PC_STATS_CID,
   contractID: PC_STATS_CONTRACT,
   QueryInterface: XPCOMUtils.generateQI([Ci.nsISupports]),
 
-  // TODO: Change to use webidl getters once available (Bug 952122)
+  setInternal: function(aKey, aObj) {
+    return this.__DOM_IMPL__.__set(aKey, aObj);
+  },
+
+  // TODO: Remove legacy API eventually
   //
-  // Since webidl getters are not available, we make the stats available as
+  // Since maplike is recent, we still also make the stats available as legacy
   // enumerable read-only properties directly on our content-facing object.
   // Must be called after our webidl sandwich is made.
 
-  makeStatsPublic: function() {
-    let props = {};
-    this.forEach(function(stat) {
-        props[stat.id] = { enumerable: true, configurable: false,
-                           writable: false, value: stat };
-      });
-    Object.defineProperties(this.__DOM_IMPL__.wrappedJSObject, props);
-  },
-
-  forEach: function(cb, thisArg) {
-    for (var key in this._report) {
-      cb.call(thisArg || this._report, this.get(key), key, this._report);
-    }
-  },
+  makeStatsPublic: function(warnNullable) {
+    let legacyProps = {};
+    for (let key in this._report) {
+      let value = Cu.cloneInto(this._report[key], this._win);
+      this.setInternal(key, value);
 
-  get: function(key) {
-    function publifyReadonly(win, obj) {
-      let props = {};
-      for (let k in obj) {
-        props[k] = {enumerable:true, configurable:false, writable:false, value:obj[k]};
-      }
-      let pubobj = Cu.createObjectIn(win);
-      Object.defineProperties(pubobj, props);
-      return pubobj;
+      legacyProps[key] = {
+        enumerable: true, configurable: false,
+        get: Cu.exportFunction(function() {
+          if (warnNullable.warn) {
+            warnNullable.warn();
+            warnNullable.warn = null;
+          }
+          return value;
+        }, this.__DOM_IMPL__.wrappedJSObject)
+      };
     }
-
-    // Return a content object rather than a wrapped chrome one.
-    return publifyReadonly(this._win, this._report[key]);
-  },
-
-  has: function(key) {
-    return this._report[key] !== undefined;
+    Object.defineProperties(this.__DOM_IMPL__.wrappedJSObject, legacyProps);
   },
 
   get mozPcid() { return this._pcid; }
 };
 
 function RTCPeerConnection() {
   this._senders = [];
   this._receivers = [];
@@ -429,16 +419,21 @@ RTCPeerConnection.prototype = {
 
     this.__DOM_IMPL__._innerObject = this;
     this._observer = new this._win.PeerConnectionObserver(this.__DOM_IMPL__);
 
     var location = "" + this._win.location;
     this._isLoop = location.startsWith("about:loop") ||
                    location.startsWith("https://hello.firefox.com/");
 
+    // Warn just once per PeerConnection about deprecated getStats usage.
+    this._warnDeprecatedStatsAccessNullable = { warn: () =>
+      this.logWarning("non-maplike pc.getStats access is deprecated! " +
+                      "See http://w3c.github.io/webrtc-pc/#example for usage.") };
+
     // Add a reference to the PeerConnection to global list (before init).
     _globalPCList.addPC(this);
 
     this._impl.initialize(this._observer, this._win, rtcConfig,
                           Services.tm.currentThread);
     this._initCertificate(rtcConfig.certificates);
     this._initIdp();
     _globalPCList.notifyLifecycleObservers(this, "initialized");
@@ -1504,17 +1499,17 @@ PeerConnectionObserver.prototype = {
         break;
     }
   },
 
   onGetStatsSuccess: function(dict) {
     let pc = this._dompc;
     let chromeobj = new RTCStatsReport(pc._win, dict);
     let webidlobj = pc._win.RTCStatsReport._create(pc._win, chromeobj);
-    chromeobj.makeStatsPublic();
+    chromeobj.makeStatsPublic(pc._warnDeprecatedStatsAccessNullable);
     pc._onGetStatsSuccess(webidlobj);
   },
 
   onGetStatsError: function(code, message) {
     this._dompc._onGetStatsFailure(this.newError(message, code));
   },
 
   onAddStream: function(stream) {
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -141,18 +141,16 @@ dictionary RTCIceCandidateStats : RTCSta
 dictionary RTCCodecStats : RTCStats {
   unsigned long payloadType;       // As used in RTP encoding.
   DOMString codec;                 // video/vp8 or equivalent
   unsigned long clockRate;
   unsigned long channels;          // 2=stereo, missing for most other cases.
   DOMString parameters;            // From SDP description line
 };
 
-callback RTCStatsReportCallback = void (RTCStatsReport obj);
-
 // This is the internal representation of the report in this implementation
 // to be received from c++
 
 dictionary RTCStatsReportInternal {
   DOMString                           pcid = "";
   sequence<RTCInboundRTPStreamStats>  inboundRTPStreamStats;
   sequence<RTCOutboundRTPStreamStats> outboundRTPStreamStats;
   sequence<RTCMediaStreamTrackStats>  mediaStreamTrackStats;
@@ -168,14 +166,12 @@ dictionary RTCStatsReportInternal {
   boolean                             closed; // Is the PC now closed
 };
 
 [Pref="media.peerconnection.enabled",
 // TODO: Use MapClass here once it's available (Bug 928114)
 // MapClass(DOMString, object)
  JSImplementation="@mozilla.org/dom/rtcstatsreport;1"]
 interface RTCStatsReport {
+  readonly maplike<DOMString, object>;
   [ChromeOnly]
   readonly attribute DOMString mozPcid;
-  void forEach(RTCStatsReportCallback callbackFn, optional any thisArg);
-  object get(DOMString key);
-  boolean has(DOMString key);
 };