Bug 1182040 - Upgrade TokBox SDK to 2.5.2 which fixes the Hello tab sharing feature. r=dmose, a=ritu
authorMike de Boer <mdeboer@mozilla.com>
Wed, 15 Jul 2015 12:53:13 +0200
changeset 281600 4fd3c1a29327286315625ae2fdddc3b59be1e0fd
parent 281599 f6d27aa240d1ce8b58fb9eca2bab617df97f6cbf
child 281601 c9d4b8479814ef67e383a5cca8daaaf33a647a38
push id4932
push userjlund@mozilla.com
push dateMon, 10 Aug 2015 18:23:06 +0000
treeherdermozilla-beta@6dd5a4f5f745 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmose, ritu
bugs1182040
milestone41.0a2
Bug 1182040 - Upgrade TokBox SDK to 2.5.2 which fixes the Hello tab sharing feature. r=dmose, a=ritu
browser/components/loop/content/shared/libs/sdk.js
old mode 100644
new mode 100755
--- a/browser/components/loop/content/shared/libs/sdk.js
+++ b/browser/components/loop/content/shared/libs/sdk.js
@@ -1,31 +1,31 @@
 /**
- * @license  OpenTok JavaScript Library v2.5.1 23265fa HEAD
+ * @license  OpenTok JavaScript Library v2.5.2 f4508e1 2015Q1.patch.1
  * http://www.tokbox.com/
  *
  * Copyright (c) 2014 TokBox, Inc.
  * Released under the MIT license
  * http://opensource.org/licenses/MIT
  *
- * Date: April 13 06:37:42 2015
+ * Date: July 13 05:38:08 2015
  */
 
 
 !(function(window) {
 
 !(function(window, OTHelpers, undefined) {
 
 /**
- * @license  Common JS Helpers on OpenTok 0.3.0 058dfa5 2015Q1
+ * @license  Common JS Helpers on OpenTok 0.3.0 f151b47 HEAD
  * http://www.tokbox.com/
  *
  * Copyright (c) 2015 TokBox, Inc.
  *
- * Date: April 13 06:37:28 2015
+ * Date: July 13 05:37:51 2015
  *
  */
 
 
 // OT Helper Methods
 //
 // helpers.js                           <- the root file
 // helpers/lib/{helper topic}.js        <- specialised helpers for specific tasks/topics
@@ -3711,16 +3711,29 @@ OTHelpers.getCookie = function(key) {
     if (value) {
       return value;
     }
   }
 
   return null;
 };
 
+/*jshint browser:true, smarttabs:true*/
+
+// tb_require('../helpers.js')
+
+OTHelpers.castToBoolean = function(value, defaultValue) {
+  if (value === undefined) return defaultValue;
+  return value === 'true' || value === true;
+};
+
+OTHelpers.roundFloat = function(value, places) {
+  return Number(value.toFixed(places));
+};
+
 // tb_require('../helpers.js')
 
 /* jshint globalstrict: true, strict: false, undef: true, unused: true,
           trailing: true, browser: true, smarttabs:true */
 
 
 OTHelpers.Collection = function(idField) {
   var _models = [],
@@ -3894,29 +3907,16 @@ OTHelpers.Collection = function(idField)
   };
 };
 
 
 /*jshint browser:true, smarttabs:true*/
 
 // tb_require('../helpers.js')
 
-OTHelpers.castToBoolean = function(value, defaultValue) {
-  if (value === undefined) return defaultValue;
-  return value === 'true' || value === true;
-};
-
-OTHelpers.roundFloat = function(value, places) {
-  return Number(value.toFixed(places));
-};
-
-/*jshint browser:true, smarttabs:true*/
-
-// tb_require('../helpers.js')
-
 (function() {
 
   var capabilities = {};
 
   // Registers a new capability type and a function that will indicate
   // whether this client has that capability.
   //
   //   OTHelpers.registerCapability('bundle', function() {
@@ -6100,22 +6100,22 @@ OTHelpers.post = function(url, options, 
   }
 };
 
 
 })(window, window.OTHelpers);
 
 
 /**
- * @license  TB Plugin 0.4.0.10 01e58ad 2015Q1
+ * @license  TB Plugin 0.4.0.10 6935b20 HEAD
  * http://www.tokbox.com/
  *
  * Copyright (c) 2015 TokBox, Inc.
  *
- * Date: April 13 06:37:38 2015
+ * Date: July 13 05:38:06 2015
  *
  */
 
 /* global scope:true */
 /* exported OTPlugin */
 
 /* jshint ignore:start */
 (function(scope) {
@@ -7421,106 +7421,16 @@ var MediaConstraints = function(userCons
 
   this.toHash = function() {
     return constraints;
   };
 };
 
 // tb_require('./header.js')
 // tb_require('./shims.js')
-
-/* global scope:true */
-/* exported  createFrame */
-
-var createFrame = function createFrame (bodyContent, callbackId, callback) {
-  var Proto = function Frame () {},
-      api = new Proto(),
-      domElement = scope.document.createElement('iframe');
-
-  domElement.id = 'OTPlugin_frame_' + $.uuid().replace(/\-+/g, '');
-  domElement.style.border = '0';
-
-  try {
-    domElement.style.backgroundColor = 'rgba(0,0,0,0)';
-  } catch (err) {
-    // Old IE browsers don't support rgba
-    domElement.style.backgroundColor = 'transparent';
-    domElement.setAttribute('allowTransparency', 'true');
-  }
-
-  domElement.scrolling = 'no';
-  domElement.setAttribute('scrolling', 'no');
-
-  // This is necessary for IE, as it will not inherit it's doctype from
-  // the parent frame.
-  var frameContent = '<!DOCTYPE html><html><head>' +
-                    '<meta http-equiv="x-ua-compatible" content="IE=Edge">' +
-                    '<meta http-equiv="Content-type" content="text/html; charset=utf-8">' +
-                    '<title></title></head><body>' +
-                    bodyContent +
-                    '<script>window.parent["' + callbackId + '"](' +
-                      'document.querySelector("object")' +
-                    ');</script></body></html>';
-
-  var wrappedCallback = function() {
-    OTPlugin.log('LOADED IFRAME');
-    var doc = domElement.contentDocument || domElement.contentWindow.document;
-
-    if ($.env.iframeNeedsLoad) {
-      doc.body.style.backgroundColor = 'transparent';
-      doc.body.style.border = 'none';
-
-      if ($.env.name !== 'IE') {
-        // Skip this for IE as we use the bookmarklet workaround
-        // for THAT browser.
-        doc.open();
-        doc.write(frameContent);
-        doc.close();
-      }
-    }
-
-    if (callback) {
-      callback(
-        api,
-        domElement.contentWindow,
-        doc
-      );
-    }
-  };
-
-  scope.document.body.appendChild(domElement);
-
-  if($.env.iframeNeedsLoad) {
-    if ($.env.name === 'IE') {
-      // This works around some issues with IE and document.write.
-      // Basically this works by slightly abusing the bookmarklet/scriptlet
-      // functionality that all browsers support.
-      domElement.contentWindow.contents = frameContent;
-      /*jshint scripturl:true*/
-      domElement.src = 'javascript:window["contents"]';
-      /*jshint scripturl:false*/
-    }
-
-    $.on(domElement, 'load', wrappedCallback);
-  } else {
-    setTimeout(wrappedCallback, 0);
-  }
-
-  api.reparent = function reparent (target) {
-    // document.adoptNode(domElement);
-    target.appendChild(domElement);
-  };
-
-  api.element = domElement;
-
-  return api;
-};
-
-// tb_require('./header.js')
-// tb_require('./shims.js')
 // tb_require('./plugin_proxies.js')
 
 /* global OT:true, OTPlugin:true, ActiveXObject:true,
           PluginProxies:true, curryCallAsync:true */
 
 /* exported AutoUpdater:true */
 var AutoUpdater;
 
@@ -7842,16 +7752,106 @@ var // jshint -W098
 
           $.onDOMUnload(destroy);
         });
       });
     };
 
 // tb_require('./header.js')
 // tb_require('./shims.js')
+
+/* global scope:true */
+/* exported  createFrame */
+
+var createFrame = function createFrame (bodyContent, callbackId, callback) {
+  var Proto = function Frame () {},
+      api = new Proto(),
+      domElement = scope.document.createElement('iframe');
+
+  domElement.id = 'OTPlugin_frame_' + $.uuid().replace(/\-+/g, '');
+  domElement.style.border = '0';
+
+  try {
+    domElement.style.backgroundColor = 'rgba(0,0,0,0)';
+  } catch (err) {
+    // Old IE browsers don't support rgba
+    domElement.style.backgroundColor = 'transparent';
+    domElement.setAttribute('allowTransparency', 'true');
+  }
+
+  domElement.scrolling = 'no';
+  domElement.setAttribute('scrolling', 'no');
+
+  // This is necessary for IE, as it will not inherit it's doctype from
+  // the parent frame.
+  var frameContent = '<!DOCTYPE html><html><head>' +
+                    '<meta http-equiv="x-ua-compatible" content="IE=Edge">' +
+                    '<meta http-equiv="Content-type" content="text/html; charset=utf-8">' +
+                    '<title></title></head><body>' +
+                    bodyContent +
+                    '<script>window.parent["' + callbackId + '"](' +
+                      'document.querySelector("object")' +
+                    ');</script></body></html>';
+
+  var wrappedCallback = function() {
+    OTPlugin.log('LOADED IFRAME');
+    var doc = domElement.contentDocument || domElement.contentWindow.document;
+
+    if ($.env.iframeNeedsLoad) {
+      doc.body.style.backgroundColor = 'transparent';
+      doc.body.style.border = 'none';
+
+      if ($.env.name !== 'IE') {
+        // Skip this for IE as we use the bookmarklet workaround
+        // for THAT browser.
+        doc.open();
+        doc.write(frameContent);
+        doc.close();
+      }
+    }
+
+    if (callback) {
+      callback(
+        api,
+        domElement.contentWindow,
+        doc
+      );
+    }
+  };
+
+  scope.document.body.appendChild(domElement);
+
+  if($.env.iframeNeedsLoad) {
+    if ($.env.name === 'IE') {
+      // This works around some issues with IE and document.write.
+      // Basically this works by slightly abusing the bookmarklet/scriptlet
+      // functionality that all browsers support.
+      domElement.contentWindow.contents = frameContent;
+      /*jshint scripturl:true*/
+      domElement.src = 'javascript:window["contents"]';
+      /*jshint scripturl:false*/
+    }
+
+    $.on(domElement, 'load', wrappedCallback);
+  } else {
+    setTimeout(wrappedCallback, 0);
+  }
+
+  api.reparent = function reparent (target) {
+    // document.adoptNode(domElement);
+    target.appendChild(domElement);
+  };
+
+  api.element = domElement;
+
+  return api;
+};
+
+// tb_require('./header.js')
+// tb_require('./shims.js')
 // tb_require('./proxy.js')
 // tb_require('./auto_updater.js')
 // tb_require('./media_constraints.js')
 // tb_require('./peer_connection.js')
 // tb_require('./media_stream.js')
 // tb_require('./video_container.js')
 // tb_require('./rumor.js')
 // tb_require('./lifecycle.js')
@@ -8060,18 +8060,18 @@ OT.APIKEY = (function(){
 
 
 if (!window.OT) window.OT = OT;
 if (!window.TB) window.TB = OT;
 
 // tb_require('../js/ot.js')
 
 OT.properties = {
-  version: 'v2.5.1',         // The current version (eg. v2.0.4) (This is replaced by gradle)
-  build: '23265fa',    // The current build hash (This is replaced by gradle)
+  version: 'v2.5.2',         // The current version (eg. v2.0.4) (This is replaced by gradle)
+  build: 'f4508e1',    // The current build hash (This is replaced by gradle)
 
   // Whether or not to turn on debug logging by default
   debug: 'false',
   // The URL of the tokbox website
   websiteURL: 'http://www.tokbox.com',
 
   // The URL of the CDN
   cdnURL: 'http://static.opentok.com',
@@ -8248,132 +8248,16 @@ OT.$.userAgent = function() { return OT.
   * @name OT.log
   * @memberof OT
   * @function
   * @see <a href="#setLogLevel">OT.setLogLevel()</a>
   */
 
 // tb_require('../../../helpers/helpers.js')
 
-/* jshint globalstrict: true, strict: false, undef: true, unused: true,
-          trailing: true, browser: true, smarttabs:true */
-/* global OT */
-
-// Rumor Messaging for JS
-//
-// https://tbwiki.tokbox.com/index.php/Rumor_:_Messaging_FrameWork
-//
-// @todo Rumor {
-//     Add error codes for all the error cases
-//     Add Dependability commands
-// }
-
-OT.Rumor = {
-  MessageType: {
-    // This is used to subscribe to address/addresses. The address/addresses the
-    // client specifies here is registered on the server. Once any message is sent to
-    // that address/addresses, the client receives that message.
-    SUBSCRIBE: 0,
-
-    // This is used to unsubscribe to address / addresses. Once the client unsubscribe
-    // to an address, it will stop getting messages sent to that address.
-    UNSUBSCRIBE: 1,
-
-    // This is used to send messages to arbitrary address/ addresses. Messages can be
-    // anything and Rumor will not care about what is included.
-    MESSAGE: 2,
-
-    // This will be the first message that the client sends to the server. It includes
-    // the uniqueId for that client connection and a disconnect_notify address that will
-    // be notified once the client disconnects.
-    CONNECT: 3,
-
-    // This will be the message used by the server to notify an address that a
-    // client disconnected.
-    DISCONNECT: 4,
-
-    //Enhancements to support Keepalives
-    PING: 7,
-    PONG: 8,
-    STATUS: 9
-  }
-};
-
-// tb_require('../../../helpers/helpers.js')
-// tb_require('./rumor.js')
-
-/* jshint globalstrict: true, strict: false, undef: true, unused: true,
-          trailing: true, browser: true, smarttabs:true */
-/* global OT, OTPlugin */
-
-!(function() {
-
-  OT.Rumor.PluginSocket = function(messagingURL, events) {
-
-    var webSocket,
-        state = 'initializing';
-
-    OTPlugin.initRumorSocket(messagingURL, OT.$.bind(function(err, rumorSocket) {
-      if(err) {
-        state = 'closed';
-        events.onClose({ code: 4999 });
-      } else if(state === 'initializing') {
-        webSocket = rumorSocket;
-
-        webSocket.onOpen(function() {
-          state = 'open';
-          events.onOpen();
-        });
-        webSocket.onClose(function(error) {
-          state = 'closed'; /* CLOSED */
-          events.onClose({ code: error });
-        });
-        webSocket.onError(function(error) {
-          state = 'closed'; /* CLOSED */
-          events.onError(error);
-          /* native websockets seem to do this, so should we */
-          events.onClose({ code: error });
-        });
-
-        webSocket.onMessage(function(type, addresses, headers, payload) {
-          var msg = new OT.Rumor.Message(type, addresses, headers, payload);
-          events.onMessage(msg);
-        });
-
-        webSocket.open();
-      } else {
-        this.close();
-      }
-    }, this));
-
-    this.close = function() {
-      if(state === 'initializing' || state === 'closed') {
-        state = 'closed';
-        return;
-      }
-
-      webSocket.close(1000, '');
-    };
-
-    this.send = function(msg) {
-      if(state === 'open') {
-        webSocket.send(msg);
-      }
-    };
-
-    this.isClosed = function() {
-      return state === 'closed';
-    };
-
-  };
-
-}(this));
-
-// tb_require('../../../helpers/helpers.js')
-
 // https://code.google.com/p/stringencoding/
 // An implementation of http://encoding.spec.whatwg.org/#api
 // Modified by TokBox to remove all encoding support except for utf-8
 
 /**
  * @license  Copyright 2014 Joshua Bell
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
@@ -9420,16 +9304,132 @@ OT.Rumor = {
   global['TextEncoder'] = global['TextEncoder'] || TextEncoder;
   global['TextDecoder'] = global['TextDecoder'] || TextDecoder;
 
   /* jshint ignore:end */
 
 }(this));
 
 // tb_require('../../../helpers/helpers.js')
+
+/* jshint globalstrict: true, strict: false, undef: true, unused: true,
+          trailing: true, browser: true, smarttabs:true */
+/* global OT */
+
+// Rumor Messaging for JS
+//
+// https://tbwiki.tokbox.com/index.php/Rumor_:_Messaging_FrameWork
+//
+// @todo Rumor {
+//     Add error codes for all the error cases
+//     Add Dependability commands
+// }
+
+OT.Rumor = {
+  MessageType: {
+    // This is used to subscribe to address/addresses. The address/addresses the
+    // client specifies here is registered on the server. Once any message is sent to
+    // that address/addresses, the client receives that message.
+    SUBSCRIBE: 0,
+
+    // This is used to unsubscribe to address / addresses. Once the client unsubscribe
+    // to an address, it will stop getting messages sent to that address.
+    UNSUBSCRIBE: 1,
+
+    // This is used to send messages to arbitrary address/ addresses. Messages can be
+    // anything and Rumor will not care about what is included.
+    MESSAGE: 2,
+
+    // This will be the first message that the client sends to the server. It includes
+    // the uniqueId for that client connection and a disconnect_notify address that will
+    // be notified once the client disconnects.
+    CONNECT: 3,
+
+    // This will be the message used by the server to notify an address that a
+    // client disconnected.
+    DISCONNECT: 4,
+
+    //Enhancements to support Keepalives
+    PING: 7,
+    PONG: 8,
+    STATUS: 9
+  }
+};
+
+// tb_require('../../../helpers/helpers.js')
+// tb_require('./rumor.js')
+
+/* jshint globalstrict: true, strict: false, undef: true, unused: true,
+          trailing: true, browser: true, smarttabs:true */
+/* global OT, OTPlugin */
+
+!(function() {
+
+  OT.Rumor.PluginSocket = function(messagingURL, events) {
+
+    var webSocket,
+        state = 'initializing';
+
+    OTPlugin.initRumorSocket(messagingURL, OT.$.bind(function(err, rumorSocket) {
+      if(err) {
+        state = 'closed';
+        events.onClose({ code: 4999 });
+      } else if(state === 'initializing') {
+        webSocket = rumorSocket;
+
+        webSocket.onOpen(function() {
+          state = 'open';
+          events.onOpen();
+        });
+        webSocket.onClose(function(error) {
+          state = 'closed'; /* CLOSED */
+          events.onClose({ code: error });
+        });
+        webSocket.onError(function(error) {
+          state = 'closed'; /* CLOSED */
+          events.onError(error);
+          /* native websockets seem to do this, so should we */
+          events.onClose({ code: error });
+        });
+
+        webSocket.onMessage(function(type, addresses, headers, payload) {
+          var msg = new OT.Rumor.Message(type, addresses, headers, payload);
+          events.onMessage(msg);
+        });
+
+        webSocket.open();
+      } else {
+        this.close();
+      }
+    }, this));
+
+    this.close = function() {
+      if(state === 'initializing' || state === 'closed') {
+        state = 'closed';
+        return;
+      }
+
+      webSocket.close(1000, '');
+    };
+
+    this.send = function(msg) {
+      if(state === 'open') {
+        webSocket.send(msg);
+      }
+    };
+
+    this.isClosed = function() {
+      return state === 'closed';
+    };
+
+  };
+
+}(this));
+
+// tb_require('../../../helpers/helpers.js')
 // tb_require('./encoding.js')
 // tb_require('./rumor.js')
 
 /* jshint globalstrict: true, strict: false, undef: true, unused: true,
           trailing: true, browser: true, smarttabs:true */
 /* global OT, TextEncoder, TextDecoder */
 
 //
@@ -16553,16 +16553,150 @@ var loadCSS = function loadCSS(cssURL) {
   style.media = 'screen';
   style.rel = 'stylesheet';
   style.href = cssURL;
   var head = document.head || document.getElementsByTagName('head')[0];
   head.appendChild(style);
 };
 
 // tb_require('../helpers.js')
+
+/* jshint globalstrict: true, strict: false, undef: true, unused: true,
+          trailing: true, browser: true, smarttabs:true */
+/* global OTPlugin, OT */
+
+///
+// Capabilities
+//
+// Support functions to query browser/client Media capabilities.
+//
+
+
+// Indicates whether this client supports the getUserMedia
+// API.
+//
+OT.$.registerCapability('getUserMedia', function() {
+  if (OT.$.env === 'Node') return false;
+  return !!(navigator.webkitGetUserMedia ||
+            navigator.mozGetUserMedia ||
+            OTPlugin.isInstalled());
+});
+
+
+
+// TODO Remove all PeerConnection stuff, that belongs to the messaging layer not the Media layer.
+// Indicates whether this client supports the PeerConnection
+// API.
+//
+// Chrome Issues:
+// * The explicit prototype.addStream check is because webkitRTCPeerConnection was
+// partially implemented, but not functional, in Chrome 22.
+//
+// Firefox Issues:
+// * No real support before Firefox 19
+// * Firefox 19 has issues with generating Offers.
+// * Firefox 20 doesn't interoperate with Chrome.
+//
+OT.$.registerCapability('PeerConnection', function() {
+  if (OT.$.env === 'Node') {
+    return false;
+  }
+  else if (typeof(window.webkitRTCPeerConnection) === 'function' &&
+                    !!window.webkitRTCPeerConnection.prototype.addStream) {
+    return true;
+  } else if (typeof(window.mozRTCPeerConnection) === 'function' && OT.$.env.version > 20.0) {
+    return true;
+  } else {
+    return OTPlugin.isInstalled();
+  }
+});
+
+
+
+// Indicates whether this client supports WebRTC
+//
+// This is defined as: getUserMedia + PeerConnection + exceeds min browser version
+//
+OT.$.registerCapability('webrtc', function() {
+  if (OT.properties) {
+    var minimumVersions = OT.properties.minimumVersion || {},
+        minimumVersion = minimumVersions[OT.$.env.name.toLowerCase()];
+
+    if(minimumVersion && OT.$.env.versionGreaterThan(minimumVersion)) {
+      OT.debug('Support for', OT.$.env.name, 'is disabled because we require',
+        minimumVersion, 'but this is', OT.$.env.version);
+      return false;
+    }
+  }
+
+  if (OT.$.env === 'Node') {
+    // Node works, even though it doesn't have getUserMedia
+    return true;
+  }
+
+  return OT.$.hasCapabilities('getUserMedia', 'PeerConnection');
+});
+
+
+// TODO Remove all transport stuff, that belongs to the messaging layer not the Media layer.
+// Indicates if the browser supports bundle
+//
+// Broadly:
+// * Firefox doesn't support bundle
+// * Chrome support bundle
+// * OT Plugin supports bundle
+// * We assume NodeJs supports bundle (e.g. 'you're on your own' mode)
+//
+OT.$.registerCapability('bundle', function() {
+  return OT.$.hasCapabilities('webrtc') &&
+            (OT.$.env.name === 'Chrome' ||
+              OT.$.env.name === 'Node' ||
+              OTPlugin.isInstalled());
+});
+
+// Indicates if the browser supports RTCP Mux
+//
+// Broadly:
+// * Older versions of Firefox (<= 25) don't support RTCP Mux
+// * Older versions of Firefox (>= 26) support RTCP Mux (not tested yet)
+// * Chrome support RTCP Mux
+// * OT Plugin supports RTCP Mux
+// * We assume NodeJs supports RTCP Mux (e.g. 'you're on your own' mode)
+//
+OT.$.registerCapability('RTCPMux', function() {
+  return OT.$.hasCapabilities('webrtc') &&
+              (OT.$.env.name === 'Chrome' ||
+                OT.$.env.name === 'Node' ||
+                OTPlugin.isInstalled());
+});
+
+
+
+// Indicates whether this browser supports the getMediaDevices (getSources) API.
+//
+OT.$.registerCapability('getMediaDevices', function() {
+  return OT.$.isFunction(window.MediaStreamTrack) &&
+            OT.$.isFunction(window.MediaStreamTrack.getSources);
+});
+
+
+OT.$.registerCapability('audioOutputLevelStat', function() {
+  return OT.$.env.name === 'Chrome' || OT.$.env.name === 'IE';
+});
+
+OT.$.registerCapability('webAudioCapableRemoteStream', function() {
+  return OT.$.env.name === 'Firefox';
+});
+
+OT.$.registerCapability('webAudio', function() {
+  return 'AudioContext' in window;
+});
+
+
+// tb_require('../helpers.js')
 // tb_require('./properties.js')
 
 /* jshint globalstrict: true, strict: false, undef: true, unused: true,
           trailing: true, browser: true, smarttabs:true */
 /* global OT */
 
 //--------------------------------------
 // JS Dynamic Config
@@ -16702,150 +16836,16 @@ OT.Config = (function() {
   };
 
   OT.$.eventing(_this);
 
   return _this;
 })();
 
 // tb_require('../helpers.js')
-
-/* jshint globalstrict: true, strict: false, undef: true, unused: true,
-          trailing: true, browser: true, smarttabs:true */
-/* global OTPlugin, OT */
-
-///
-// Capabilities
-//
-// Support functions to query browser/client Media capabilities.
-//
-
-
-// Indicates whether this client supports the getUserMedia
-// API.
-//
-OT.$.registerCapability('getUserMedia', function() {
-  if (OT.$.env === 'Node') return false;
-  return !!(navigator.webkitGetUserMedia ||
-            navigator.mozGetUserMedia ||
-            OTPlugin.isInstalled());
-});
-
-
-
-// TODO Remove all PeerConnection stuff, that belongs to the messaging layer not the Media layer.
-// Indicates whether this client supports the PeerConnection
-// API.
-//
-// Chrome Issues:
-// * The explicit prototype.addStream check is because webkitRTCPeerConnection was
-// partially implemented, but not functional, in Chrome 22.
-//
-// Firefox Issues:
-// * No real support before Firefox 19
-// * Firefox 19 has issues with generating Offers.
-// * Firefox 20 doesn't interoperate with Chrome.
-//
-OT.$.registerCapability('PeerConnection', function() {
-  if (OT.$.env === 'Node') {
-    return false;
-  }
-  else if (typeof(window.webkitRTCPeerConnection) === 'function' &&
-                    !!window.webkitRTCPeerConnection.prototype.addStream) {
-    return true;
-  } else if (typeof(window.mozRTCPeerConnection) === 'function' && OT.$.env.version > 20.0) {
-    return true;
-  } else {
-    return OTPlugin.isInstalled();
-  }
-});
-
-
-
-// Indicates whether this client supports WebRTC
-//
-// This is defined as: getUserMedia + PeerConnection + exceeds min browser version
-//
-OT.$.registerCapability('webrtc', function() {
-  if (OT.properties) {
-    var minimumVersions = OT.properties.minimumVersion || {},
-        minimumVersion = minimumVersions[OT.$.env.name.toLowerCase()];
-
-    if(minimumVersion && OT.$.env.versionGreaterThan(minimumVersion)) {
-      OT.debug('Support for', OT.$.env.name, 'is disabled because we require',
-        minimumVersion, 'but this is', OT.$.env.version);
-      return false;
-    }
-  }
-
-  if (OT.$.env === 'Node') {
-    // Node works, even though it doesn't have getUserMedia
-    return true;
-  }
-
-  return OT.$.hasCapabilities('getUserMedia', 'PeerConnection');
-});
-
-
-// TODO Remove all transport stuff, that belongs to the messaging layer not the Media layer.
-// Indicates if the browser supports bundle
-//
-// Broadly:
-// * Firefox doesn't support bundle
-// * Chrome support bundle
-// * OT Plugin supports bundle
-// * We assume NodeJs supports bundle (e.g. 'you're on your own' mode)
-//
-OT.$.registerCapability('bundle', function() {
-  return OT.$.hasCapabilities('webrtc') &&
-            (OT.$.env.name === 'Chrome' ||
-              OT.$.env.name === 'Node' ||
-              OTPlugin.isInstalled());
-});
-
-// Indicates if the browser supports RTCP Mux
-//
-// Broadly:
-// * Older versions of Firefox (<= 25) don't support RTCP Mux
-// * Older versions of Firefox (>= 26) support RTCP Mux (not tested yet)
-// * Chrome support RTCP Mux
-// * OT Plugin supports RTCP Mux
-// * We assume NodeJs supports RTCP Mux (e.g. 'you're on your own' mode)
-//
-OT.$.registerCapability('RTCPMux', function() {
-  return OT.$.hasCapabilities('webrtc') &&
-              (OT.$.env.name === 'Chrome' ||
-                OT.$.env.name === 'Node' ||
-                OTPlugin.isInstalled());
-});
-
-
-
-// Indicates whether this browser supports the getMediaDevices (getSources) API.
-//
-OT.$.registerCapability('getMediaDevices', function() {
-  return OT.$.isFunction(window.MediaStreamTrack) &&
-            OT.$.isFunction(window.MediaStreamTrack.getSources);
-});
-
-
-OT.$.registerCapability('audioOutputLevelStat', function() {
-  return OT.$.env.name === 'Chrome' || OT.$.env.name === 'IE';
-});
-
-OT.$.registerCapability('webAudioCapableRemoteStream', function() {
-  return OT.$.env.name === 'Firefox';
-});
-
-OT.$.registerCapability('webAudio', function() {
-  return 'AudioContext' in window;
-});
-
-
-// tb_require('../helpers.js')
 // tb_require('./config.js')
 
 /* jshint globalstrict: true, strict: false, undef: true, unused: true,
           trailing: true, browser: true, smarttabs:true */
 /* global OT */
 
 
 OT.Analytics = function(loggingUrl) {
@@ -25965,19 +25965,19 @@ OT.Publisher = function(options) {
             }
 
             var replacePromises = [];
 
             Object.keys(_peerConnections).forEach(function(connectionId) {
               var peerConnection = _peerConnections[connectionId];
               peerConnection.getSenders().forEach(function(sender) {
                 if (sender.track.kind === 'audio' && newStream.getAudioTracks().length) {
-                  replacePromises.push(sender.switchTracks(newStream.getAudioTracks()[0]));
+                  replacePromises.push(sender.replaceTrack(newStream.getAudioTracks()[0]));
                 } else if (sender.track.kind === 'video' && newStream.getVideoTracks().length) {
-                  replacePromises.push(sender.switchTracks(newStream.getVideoTracks()[0]));
+                  replacePromises.push(sender.replaceTrack(newStream.getVideoTracks()[0]));
                 }
               });
             });
 
             Promise.all(replacePromises).then(resolve, reject);
           },
           function(error) {
             onStreamAvailableError(error);
@@ -26244,16 +26244,48 @@ OT.Publisher = function(options) {
  * @memberof Publisher
  * @see StreamEvent
  */
 };
 
 // Helper function to generate unique publisher ids
 OT.Publisher.nextId = OT.$.uuid;
 
+// tb_require('./helpers/lib/css_loader.js')
+// tb_require('./ot/system_requirements.js')
+// tb_require('./ot/session.js')
+// tb_require('./ot/publisher.js')
+// tb_require('./ot/subscriber.js')
+// tb_require('./ot/archive.js')
+// tb_require('./ot/connection.js')
+// tb_require('./ot/stream.js')
+// We want this to be included at the end, just before footer.js
+
+/* jshint globalstrict: true, strict: false, undef: true, unused: true,
+          trailing: true, browser: true, smarttabs:true */
+/* global loadCSS, define */
+
+// Tidy up everything on unload
+OT.onUnload(function() {
+  OT.publishers.destroy();
+  OT.subscribers.destroy();
+  OT.sessions.destroy('unloaded');
+});
+
+loadCSS(OT.properties.cssURL);
+
+// Register as a named AMD module, since TokBox could be concatenated with other
+// files that may use define, but not via a proper concatenation script that
+// understands anonymous AMD modules. A named AMD is safest and most robust
+// way to register. Uppercase TB is used because AMD module names are
+// derived from file names, and OpenTok is normally delivered in an uppercase
+// file name.
+if (typeof define === 'function' && define.amd) {
+  define( 'TB', [], function () { return TB; } );
+}
 // tb_require('../../conf/properties.js')
 // tb_require('../ot.js')
 // tb_require('./session.js')
 // tb_require('./publisher.js')
 
 /* jshint globalstrict: true, strict: false, undef: true, unused: true,
           trailing: true, browser: true, smarttabs:true */
 /* global OT */
@@ -26943,47 +26975,15 @@ OT.components = {};
  * @name exception
  * @event
  * @borrows ExceptionEvent#message as this.message
  * @memberof OT
  * @see ExceptionEvent
  */
 
 
-// tb_require('./helpers/lib/css_loader.js')
-// tb_require('./ot/system_requirements.js')
-// tb_require('./ot/session.js')
-// tb_require('./ot/publisher.js')
-// tb_require('./ot/subscriber.js')
-// tb_require('./ot/archive.js')
-// tb_require('./ot/connection.js')
-// tb_require('./ot/stream.js')
-// We want this to be included at the end, just before footer.js
-
-/* jshint globalstrict: true, strict: false, undef: true, unused: true,
-          trailing: true, browser: true, smarttabs:true */
-/* global loadCSS, define */
-
-// Tidy up everything on unload
-OT.onUnload(function() {
-  OT.publishers.destroy();
-  OT.subscribers.destroy();
-  OT.sessions.destroy('unloaded');
-});
-
-loadCSS(OT.properties.cssURL);
-
-// Register as a named AMD module, since TokBox could be concatenated with other
-// files that may use define, but not via a proper concatenation script that
-// understands anonymous AMD modules. A named AMD is safest and most robust
-// way to register. Uppercase TB is used because AMD module names are
-// derived from file names, and OpenTok is normally delivered in an uppercase
-// file name.
-if (typeof define === 'function' && define.amd) {
-  define( 'TB', [], function () { return TB; } );
-}
 // tb_require('./postscript.js')
 
 /* jshint ignore:start */
 })(window, window.OT);
 /* jshint ignore:end */
 
 })(window || exports);
\ No newline at end of file