diff --git a/.gitignore b/.gitignore
index 212e58e..10e3786 100644
--- a/.gitignore
+++ b/.gitignore
@@ -87,3 +87,7 @@ publish
staging
_site
source/config/local.json
+node_modules/
+demo/
+doc/
+doc-style/
diff --git a/Gruntfile.js b/Gruntfile.js
index f7b9b0f..de42e64 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -4,6 +4,7 @@ module.exports = function (grunt) {
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-uglify');
+ grunt.loadNpmTasks('grunt-replace');
grunt.initConfig({
@@ -21,8 +22,8 @@ module.exports = function (grunt) {
concat: {
options: {
- separator: ';',
- stripBanners: true,
+ separator: '\n',
+ stripBanners: false,
banner: '/*! <%= pkg.name %> - v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> */\n\n'
},
@@ -49,6 +50,25 @@ module.exports = function (grunt) {
}
},
+ replace: {
+ dist: {
+ options: {
+ variables: {
+ 'version': '<%= pkg.version %>'
+ },
+ prefix: '@@'
+ },
+ files: [{
+ expand: true,
+ flatten: true,
+ src: [
+ '<%= production %>/*.js'
+ ],
+ dest: '<%= production %>/'
+ }]
+ }
+ },
+
jshint: {
build: {
options: grunt.util._.merge({
@@ -86,7 +106,7 @@ module.exports = function (grunt) {
grunt.registerTask('publish', [
'clean:production',
'concat:production',
+ 'replace:dist',
'uglify:production_min'
]);
-
-};
+};
\ No newline at end of file
diff --git a/README.md b/README.md
index c070eb4..c302291 100644
--- a/README.md
+++ b/README.md
@@ -17,19 +17,12 @@ AdapterJS provides polyfills and cross-browser helpers for WebRTC. It wraps arou
#### Polyfills
-`RTCPeerConnection`, `RTCDataChannel` and `navigator.getUserMedia`
+`RTCPeerConnection`, `RTCIceCandidate`, `RTCSessionDescription`, `MediaStreamTrack`, `navigator.getUserMedia`, `attachMediaStream`, `reattachMediaStream`
+## Using AdapterJS
#### Helper functions
-##### `attachMediaStream(videoelement, stream)`
-
-universally adds a stream object to a video element
-
-##### `reattachMediaStream(videoelement, videoelement)`
-
-universally copies a stream object from one video element to another
-
##### `createIceServer(url, username, password)`
creates a valid iceServer from one url, username and password
@@ -38,57 +31,63 @@ creates a valid iceServer from one url, username and password
creates a valid iceServers array for the specific browser and version.
-##### `checkIceConnectionState(peerID, iceConnectionState, callback, returnStateAlways)`
+##### `maybeFixConfiguration(pcConfig)`
+
+Fixes the incompability of `urls` attribute in some browsers.
+
+
-handles all the iceConnectionState differences cross-browsers. Order of return values are 'checking' > 'connected' > 'completed'.
+##### `checkIceConnectionState(peerId, iceConnectionState, callback)`
+
+handles all the iceConnectionState differences cross-browsers. Order of return values are `'checking' > 'connected' > 'completed'`.
+tested outcomes in Firefox returns `'checking' > 'connected'` for both offerer and answerer.
+
+Tested outcomes:
+- Chrome (offerer) : `'checking' > 'completed' > 'completed'`
+- Chrome (answerer) : `'checking' > 'connected'`
+- Firefox (offerer) : `'checking' > 'connected'`
+- Firefox (answerer) : `'checking' > 'connected'`
```javascript
peerConnection.oniceconnectionstatechange = function () {
- checkICEConnectionState(peerID, peerConnection.iceConnectionState, function (iceConnectionState) {
+ checkICEConnectionState(peerId, peerConnection.iceConnectionState, function (updatedIceConnectionState) {
// do Something every time there's a new state ['checking', 'connected', 'completed']
});
};
```
-##### `checkMediaDataChannelSettings(isOffer, peerBrowserAgent, callback, constraints)`
+##### `checkMediaDataChannelSettings(peerAgentBrowser, peerAgentVersion, callback, constraints)`
handles all MediaStream and DataChannel differences for interopability cross-browsers.
-method has to be called before sending the acknowledge to create the offer and before creating the offer
+method has to be called before creating the offer to check if peer should create the offer.
+
+For some older (20+) versions of Firefox and Chrome MediaStream interopability, `MozDontOfferDataChannel` has to be used, and hence Firefox cannot establish a DataChannel connection as an offerer, and results in no DataChannel connection. To achieve both MediaStream and DataChannel connection interopability, Chrome or other browsers has to be the one creating the offer.
```javascript
-// Right now we are not yet doing the offer. We are just checking if we should be the offerer instead of
-// the other peer
-var isOffer = false;
-// You may use "webrtcDetectedBrowser" Helper function to get the peer to send browser information
-var peerAgentBrowser = peerBrowserName + '|' + peerBrowserVersion;
-checkMediaDataChannelSettings(false, peerAgentBrowser, function (beOfferer) {
+// Right now we are not yet doing the offer. We are just checking if we should be the offerer instead of the other peer
+checkMediaDataChannelSettings(peerAgentBrowser, peerAgentVersion
+ function (beOfferer, unifiedOfferConstraints) {
if (beOfferer) {
- // be the one who does the offer
+ peerConnection.createOffer(function (offer) {
+ // success
+ }, function (error) {
+ // failure
+ }, unifiedOfferConstraints);
} else {
- // your peer does the offer
+ // let the other peer do the offer instead.
}
-});
+}, inputConstraints);
```
-```javascript
-// We are going to do the offer so we need to check the constraints first.
-var isOffer = true;
-// You may use "webrtcDetectedBrowser" Helper variable to get the peer to send browser information
-var peerAgentBrowser = peerBrowserName + '|' + peerBrowserVersion;
-checkMediaDataChannelSettings(isOffer, peerAgentBrowser, function (offerConstraints) {
- peerConnection.createOffer(function (offer) {
- // success
- }, function (error) {
- // failure
- }, offerConstraints);
-}, constraints);
-```
+#### Helper variables
+
+##### `webrtcDetectedType`
-### Helper variables
+displays the browser webrtc implementation type.
-##### `webrtcDetectedBrowser`
+##### `webrtcDetectedDCSupport`
-displays all the browser information and the webrtc type of support
+displays the browser webrtc datachannel support type.
## Setup this project
@@ -123,4 +122,4 @@ Tape tests
## License
-APACHE 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html
+APACHE 2.0 - http://www.apache.org/licenses/LICENSE-2.0.html
\ No newline at end of file
diff --git a/package.json b/package.json
index 5df5981..561dbe9 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"name": "adapterjs",
"description": "Creating a common API for WebRTC in the browser",
- "version": "0.0.2",
+ "version": "0.9.0",
"homepage": "https://temasys.github.io/",
"author": {
"name": "Temasys Communications Pte. Ltd.",
@@ -25,6 +25,7 @@
"grunt-contrib-concat": "0.3.0",
"grunt-contrib-jshint": "0.3.0",
"grunt-contrib-uglify": "^0.5.0",
+ "grunt-replace": "0.7.9",
"tape": "2.12.0"
},
"testling": {
diff --git a/publish/adapter.debug.js b/publish/adapter.debug.js
index 5c84de2..b537b8b 100644
--- a/publish/adapter.debug.js
+++ b/publish/adapter.debug.js
@@ -1,73 +1,193 @@
-/*! adapterjs - v0.0.2 - 2014-07-10 */
+/*! adapterjs - v0.9.0 - 2014-09-09 */
-RTCPeerConnection = null;
/**
- * Note:
- * Get UserMedia (only difference is the prefix).
- * [Credits] Code from Adam Barth.
- *
- * [attribute] RTCIceCandidate
- * [type] Function
+ * Temasys reserved namespace.
+ * - This are where all Temasys implemented functions are.
+ * - Interface are called "classes" because yuidoc does not support interfaces.
+ * - Functions and variables are not encapsulated except Temasys private
+ * functions and variables.
+ * @class Temasys
*/
-getUserMedia = null;
+var Temasys = Temasys || {};
/**
- * Note:
- * Attach a media stream to an element.
- *
- * [attribute] attachMediaStream
- * [type] Function
+ * Temasys plugin interface.
+ * - WARNING: You may be required to [download our plugin](https:
+ * /temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins) if you are using
+ * Internet Explorer, Safari or older supported browsers (Chrome, Opera, Firefox).
+ * @class Temasys.WebRTCPlugin
+ * @for Temasys
*/
-attachMediaStream = null;
+Temasys.WebRTCPlugin = Temasys.WebRTCPlugin || {};
/**
- * Note:
- * Re-attach a media stream to an element.
- *
- * [attribute] reattachMediaStream
- * [type] Function
+ * Adapter's interface.
+ * @class Temasys.AdapterJS
+ * @extends Temasys
*/
-reattachMediaStream = null;
+Temasys.AdapterJS = {
+ VERSION: '0.9.0'
+};
/**
- * Note:
- * This function detects whether or not a plugin is installed
- * - Com name : the company name,
- * - plugName : the plugin name
- * - installedCb : callback if the plugin is detected (no argument)
- * - notInstalledCb : callback if the plugin is not detected (no argument)
+ * This function detects whether or not a plugin is installed.
+ * Checks if Not IE (firefox, for example), else if it's IE,
+ * we're running IE and do something. If not it is not supported.
* @method isPluginInstalled
- * @protected
+ * @param {String} comName The company name.
+ * @param {String} plugName The plugin name.
+ * @param {Function} installedCb The callback fired if the plugin is detected
+ * @param {Function} notInstalledCb The callback fired
+ * if the plugin is not detected (no argument).
+ * @return {Boolean} Is plugin installed.
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.isPluginInstalled = null;
+/**
+ * Check if WebRTC Interface is defined.
+ * @method isDefined
+ * @param {String} variable The variable to check.
+ * @return {Boolean} If variable is defined.
+ * @private
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.isDefined = null;
+/**
+ * Inject the HTML DOM object element into the page.
+ * @method injectPlugin
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.injectPlugin = null;
+/**
+ * Does a waiting check before proceeding to load the plugin.
+ * @method WaitForPluginReady
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.WaitForPluginReady = null;
+/**
+ * This methid will use an interval to wait for the plugin to be ready.
+ * @for Temasys.WebRTCPlugin
+*/
+Temasys.WebRTCPlugin.callWhenPluginReady = null;
+/**
+ * This function will be called if the plugin is needed (browser different
+ * from Chrome or Firefox), but the plugin is not installed.
+ * Override it according to your application logic.
+ * @method pluginNeededButNotInstalledCb
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb = null;
+/**
+ * The object to store plugin information
+ * @attribute temPluginInfo
+ * @type JSON
+ * @readOnly
+ * @required
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.temPluginInfo = {
+ pluginId : 'plugin0',
+ type : 'application/x-temwebrtcplugin',
+ onload : '__TemWebRTCReady0'
+};
+/**
+ * Unique identifier of each opened page
+ * @attribute TemPageId
+ * @type String
+ * @readOnly
+ * @required
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.TemPageId = Math.random().toString(36).slice(2);
+/**
+ * Use this whenever you want to call the plugin.
+ * @attribute TemRTCPlugin
+ * @type <>Object
+ * @readOnly
+ * @for Temasys.WebRTCPlugin
*/
-isPluginInstalled = null;
+Temasys.WebRTCPlugin.TemRTCPlugin = null;
/**
- * Note:
- * defines webrtc's JS interface according to the plugin's implementation
- * [attribute] defineWebRTCInterface
- * [type] Function
+ * Plugin ready status.
+ * @attribute isPluginReady
+ * @type Boolean
+ * @for Temasys.WebRTCPlugin
*/
-defineWebRTCInterface = null;
+Temasys.WebRTCPlugin.isPluginReady = false;
+/**
+ * Defines webrtc's JS interface according to the plugin's implementation.
+ * - Define plugin Browsers as WebRTC Interface.
+ * @method defineWebRTCInterface
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.defineWebRTCInterface = null;
+/**
+ * This function will be called when plugin is ready. It sends necessary
+ * details to the plugin.
+ * - WARNING: DO NOT OVERRIDE THIS FUNCTION.
+ * - If you need to do something once the page/plugin is ready, override
+ * window.onwebrtcready instead.
+ * - This function is not in the IE/Safari condition brackets so that
+ * TemPluginLoaded function might be called on Chrome/Firefox.
+ * - This function is the only private function that is not encapsulated to
+ * allow the plugin method to be called.
+ * @method __TemWebRTCReady0
+ * @for Temasys
+ * @private
+ */
+__TemWebRTCReady0 = function () {
+ arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
+ if (arguments.callee.StaticWasInit === 1) {
+ Temasys.WebRTCPlugin.documentReadyInterval = setInterval(function () {
+ if (document.readyState === 'complete') {
+ // TODO: update comments, we wait for the document to be ready
+ clearInterval(Temasys.WebRTCPlugin.documentReadyInterval);
+ Temasys.WebRTCPlugin.isPluginReady = true;
+ Temasys.WebRTCPlugin.pluginReadyState =
+ Temasys.WebRTCPlugin.pluginReadyStates.ready;
+ }
+ }, 100);
+ }
+ arguments.callee.StaticWasInit++;
+};
/**
- * Note:
- * This function will be called if the plugin is needed
- * (browser different from Chrome or Firefox),
- * but the plugin is not installed
- * Override it according to your application logic.
- * [attribute] pluginNeededButNotInstalledCb
- * [type] Function
+ * The results of each states returns.
+ * @attribute pluginReadyStates
+ * @type JSON
+ * @param {Integer} init Plugin is loading.
+ * @param {Integer} ready Plugin has been loaded and is ready to use.
+ * @readOnly
+ * @for Temasys.WebRTCPlugin
*/
-pluginNeededButNotInstalledCb = null;
+Temasys.WebRTCPlugin.pluginReadyStates = {
+ init : 0,
+ ready : 1
+};
/**
- * Note:
- * The Object used in SkywayJS to check the WebRTC Detected type
- * [attribute] WebRTCDetectedBrowser
- * [type] JSON
+ * State of Plugin ready
+ * @attribute pluginReadyState
+ * @type String
+ * @readyOnly
+ * @for Temasys.WebRTCPlugin
*/
-webrtcDetectedBrowser = {};
+Temasys.WebRTCPlugin.pluginReadyState = Temasys.WebRTCPlugin.pluginReadyStates.init;
/**
- * Note:
- * The results of each states returns
- * @attribute ICEConnectionState
+ * The result of ice connection states.
+ * @attribute _iceConnectionStates
* @type JSON
+ * @param {String} starting: Ice connection is starting.
+ * @param {String} checking: Ice connection is checking.
+ * @param {String} connected Ice connection is connected.
+ * @param {String} completed Ice connection is connected.
+ * @param {String} done Ice connection has been completed.
+ * @param {String} disconnected Ice connection has been disconnected.
+ * @param {String} failed Ice connection has failed.
+ * @param {String} closed Ice connection is closed.
+ * @for Temasys
+ * @private
*/
-ICEConnectionState = {
+Temasys._iceConnectionStates = {
starting : 'starting',
checking : 'checking',
connected : 'connected',
@@ -78,178 +198,94 @@ ICEConnectionState = {
closed : 'closed'
};
/**
- * Note:
- * The states of each Peer
- * @attribute ICEConnectionFiredStates
- * @type JSON
+ * The IceConnection states that has been fired for each peer.
+ * @attribute _iceConnectionFiredStates
+ * @type Array
+ * @for Temasys
+ * @private
*/
-ICEConnectionFiredStates = {};
+Temasys._iceConnectionFiredStates = [];
/**
- * Note:
- * The Object to store the list of DataChannels
- * [attribute] RTCDataChannels
- * [type] JSON
+ * This function helps to retrieve the webrtc detected browser information.
+ * This sets:
+ * - webrtcDetectedBrowser: The browser agent name.
+ * - webrtcDetectedVersion: The browser version.
+ * - webrtcDetectedType: The types of webRTC support.
+ * - 'moz': Mozilla implementation of webRTC.
+ * - 'webkit': WebKit implementation of webRTC.
+ * - 'plugin': Using Temasys's plugin implementation.
+ * @method parseWebrtcDetectedBrowser
+ * @for Temasys
*/
-RTCDataChannels = {};
-/**
- * Note:
- * The Object to store Plugin information
- * [attribute] temPluginInfo
- * [type] JSON
- */
-temPluginInfo = {
- pluginId : 'plugin0',
- type : 'application/x-temwebrtcplugin',
- onload : 'TemInitPlugin0'
-};
-/**
- * Note:
- * Unique identifier of each opened page
- * [attribute] TemPageId
- * [type] String
- */
-TemPageId = Math.random().toString(36).slice(2);
-/**
- * Note:
- * - Latest Opera supports Webkit WebRTC
- * - IE is detected as Safari
- * - Older Firefox and Chrome does not support WebRTC
- * - Detected "Safari" Browsers:
- * - Firefox 1.0+
- * - IE 6+
- * - Safari 3+: '[object HTMLElementConstructor]'
- * - Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
- * - Chrome 1+
- * 1st Step: Get browser OS
- * 2nd Step: Check browser DataChannels Support
- * 3rd Step: Check browser WebRTC Support type
- * 4th Step: Get browser version
- * @author Get version of Browser. Code provided by kennebec@stackoverflow.com
- * @author IsSCTP/isRTPD Supported. Code provided by DetectRTC by Muaz Khan
- *
- * @method getBrowserVersion
- * @protected
- */
-getBrowserVersion = function () {
- var agent = {},
- na = navigator,
- ua = na.userAgent,
- tem;
- var M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
-
- if (na.mozGetUserMedia) {
- agent.mozWebRTC = true;
- } else if (na.webkitGetUserMedia) {
- agent.webkitWebRTC = true;
- } else {
- if (ua.indexOf('Safari')) {
- if (typeof InstallTrigger !== 'undefined') {
- agent.browser = 'Firefox';
- } else if (/*@cc_on!@*/
- false || !!document.documentMode) {
- agent.browser = 'IE';
- } else if (
- Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
- agent.browser = 'Safari';
- } else if (!!window.opera || na.userAgent.indexOf(' OPR/') >= 0) {
- agent.browser = 'Opera';
- } else if (!!window.chrome) {
- agent.browser = 'Chrome';
- }
- agent.pluginWebRTC = true;
+parseWebrtcDetectedBrowser = function () {
+ var hasMatch, checkMatch = navigator.userAgent.match(
+ /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
+ if (/trident/i.test(checkMatch[1])) {
+ hasMatch = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
+ webrtcDetectedBrowser = 'IE';
+ webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10);
+ } else if (checkMatch[1] === 'Chrome') {
+ hasMatch = navigator.userAgent.match(/\bOPR\/(\d+)/);
+ if (hasMatch !== null) {
+ webrtcDetectedBrowser = 'opera';
+ webrtcDetectedVersion = parseInt(hasMatch[1], 10);
}
}
- if (/trident/i.test(M[1])) {
- tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
- agent.browser = 'IE';
- agent.version = parseInt(tem[1] || '0', 10);
- } else if (M[1] === 'Chrome') {
- tem = ua.match(/\bOPR\/(\d+)/);
- if (tem !== null) {
- agent.browser = 'Opera';
- agent.version = parseInt(tem[1], 10);
+ if (navigator.userAgent.indexOf('Safari')) {
+ if (typeof InstallTrigger !== 'undefined') {
+ webrtcDetectedBrowser = 'firefox';
+ } else if (/*@cc_on!@*/ false || !!document.documentMode) {
+ webrtcDetectedBrowser = 'IE';
+ } else if (
+ Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
+ webrtcDetectedBrowser = 'safari';
+ } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
+ webrtcDetectedBrowser = 'opera';
+ } else if (!!window.chrome) {
+ webrtcDetectedBrowser = 'chrome';
}
}
- if (!agent.browser) {
- agent.browser = M[1];
+ if (!webrtcDetectedBrowser) {
+ webrtcDetectedVersion = checkMatch[1];
}
- if (!agent.version) {
+ if (!webrtcDetectedVersion) {
try {
- M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
- if ((tem = ua.match(/version\/(\d+)/i)) !== null) {
- M.splice(1, 1, tem[1]);
+ checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] :
+ [navigator.appName, navigator.appVersion, '-?'];
+ if ((hasMatch = navigator.userAgent.match(/version\/(\d+)/i)) !== null) {
+ checkMatch.splice(1, 1, hasMatch[1]);
}
- agent.version = parseInt(M[1], 10);
- } catch (err) {
- agent.version = 0;
- }
+ webrtcDetectedVersion = parseInt(checkMatch[1], 10);
+ } catch (error) { }
}
- agent.os = navigator.platform;
- agent.isSCTPDCSupported = agent.mozWebRTC ||
- (agent.browser === 'Chrome' && agent.version > 30) ||
- (agent.browser === 'Opera' && agent.version > 19);
- agent.isRTPDCSupported = agent.browser === 'Chrome' && agent.version < 30 && agent.version > 24;
- agent.isPluginSupported = !agent.isSCTPDCSupported && !agent.isRTPDCSupported;
- return agent;
-};
-webrtcDetectedBrowser = getBrowserVersion();
-/**
- * Note:
- * use this whenever you want to call the plugin
- * [attribute] plugin
- * [type DOM] {Object}
- * [protected]
- */
-TemRTCPlugin = null;
-/**
- * Note:
- * webRTC readu Cb, should only be called once.
- * Need to prevent Chrome + plugin form calling WebRTCReadyCb twice
- * --------------------------------------------------------------------------
- * WebRTCReadyCb is callback function called when the browser is webrtc ready
- * this can be because of the browser or because of the plugin
- * Override WebRTCReadyCb and use it to do whatever you need to do when the
- * page is ready
- * [attribute] TemPrivateWebRTCReadyCb
- * [type] Function
- * [private]
- */
-TemPrivateWebRTCReadyCb = function () {
- arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
- if (arguments.callee.StaticWasInit === 1) {
- if (typeof WebRTCReadyCb === 'function') {
- WebRTCReadyCb();
- }
- }
- arguments.callee.StaticWasInit++;
};
/**
- * Note:
- * !!! DO NOT OVERRIDE THIS FUNCTION !!!
- * This function will be called when plugin is ready
- * it sends necessary details to the plugin.
- * If you need to do something once the page/plugin is ready, override
- * TemPrivateWebRTCReadyCb instead.
- * This function is not in the IE/Safari condition brackets so that
- * TemPluginLoaded function might be called on Chrome/Firefox
- * [attribute] TemInitPlugin0
- * [type] Function
- * [protected]
- */
-TemInitPlugin0 = function () {
- TemRTCPlugin.setPluginId(TemPageId, temPluginInfo.pluginId);
- TemRTCPlugin.setLogFunction(console);
- TemPrivateWebRTCReadyCb();
-};
+ * Detected webrtc implementation. Types are:
+ * - 'moz': Mozilla implementation of webRTC.
+ * - 'webkit': WebKit implementation of webRTC.
+ * - 'plugin': Using Temasys's plugin implementation.
+ * @attribute webrtcDetectedType
+ * @type String
+ * @readOnly
+ * @for Temasys
+ */
+webrtcDetectedType = null;
+/**
+ * Detected webrtc datachannel support. Types are:
+ * - 'SCTP': SCTP datachannel support.
+ * - 'RTP': RTP datachannel support.
+ * @attribute webrtcDetectedDCSupport
+ * @type String
+ * @readOnly
+ * @for Temasys
+ */
+webrtcDetectedDCSupport = null;
/**
- * Note:
- * To Fix Configuration as some browsers,
- * some browsers does not support the 'urls' attribute
- * - .urls is not supported in FF yet.
- * [attribute] maybeFixConfiguration
- * [type] Function
- * _ [param] {JSON} pcConfig
- * [private]
+ * To fix configuration as some browsers does not support
+ * the 'urls' attribute.
+ * @method maybeFixConfiguration
+ * @param {JSON} pcConfig
+ * @for Temasys
*/
maybeFixConfiguration = function (pcConfig) {
if (pcConfig === null) {
@@ -263,129 +299,321 @@ maybeFixConfiguration = function (pcConfig) {
}
};
/**
- * Note:
- * Handles the differences for all Browsers
- *
+ * Set the settings for creating DataChannels, MediaStream for
+ * Cross-browser compability.
+ * - This is only for SCTP based support browsers.
+ * the 'urls' attribute.
+ * @method checkMediaDataChannelSettings
+ * @param {Boolean} isParseOC If function just needs to parse the offer constraints.
+ * @param {String} peerBrowserAgent Peer browser agent.
+ * @param {String} peerBrowserVersion Peer browser version.
+ * @param {Function} callback The callback once it's done.
+ * @param {JSON} constraints The offer constraints.
+ * @example
+ * checkMediaDataChannelSettings(peerAgentBrowser, peerAgentVersion,
+ * function (beOfferer, unifiedOfferConstraints) {
+ * if (beOfferer) {
+ * peerConnection.createOffer(function (offer) {
+ * // success
+ * }, function (error) {
+ * // failure
+ * }, unifiedOfferConstraints);
+ * } else {
+ * // let someone else do the job
+ * }
+ * }, inputConstraints);
+ * @for Temasys
+ */
+checkMediaDataChannelSettings =
+ function (peerBrowserAgent, peerBrowserVersion, callback, constraints) {
+ if (typeof callback !== 'function') {
+ return;
+ }
+ var beOfferer = true;
+ var isLocalFirefox = webrtcDetectedBrowser === 'firefox';
+ // Nightly version does not require MozDontOfferDataChannel for interop
+ var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30;
+ var isPeerFirefox = peerBrowserAgent === 'firefox';
+ var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' &&
+ ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
+
+ // Resends an updated version of constraints for MozDataChannel to work
+ // If other userAgent is firefox and user is firefox, remove MozDataChannel
+ if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
+ try {
+ delete constraints.mandatory.MozDontOfferDataChannel;
+ } catch (error) {
+ console.error('Failed deleting MozDontOfferDataChannel');
+ console.error(error);
+ }
+ } else if ((isLocalFirefox && !isPeerFirefox)) {
+ constraints.mandatory.MozDontOfferDataChannel = true;
+ }
+ if (!isLocalFirefox) {
+ // temporary measure to remove Moz* constraints in non Firefox browsers
+ for (var prop in constraints.mandatory) {
+ if (constraints.mandatory.hasOwnProperty(prop)) {
+ if (prop.indexOf('Moz') !== -1) {
+ delete constraints.mandatory[prop];
+ }
+ }
+ }
+ }
+ // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
+ // interopability of the media stream
+ if (isLocalFirefox && !isPeerFirefox && !isPeerFirefoxInterop) {
+ beOfferer = false;
+ }
+ callback(beOfferer, constraints);
+};
+/**
+ * Handles the differences for all browsers ice connection state output.
+ * - Tested outcomes are:
+ * - Chrome (offerer) : 'checking' > 'completed' > 'completed'
+ * - Chrome (answerer) : 'checking' > 'connected'
+ * - Firefox (offerer) : 'checking' > 'connected'
+ * - Firefox (answerer): 'checking' > 'connected'
* @method checkIceConnectionState
- * @param {String} peerID
- * @param {String} iceConnectionState
- * @param {Function} callback
- * @param {Boolean} returnStateAlways
- * @protected
+ * @param {String} peerId A unique identifier for the peer.
+ * @param {String} iceConnectionState The current ice connection state.
+ * @param {Function} callback The callback fired once the state is loaded.
+ * @return {String} The updated ice connection state.
+ * @example
+ * peerConnection.oniceconnectionstatechange = function () {
+ * checkICEConnectionState(peerId, peerConnection.iceConnectionState,
+ * function (updatedIceConnectionState) {
+ * // do Something every time there's a new state
+ * });
+ * };
+ * @for Temasys
*/
-checkIceConnectionState = function (peerID, iceConnectionState, callback, returnStateAlways) {
+checkIceConnectionState = function (peerId, iceConnectionState, callback) {
if (typeof callback !== 'function') {
+ console.warn('No callback specified in checkIceConnectionState. Aborted.');
return;
}
- peerID = (peerID) ? peerID : 'peer';
- var returnState = false, err = null;
- console.log('ICECONNECTIONSTATE: ' + iceConnectionState);
-
- if (!ICEConnectionFiredStates[peerID] ||
- iceConnectionState === ICEConnectionState.disconnected ||
- iceConnectionState === ICEConnectionState.failed ||
- iceConnectionState === ICEConnectionState.closed) {
- ICEConnectionFiredStates[peerID] = [];
+ peerId = (peerId) ? peerId : 'peer';
+
+ if (!Temasys._iceConnectionStates[peerId] ||
+ iceConnectionState === Temasys._iceConnectionStates.disconnected ||
+ iceConnectionState === Temasys._iceConnectionStates.failed ||
+ iceConnectionState === Temasys._iceConnectionStates.closed) {
+ Temasys._iceConnectionStates[peerId] = [];
}
- iceConnectionState = ICEConnectionState[iceConnectionState];
- if (ICEConnectionFiredStates[peerID].indexOf(iceConnectionState) === -1) {
- ICEConnectionFiredStates[peerID].push(iceConnectionState);
- if (iceConnectionState === ICEConnectionState.connected) {
+ iceConnectionState = Temasys._iceConnectionStates[iceConnectionState];
+ if (Temasys._iceConnectionStates[peerId].indexOf(iceConnectionState) < 0) {
+ Temasys._iceConnectionStates[peerId].push(iceConnectionState);
+ if (iceConnectionState === Temasys._iceConnectionStates.connected) {
setTimeout(function () {
- ICEConnectionFiredStates[peerID].push(ICEConnectionState.done);
- callback(ICEConnectionState.done);
+ Temasys._iceConnectionStates[peerId]
+ .push(Temasys._iceConnectionStates.done);
+ callback(Temasys._iceConnectionStates.done);
}, 1000);
}
- returnState = true;
- }
- if (returnStateAlways || returnState) {
callback(iceConnectionState);
}
return;
};
/**
- * Note:
- * Set the settings for creating DataChannels, MediaStream for Cross-browser compability.
- * This is only for SCTP based support browsers
- *
- * @method checkMediaDataChannelSettings
- * @param {Boolean} isOffer
- * @param {String} peerBrowserAgent
- * @param {Function} callback
+ * Check the availability of the MediaStream and DataChannel.
+ * Method to be called after getUserMedia
+ * @method checkMediaDataChannel
+ * @param {MediaStream} stream
* @param {JSON} constraints
- * @protected
+ * @for Temasys
*/
-checkMediaDataChannelSettings = function (isOffer, peerBrowserAgent, callback, constraints) {
- if (typeof callback !== 'function') {
- return;
+checkMediaDataChannel = function (stream, constraints) {
+ var testedOptions = {
+ audio : false,
+ video : false,
+ data : false
+ };
+ // Test MediaStream
+ if (constraints.audio && stream.getAudioTracks().length > 0) {
+ testedOptions.audio = true;
}
- var peerBrowserVersion, beOfferer = false;
-
- console.log('Self: ' + webrtcDetectedBrowser.browser + ' | Peer: ' + peerBrowserAgent);
-
- if (peerBrowserAgent.indexOf('|') > -1) {
- peerBrowser = peerBrowserAgent.split('|');
- peerBrowserAgent = peerBrowser[0];
- peerBrowserVersion = parseInt(peerBrowser[1], 10);
- console.info('Peer Browser version: ' + peerBrowserVersion);
+ if (constraints.video && stream.getVideoTracks().length > 0) {
+ testedOptions.video = true;
}
- var isLocalFirefox = webrtcDetectedBrowser.mozWebRTC;
- // Nightly version does not require MozDontOfferDataChannel for interop
- var isLocalFirefoxInterop = webrtcDetectedBrowser.mozWebRTC &&
- webrtcDetectedBrowser.version > 30;
- var isPeerFirefox = peerBrowserAgent === 'Firefox';
- var isPeerFirefoxInterop = peerBrowserAgent === 'Firefox' &&
- ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
-
- // Resends an updated version of constraints for MozDataChannel to work
- // If other userAgent is firefox and user is firefox, remove MozDataChannel
- if (isOffer) {
- if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
- try {
- delete constraints.mandatory.MozDontOfferDataChannel;
- } catch (err) {
- console.error('Failed deleting MozDontOfferDataChannel');
- console.exception(err);
- }
- } else if ((isLocalFirefox && !isPeerFirefox)) {
- constraints.mandatory.MozDontOfferDataChannel = true;
- }
- if (!isLocalFirefox) {
- // temporary measure to remove Moz* constraints in non Firefox browsers
- for (var prop in constraints.mandatory) {
- if (constraints.mandatory.hasOwnProperty(prop)) {
- if (prop.indexOf('Moz') !== -1) {
- delete constraints.mandatory[prop];
- }
- }
- }
- }
- console.log('Set Offer constraints for DataChannel and MediaStream interopability');
- console.dir(constraints);
- callback(constraints);
- } else {
- // Tells user to resend an 'enter' again
- // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
- // interopability of the media stream
- if (!isLocalFirefox && isPeerFirefox && !isPeerFirefoxInterop) {
- beOfferer = true;
+ // Test DataChannel
+ var testPeer = new RTCPeerConnection();
+ try {
+ var dc = testPeer.createDataChannel('_');
+ if (dc) {
+ testedOptions.data = true;
}
- console.info('Resend Enter: ' + beOfferer);
- callback(beOfferer);
+ } catch (error) {
+ console.error('Failed creating DataChannel');
+ console.error(error);
}
+ return testedOptions;
};
-/*******************************************************************
- Check for browser types and react accordingly
-*******************************************************************/
-if (webrtcDetectedBrowser.mozWebRTC) {
- /**
- * Note:
- * Creates a RTCPeerConnection object for moz
- *
- * [method] RTCPeerConnection
- * [param] {JSON} pcConfig
- * [param] {JSON} pcConstraints
- */
+/**
+ * AdapterJS original google code.
+ * - Adapted from: https://code.google.com/p/webrtc/source/
+ * browse/trunk/samples/js/base/adapter.js?r=3905
+ * @class Original
+ */
+/**
+ * The RTCPeerConnection object.
+ * @function RTCPeerConnection
+ * @param {JSON} pcConfig Servers configuration
+ * @param {JSON} pcConstraints Constraints
+ * @return {Object} The PeerConnection object.
+ * @for Original
+ */
+RTCPeerConnection = null;
+/**
+ * Plugin:
+ * - Creates RTCSessionDescription object for Plugin Browsers
+ * - This is a WebRTC Function
+ * @method RTCSessionDescription
+ * @param {JSON} info
+ * @return {Object} The RTCSessionDescription object
+ * @for Original
+ */
+RTCSessionDescription = (typeof RTCSessionDescription === 'function') ?
+ RTCSessionDescription : null;
+/**
+ * Plugin:
+ * - Creates RTCIceCandidate object for Plugin Browsers
+ * - This is a WebRTC Function
+ * @method RTCIceCandidate
+ * @param {Object} candidate
+ * @return {Object} The RTCIceCandidate object
+ * @for Original
+ */
+RTCIceCandidate = (typeof RTCIceCandidate === 'function') ?
+ RTCIceCandidate : null;
+/**
+ * Get UserMedia (only difference is the prefix).
+ * @function getUserMedia
+ * @param {JSON} mediaConstraints Media constraints
+ * @param {JSON} successCallback Callback when MediaStream is obtained
+ * successfully.
+ * @param {JSON} failuedCallback Callback when MediaStream failed to
+ * be obtained.
+ * @return {Object} The MediaStream object.
+ * @author Adam Barth.
+ * @for Original
+ */
+getUserMedia = null;
+/**
+ * Attach a media stream to an element.
+ * @function attachMediaStream
+ * @param {DOM} videoElement The Video element
+ * @param {Object} mediaStream The MediaStream object
+ * @for Original
+ */
+attachMediaStream = null;
+/**
+ * Re-attach a media stream to an element.
+ * @function reattachMediaStream
+ * @param {DOM} fromVideoElement The Video element with the stream url
+ * @param {DOM} toVideoElement The Video element to be duplicated with
+ * the stream url.
+ * @for Original
+ */
+reattachMediaStream = null;
+/**
+ * Firefox:
+ * - Creates iceServer from the url for Firefox.
+ * - Create iceServer with stun url.
+ * - Create iceServer with turn url.
+ * - Ignore the transport parameter from TURN url for FF version <=27.
+ * - Return null for createIceServer if transport=tcp.
+ * - FF 27 and above supports transport parameters in TURN url,
+ * - So passing in the full url to create iceServer.
+ * Chrome:
+ * - Creates iceServer from the url for Chrome M33 and earlier.
+ * - Create iceServer with stun url.
+ * - Chrome M28 & above uses below TURN format.
+ * Plugin:
+ * - Creates Ice Server for Plugin Browsers
+ * - If Stun - Create iceServer with stun url.
+ * - Else - Create iceServer with turn url
+ * - This is a WebRTC Function
+ * @method createIceServer
+ * @param {String} url
+ * @param {String} username
+ * @param {String} password
+ * @return {JSON} Ice Server Configuration
+ * @for Original
+ */
+createIceServer = null;
+/**
+ * Firefox:
+ * - Creates IceServers for Firefox
+ * - Use .url for FireFox.
+ * - Multiple Urls support
+ * Chrome:
+ * - Creates iceServers from the urls for Chrome M34 and above.
+ * - .urls is supported since Chrome M34.
+ * - Multiple Urls support
+ * Plugin:
+ * - Creates Ice Servers for Plugin Browsers
+ * - Multiple Urls support
+ * - This is a WebRTC Function
+ * @method createIceServers
+ * @param {Array} urls
+ * @param {String} username
+ * @param {String} password
+ * @return {Array} List of Ice Servers Configuration
+ * @for Original
+ */
+createIceServers = null;
+/**
+ * Firefox:
+ * - Creates IceServers for Firefox
+ * - Use .url for FireFox.
+ * - Multiple Urls support
+ * Chrome:
+ * - Creates iceServers from the urls for Chrome M34 and above.
+ * - .urls is supported since Chrome M34.
+ * - Multiple Urls support
+ * Plugin:
+ * - Creates Ice Servers for Plugin Browsers
+ * - Multiple Urls support
+ * - This is a WebRTC Function
+ * @method createIceServers
+ * @param {Array} urls
+ * @param {String} username
+ * @param {String} password
+ * @return {Array} List of Ice Servers Configuration
+ * @for Original
+ */
+createIceServers = null;
+/**
+ * Detected browser agent name. Types are:
+ * - 'firefox': Firefox browser.
+ * - 'chrome': Chrome browser.
+ * - 'opera': Opera browser.
+ * - 'safari': Safari browser.
+ * - 'IE' - Internet Explorer browser.
+ * @attribute webrtcDetectedBrowser
+ * @type String
+ * @readOnly
+ * @required
+ * @for Original
+ */
+webrtcDetectedBrowser = null;
+/**
+ * Detected browser version.
+ * @attribute webrtcDetectedVersion
+ * @type Integer
+ * @readOnly
+ * @required
+ * @for Original
+ */
+webrtcDetectedVersion = null;
+// Check for browser types and react accordingly
+if (navigator.mozGetUserMedia) {
+ webrtcDetectedBrowser = 'firefox';
+ webrtcDetectedVersion = parseInt(navigator
+ .userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+ webrtcDetectedType = 'moz';
+ webrtcDetectedDCSupport = 'SCTP';
+
RTCPeerConnection = function (pcConfig, pcConstraints) {
maybeFixConfiguration(pcConfig);
return new mozRTCPeerConnection(pcConfig, pcConstraints);
@@ -396,57 +624,33 @@ if (webrtcDetectedBrowser.mozWebRTC) {
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Creates iceServer from the url for Firefox.
- * - Create iceServer with stun url.
- * - Create iceServer with turn url.
- * - Ignore the transport parameter from TURN url for FF version <=27.
- * - Return null for createIceServer if transport=tcp.
- * - FF 27 and above supports transport parameters in TURN url,
- * - So passing in the full url to create iceServer.
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { 'url' : url };
+ iceServer = { url : url };
} else if (url_parts[0].indexOf('turn') === 0) {
- if (webrtcDetectedBrowser.version < 27) {
+ if (webrtcDetectedVersion < 27) {
var turn_url_parts = url.split('?');
- if (turn_url_parts.length === 1 || turn_url_parts[1].indexOf('transport=udp') === 0) {
+ if (turn_url_parts.length === 1 ||
+ turn_url_parts[1].indexOf('transport=udp') === 0) {
iceServer = {
- 'url' : turn_url_parts[0],
- 'credential' : password,
- 'username' : username
+ url : turn_url_parts[0],
+ credential : password,
+ username : username
};
}
} else {
iceServer = {
- 'url' : url,
- 'credential' : password,
- 'username' : username
+ url : url,
+ credential : password,
+ username : username
};
}
}
return iceServer;
};
- /**
- * Note:
- * Creates IceServers for Firefox
- * - Use .url for FireFox.
- * - Multiple Urls support
- *
- * [method] createIceServers
- * [param] {JSON} pcConfig
- * [param] {JSON} pcConstraints
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
for (i = 0; i < urls.length; i++) {
@@ -458,39 +662,19 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Attach Media Stream for moz
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
- console.log('Attaching media stream');
element.mozSrcObject = stream;
element.play();
return element;
};
- /**
- * Note:
- * Re-attach Media Stream for moz
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
- console.log('Reattaching media stream');
to.mozSrcObject = from.mozSrcObject;
to.play();
return to;
};
- /*******************************************************
- Fake get{Video,Audio}Tracks
- ********************************************************/
+ // Fake get{Video,Audio}Tracks
if (!MediaStream.prototype.getVideoTracks) {
MediaStream.prototype.getVideoTracks = function () {
return [];
@@ -501,19 +685,28 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return [];
};
}
- TemPrivateWebRTCReadyCb();
-} else if (webrtcDetectedBrowser.webkitWebRTC) {
- /**
- * Note:
- * Creates iceServer from the url for Chrome M33 and earlier.
- * - Create iceServer with stun url.
- * - Chrome M28 & above uses below TURN format.
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
+} else if (navigator.webkitGetUserMedia) {
+ webrtcDetectedBrowser = 'chrome';
+ webrtcDetectedType = 'webkit';
+ webrtcDetectedVersion = parseInt(navigator
+ .userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+ // check if browser is opera 20+
+ var checkIfOpera = navigator.userAgent.match(/\bOPR\/(\d+)/);
+ if (checkIfOpera !== null) {
+ webrtcDetectedBrowser = 'opera';
+ webrtcDetectedVersion = parseInt(checkIfOpera[1], 10);
+ }
+ // check browser datachannel support
+ if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) ||
+ (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) {
+ webrtcDetectedDCSupport = 'SCTP';
+ } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 &&
+ webrtcDetectedVersion > 24) {
+ webrtcDetectedDCSupport = 'RTP';
+ } else {
+ webrtcDetectedDCSupport = '';
+ }
+
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
@@ -529,20 +722,9 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServer;
};
- /**
- * Note:
- * Creates iceServers from the urls for Chrome M34 and above.
- * - .urls is supported since Chrome M34.
- * - Multiple Urls support
- *
- * [method] createIceServers
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
- if (webrtcDetectedBrowser.version >= 34) {
+ if (webrtcDetectedVersion >= 34) {
iceServers = {
'urls' : urls,
'credential' : password,
@@ -559,17 +741,8 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Creates an RTCPeerConection Object for webkit
- * - .urls is supported since Chrome M34.
- * [method] RTCPeerConnection
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
RTCPeerConnection = function (pcConfig, pcConstraints) {
- if (webrtcDetectedBrowser.version < 34) {
+ if (webrtcDetectedVersion < 34) {
maybeFixConfiguration(pcConfig);
}
return new webkitRTCPeerConnection(pcConfig, pcConstraints);
@@ -578,14 +751,6 @@ if (webrtcDetectedBrowser.mozWebRTC) {
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Attach Media Stream for webkit
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
if (typeof element.srcObject !== 'undefined') {
element.srcObject = stream;
@@ -599,60 +764,90 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return element;
};
- /**
- * Note:
- * Re-attach Media Stream for webkit
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
to.src = from.src;
return to;
};
- TemPrivateWebRTCReadyCb();
-} else if (webrtcDetectedBrowser.pluginWebRTC) {
- // var isOpera = webrtcDetectedBrowser.browser === 'Opera'; // Might not be used.
- var isFirefox = webrtcDetectedBrowser.browser === 'Firefox';
- var isSafari = webrtcDetectedBrowser.browser === 'Safari';
- var isChrome = webrtcDetectedBrowser.browser === 'Chrome';
- var isIE = webrtcDetectedBrowser.browser === 'IE';
-
- /********************************************************************************
- Load Plugin
- ********************************************************************************/
- TemRTCPlugin = document.createElement('object');
- TemRTCPlugin.id = temPluginInfo.pluginId;
- TemRTCPlugin.style.visibility = 'hidden';
- TemRTCPlugin.type = temPluginInfo.type;
- TemRTCPlugin.innerHTML = '' +
- '' +
- '';
- document.getElementsByTagName('body')[0].appendChild(TemRTCPlugin);
- TemRTCPlugin.onreadystatechange = function (state) {
- console.log('Plugin: Ready State : ' + state);
- if (state === 4) {
- console.log('Plugin has been loaded');
+} else { // TRY TO USE PLUGIN
+ // IE 9 is not offering an implementation of console.log until you open a console
+ if (typeof console !== 'object' || typeof console.log !== 'function') {
+ var console = console || {};
+ console.log = function (arg) {
+ // You may override this function
+ };
+ }
+ webrtcDetectedType = 'plugin';
+ webrtcDetectedDCSupport = 'plugin';
+ parseWebrtcDetectedBrowser();
+ isIE = webrtcDetectedBrowser === 'IE';
+
+ Temasys.WebRTCPlugin.WaitForPluginReady = function() {
+ while (!Temasys.WebRTCPlugin.isPluginReady) {
+ /* empty because it needs to prevent the function from running. */
+ }
+ };
+
+ Temasys.WebRTCPlugin.callWhenPluginReady = function (callback) {
+ var checkPluginReadyState = setInterval(function () {
+ if (Temasys.WebRTCPlugin.isPluginReady) {
+ clearInterval(checkPluginReadyState);
+ callback();
+ }
+ }, 100);
+ };
+
+ Temasys.WebRTCPlugin.injectPlugin = function () {
+ if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 9) {
+ var frag = document.createDocumentFragment();
+ Temasys.WebRTCPlugin.TemRTCPlugin = document.createElement('div');
+ Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML = '';
+ while (Temasys.WebRTCPlugin.TemRTCPlugin.firstChild) {
+ frag.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin.firstChild);
+ }
+ document.body.appendChild(frag);
+
+ // Need to re-fetch the plugin
+ Temasys.WebRTCPlugin.TemRTCPlugin =
+ document.getElementById(Temasys.WebRTCPlugin.temPluginInfo.pluginId);
+ } else {
+ // Load Plugin
+ Temasys.WebRTCPlugin.TemRTCPlugin = document.createElement('object');
+ Temasys.WebRTCPlugin.TemRTCPlugin.id =
+ Temasys.WebRTCPlugin.temPluginInfo.pluginId;
+ // IE will only start the plugin if it's ACTUALLY visible
+ if (isIE) {
+ Temasys.WebRTCPlugin.TemRTCPlugin.width = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.height = '1px';
+ }
+ Temasys.WebRTCPlugin.TemRTCPlugin.width = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.height = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.type = Temasys.WebRTCPlugin.temPluginInfo.type;
+ Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML = '' +
+ '' +
+ ' ' +
+ // uncomment to be able to use virtual cams
+ // '' +
+ '';
+ document.body.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin);
}
};
- /**
- * Note:
- * Checks if the Plugin is installed
- * - Check If Not IE (firefox, for example)
- * - Else If it's IE - we're running IE and do something
- * - Else Unsupported
- *
- * [method] isPluginInstalled
- * [param] {String} comName
- * [param] {String} plugName
- * [param] {Function} installedCb
- * [param] {Function} notInstalledCb
- */
- isPluginInstalled = function (comName, plugName, installedCb, notInstalledCb) {
- if (isChrome || isSafari || isFirefox) {
+
+ Temasys.WebRTCPlugin.isPluginInstalled =
+ function (comName, plugName, installedCb, notInstalledCb) {
+ if (!isIE) {
var pluginArray = navigator.plugins;
for (var i = 0; i < pluginArray.length; i++) {
if (pluginArray[i].name.indexOf(plugName) >= 0) {
@@ -661,7 +856,7 @@ if (webrtcDetectedBrowser.mozWebRTC) {
}
}
notInstalledCb();
- } else if (isIE) {
+ } else {
try {
var axo = new ActiveXObject(comName + '.' + plugName);
} catch (e) {
@@ -669,42 +864,14 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return;
}
installedCb();
- } else {
- return;
}
};
- /**
- * Note:
- * Define Plugin Browsers as WebRTC Interface
- *
- * [method] defineWebRTCInterface
- */
- defineWebRTCInterface = function () {
- /**
- * Note:
- * Check if WebRTC Interface is Defined
- * - This is a Util Function
- *
- * [method] isDefined
- * [param] {String} variable
- */
- isDefined = function (variable) {
+ Temasys.WebRTCPlugin.defineWebRTCInterface = function () {
+ Temasys.WebRTCPlugin.isDefined = function (variable) {
return variable !== null && variable !== undefined;
};
- /**
- * Note:
- * Creates Ice Server for Plugin Browsers
- * - If Stun - Create iceServer with stun url.
- * - Else - Create iceServer with turn url
- * - This is a WebRTC Function
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
@@ -724,17 +891,6 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServer;
};
- /**
- * Note:
- * Creates Ice Servers for Plugin Browsers
- * - Multiple Urls support
- * - This is a WebRTC Function
- *
- * [method] createIceServers
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
for (var i = 0; i < urls.length; ++i) {
@@ -743,29 +899,12 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Creates RTCSessionDescription object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCSessionDescription
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
RTCSessionDescription = function (info) {
- return TemRTCPlugin.ConstructSessionDescription(info.type, info.sdp);
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.
+ ConstructSessionDescription(info.type, info.sdp);
};
- /**
- * Note:
- * Creates RTCPeerConnection object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCSessionDescription
- * [param] {JSON} servers
- * [param] {JSON} contstraints
- */
RTCPeerConnection = function (servers, constraints) {
var iceServers = null;
if (servers) {
@@ -774,41 +913,41 @@ if (webrtcDetectedBrowser.mozWebRTC) {
if (iceServers[i].urls && !iceServers[i].url) {
iceServers[i].url = iceServers[i].urls;
}
- iceServers[i].hasCredentials = isDefined(iceServers[i].username) &&
- isDefined(iceServers[i].credential);
+ iceServers[i].hasCredentials = Temasys.WebRTCPlugin.
+ isDefined(iceServers[i].username) &&
+ Temasys.WebRTCPlugin.isDefined(iceServers[i].credential);
}
}
- var mandatory = (constraints && constraints.mandatory) ? constraints.mandatory : null;
- var optional = (constraints && constraints.optional) ? constraints.optional : null;
- return TemRTCPlugin.PeerConnection(TemPageId, iceServers, mandatory, optional);
+ var mandatory = (constraints && constraints.mandatory) ?
+ constraints.mandatory : null;
+ var optional = (constraints && constraints.optional) ?
+ constraints.optional : null;
+
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.
+ PeerConnection(Temasys.WebRTCPlugin.TemPageId,
+ iceServers, mandatory, optional);
};
MediaStreamTrack = {};
MediaStreamTrack.getSources = function (callback) {
- TemRTCPlugin.GetSources(callback);
+ Temasys.WebRTCPlugin.callWhenPluginReady(function() {
+ Temasys.WebRTCPlugin.TemRTCPlugin.GetSources(callback);
+ });
};
- /*******************************************************
- getUserMedia
- ********************************************************/
getUserMedia = function (constraints, successCallback, failureCallback) {
if (!constraints.audio) {
constraints.audio = false;
}
- TemRTCPlugin.getUserMedia(constraints, successCallback, failureCallback);
+
+ Temasys.WebRTCPlugin.callWhenPluginReady(function() {
+ Temasys.WebRTCPlugin.TemRTCPlugin.
+ getUserMedia(constraints, successCallback, failureCallback);
+ });
};
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Attach Media Stream for Plugin Browsers
- * - If Check is audio element
- * - Else The sound was enabled, there is nothing to do here
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
stream.enableSoundTracks(true);
if (element.nodeName.toLowerCase() !== 'audio') {
@@ -820,7 +959,8 @@ if (webrtcDetectedBrowser.mozWebRTC) {
temp.innerHTML = '';
while (temp.firstChild) {
@@ -843,66 +983,135 @@ if (webrtcDetectedBrowser.mozWebRTC) {
element.setStreamId(stream.id);
}
var newElement = document.getElementById(elementId);
- newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
- newElement._TemOnClick = function (id) {
- var arg = {
- srcElement : document.getElementById(id)
+ newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
+ if (isIE) { // on IE the event needs to be plugged manually
+ newElement.attachEvent('onplaying', newElement.onplaying);
+ newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
+ newElement._TemOnClick = function (id) {
+ var arg = {
+ srcElement : document.getElementById(id)
+ };
+ newElement.onclick(arg);
};
- newElement.onclick(arg);
- };
+ }
return newElement;
} else {
return element;
}
};
- /**
- * Note:
- * Re-attach Media Stream for Plugin Browsers
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
var stream = null;
var children = from.children;
for (var i = 0; i !== children.length; ++i) {
if (children[i].name === 'streamId') {
- stream = TemRTCPlugin.getStreamWithId(TemPageId, children[i].value);
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ stream = Temasys.WebRTCPlugin.TemRTCPlugin
+ .getStreamWithId(Temasys.WebRTCPlugin.TemPageId, children[i].value);
break;
}
}
if (stream !== null) {
return attachMediaStream(to, stream);
} else {
- alert('Could not find the stream associated with this element');
+ console.log('Could not find the stream associated with this element');
}
};
- /**
- * Note:
- * Creates RTCIceCandidate object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCIceCandidate
- * [param] {JSON} candidate
- */
RTCIceCandidate = function (candidate) {
if (!candidate.sdpMid) {
candidate.sdpMid = '';
}
- return TemRTCPlugin.ConstructIceCandidate(
+
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.ConstructIceCandidate(
candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate
);
};
+
+ Temasys.WebRTCPlugin.injectPlugin();
};
- pluginNeededButNotInstalledCb = function () {
- alert('Your browser is not webrtc ready and Temasys plugin is not installed');
+ Temasys.WebRTCPlugin.getWebsiteLink = function() {
+ return 'http://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins';
+ };
+
+ Temasys.WebRTCPlugin.getDownloadLink = function() {
+ if(!!navigator.platform.match(/^Mac/i)) {
+ return 'http://bit.ly/1n77hco';
+ }
+ else if(!!navigator.platform.match(/^Win/i)) {
+ return 'http://bit.ly/1kkS4FN';
+ }
+ return null;
+ };
+
+ Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb = function () {
+ var downloadLink = Temasys.WebRTCPlugin.getDownloadLink();
+ if(downloadLink) {
+ Temasys.WebRTCPlugin.renderNotificationBar('This website needs to install the Temasys WebRTC Plugin' +
+ ' to upgrade your browser.', 'Install Now', downloadLink);
+ }
+ else {
+ Temasys.WebRTCPlugin.renderNotificationBar('Your browser does not support WebRTC.');
+ }
+ };
+
+ Temasys.WebRTCPlugin.renderNotificationBar = function (text, buttonText, buttonLink) {
+ var w = window;
+ var i = document.createElement('iframe');
+ i.style.position = 'fixed';
+ i.style.top = '-41px';
+ i.style.left = 0;
+ i.style.right = 0;
+ i.style.width = '100%';
+ i.style.height = '40px';
+ i.style.backgroundColor = '#ffffe1';
+ i.style.border = 'none';
+ i.style.borderBottom = '1px solid #888888';
+ i.style.zIndex = '9999999';
+ if(typeof i.style.webkitTransition === 'string') {
+ i.style.webkitTransition = 'all .5s ease-out';
+ } else if(typeof i.style.transition === 'string') {
+ i.style.transition = 'all .5s ease-out';
+ }
+ document.body.appendChild(i);
+ c = (i.contentWindow) ? i.contentWindow :
+ (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument;
+ c.document.open();
+ c.document.write('' + text + '');
+ if(buttonText && buttonLink) {
+ c.document.write('');
+ c.document.close();
+ c.document.getElementById('okay').addEventListener('click', function(e) {
+ window.open(buttonLink, '_top');
+ e.preventDefault();
+ try {
+ event.cancelBubble = true;
+ } catch(error) { }
+ });
+ }
+ else {
+ c.document.close();
+ }
+ c.document.addEventListener('click', function() {
+ w.document.body.removeChild(i);
+ });
+ setTimeout(function() {
+ if(typeof i.style.webkitTransform === 'string') {
+ i.style.webkitTransform = 'translateY(40px)';
+ } else if(typeof i.style.transform === 'string') {
+ i.style.transform = 'translateY(40px)';
+ } else {
+ i.style.top = '0px';
+ }
+ }, 300);
};
// Try to detect the plugin and act accordingly
- isPluginInstalled('Tem', 'TemWebRTCPlugin', defineWebRTCInterface, pluginNeededButNotInstalledCb);
-} else {
- console.log('Browser does not appear to be WebRTC-capable');
+ Temasys.WebRTCPlugin.isPluginInstalled('Tem', 'TemWebRTCPlugin',
+ Temasys.WebRTCPlugin.defineWebRTCInterface,
+ Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb);
}
diff --git a/publish/adapter.min.js b/publish/adapter.min.js
index f53ad71..ccc88ca 100644
--- a/publish/adapter.min.js
+++ b/publish/adapter.min.js
@@ -1,2 +1,2 @@
-/*! adapterjs - v0.0.2 - 2014-07-10 */
-if(RTCPeerConnection=null,getUserMedia=null,attachMediaStream=null,reattachMediaStream=null,isPluginInstalled=null,defineWebRTCInterface=null,pluginNeededButNotInstalledCb=null,webrtcDetectedBrowser={},ICEConnectionState={starting:"starting",checking:"checking",connected:"connected",completed:"connected",done:"completed",disconnected:"disconnected",failed:"failed",closed:"closed"},ICEConnectionFiredStates={},RTCDataChannels={},temPluginInfo={pluginId:"plugin0",type:"application/x-temwebrtcplugin",onload:"TemInitPlugin0"},TemPageId=Math.random().toString(36).slice(2),getBrowserVersion=function(){var tem,agent={},na=navigator,ua=na.userAgent,M=ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i)||[];if(na.mozGetUserMedia?agent.mozWebRTC=!0:na.webkitGetUserMedia?agent.webkitWebRTC=!0:ua.indexOf("Safari")&&("undefined"!=typeof InstallTrigger?agent.browser="Firefox":document.documentMode?agent.browser="IE":Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0?agent.browser="Safari":window.opera||na.userAgent.indexOf(" OPR/")>=0?agent.browser="Opera":window.chrome&&(agent.browser="Chrome"),agent.pluginWebRTC=!0),/trident/i.test(M[1])?(tem=/\brv[ :]+(\d+)/g.exec(ua)||[],agent.browser="IE",agent.version=parseInt(tem[1]||"0",10)):"Chrome"===M[1]&&(tem=ua.match(/\bOPR\/(\d+)/),null!==tem&&(agent.browser="Opera",agent.version=parseInt(tem[1],10))),agent.browser||(agent.browser=M[1]),!agent.version)try{M=M[2]?[M[1],M[2]]:[navigator.appName,navigator.appVersion,"-?"],null!==(tem=ua.match(/version\/(\d+)/i))&&M.splice(1,1,tem[1]),agent.version=parseInt(M[1],10)}catch(err){agent.version=0}return agent.os=navigator.platform,agent.isSCTPDCSupported=agent.mozWebRTC||"Chrome"===agent.browser&&agent.version>30||"Opera"===agent.browser&&agent.version>19,agent.isRTPDCSupported="Chrome"===agent.browser&&agent.version<30&&agent.version>24,agent.isPluginSupported=!agent.isSCTPDCSupported&&!agent.isRTPDCSupported,agent},webrtcDetectedBrowser=getBrowserVersion(),TemRTCPlugin=null,TemPrivateWebRTCReadyCb=function(){arguments.callee.StaticWasInit=arguments.callee.StaticWasInit||1,1===arguments.callee.StaticWasInit&&"function"==typeof WebRTCReadyCb&&WebRTCReadyCb(),arguments.callee.StaticWasInit++},TemInitPlugin0=function(){TemRTCPlugin.setPluginId(TemPageId,temPluginInfo.pluginId),TemRTCPlugin.setLogFunction(console),TemPrivateWebRTCReadyCb()},maybeFixConfiguration=function(pcConfig){if(null!==pcConfig)for(var i=0;i-1&&(peerBrowser=peerBrowserAgent.split("|"),peerBrowserAgent=peerBrowser[0],peerBrowserVersion=parseInt(peerBrowser[1],10));var isLocalFirefox=webrtcDetectedBrowser.mozWebRTC,isLocalFirefoxInterop=webrtcDetectedBrowser.mozWebRTC&&webrtcDetectedBrowser.version>30,isPeerFirefox="Firefox"===peerBrowserAgent,isPeerFirefoxInterop="Firefox"===peerBrowserAgent&&(peerBrowserVersion?peerBrowserVersion>30:!1);if(isOffer){if(isLocalFirefox&&isPeerFirefox||isLocalFirefoxInterop)try{delete constraints.mandatory.MozDontOfferDataChannel}catch(err){}else isLocalFirefox&&!isPeerFirefox&&(constraints.mandatory.MozDontOfferDataChannel=!0);if(!isLocalFirefox)for(var prop in constraints.mandatory)constraints.mandatory.hasOwnProperty(prop)&&-1!==prop.indexOf("Moz")&&delete constraints.mandatory[prop];callback(constraints)}else isLocalFirefox||!isPeerFirefox||isPeerFirefoxInterop||(beOfferer=!0),callback(beOfferer)}},webrtcDetectedBrowser.mozWebRTC)RTCPeerConnection=function(pcConfig,pcConstraints){return maybeFixConfiguration(pcConfig),new mozRTCPeerConnection(pcConfig,pcConstraints)},RTCSessionDescription=mozRTCSessionDescription,RTCIceCandidate=mozRTCIceCandidate,getUserMedia=navigator.mozGetUserMedia.bind(navigator),navigator.getUserMedia=getUserMedia,createIceServer=function(url,username,password){var iceServer=null,url_parts=url.split(":");if(0===url_parts[0].indexOf("stun"))iceServer={url:url};else if(0===url_parts[0].indexOf("turn"))if(webrtcDetectedBrowser.version<27){var turn_url_parts=url.split("?");(1===turn_url_parts.length||0===turn_url_parts[1].indexOf("transport=udp"))&&(iceServer={url:turn_url_parts[0],credential:password,username:username})}else iceServer={url:url,credential:password,username:username};return iceServer},createIceServers=function(urls,username,password){var iceServers=[];for(i=0;i=34)iceServers={urls:urls,credential:password,username:username};else for(i=0;i',document.getElementsByTagName("body")[0].appendChild(TemRTCPlugin),TemRTCPlugin.onreadystatechange=function(state){},isPluginInstalled=function(comName,plugName,installedCb,notInstalledCb){if(isChrome||isSafari||isFirefox){for(var pluginArray=navigator.plugins,i=0;i=0)return void installedCb();notInstalledCb()}else{if(!isIE)return;try{{new ActiveXObject(comName+"."+plugName)}}catch(e){return void notInstalledCb()}installedCb()}},defineWebRTCInterface=function(){isDefined=function(variable){return null!==variable&&void 0!==variable},createIceServer=function(url,username,password){var iceServer=null,url_parts=url.split(":");return 0===url_parts[0].indexOf("stun")?iceServer={url:url,hasCredentials:!1}:0===url_parts[0].indexOf("turn")&&(iceServer={url:url,hasCredentials:!0,credential:password,username:username}),iceServer},createIceServers=function(urls,username,password){for(var iceServers=[],i=0;i ';temp.firstChild;)frag.appendChild(temp.firstChild);var rectObject=element.getBoundingClientRect();element.parentNode.insertBefore(frag,element),frag=document.getElementById(elementId),frag.width=rectObject.width+"px",frag.height=rectObject.height+"px",element.parentNode.removeChild(element)}var newElement=document.getElementById(elementId);return newElement.onclick=element.onclick?element.onclick:function(){},newElement._TemOnClick=function(id){var arg={srcElement:document.getElementById(id)};newElement.onclick(arg)},newElement}return element},reattachMediaStream=function(to,from){for(var stream=null,children=from.children,i=0;i!==children.length;++i)if("streamId"===children[i].name){stream=TemRTCPlugin.getStreamWithId(TemPageId,children[i].value);break}return null!==stream?attachMediaStream(to,stream):void alert("Could not find the stream associated with this element")},RTCIceCandidate=function(candidate){return candidate.sdpMid||(candidate.sdpMid=""),TemRTCPlugin.ConstructIceCandidate(candidate.sdpMid,candidate.sdpMLineIndex,candidate.candidate)}},pluginNeededButNotInstalledCb=function(){alert("Your browser is not webrtc ready and Temasys plugin is not installed")},isPluginInstalled("Tem","TemWebRTCPlugin",defineWebRTCInterface,pluginNeededButNotInstalledCb)}
\ No newline at end of file
+/*! adapterjs - v0.9.0 - 2014-09-09 */
+var Temasys=Temasys||{};if(Temasys.WebRTCPlugin=Temasys.WebRTCPlugin||{},Temasys.AdapterJS={VERSION:"0.9.0"},Temasys.WebRTCPlugin.isPluginInstalled=null,Temasys.WebRTCPlugin.isDefined=null,Temasys.WebRTCPlugin.injectPlugin=null,Temasys.WebRTCPlugin.WaitForPluginReady=null,Temasys.WebRTCPlugin.callWhenPluginReady=null,Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb=null,Temasys.WebRTCPlugin.temPluginInfo={pluginId:"plugin0",type:"application/x-temwebrtcplugin",onload:"__TemWebRTCReady0"},Temasys.WebRTCPlugin.TemPageId=Math.random().toString(36).slice(2),Temasys.WebRTCPlugin.TemRTCPlugin=null,Temasys.WebRTCPlugin.isPluginReady=!1,Temasys.WebRTCPlugin.defineWebRTCInterface=null,__TemWebRTCReady0=function(){arguments.callee.StaticWasInit=arguments.callee.StaticWasInit||1,1===arguments.callee.StaticWasInit&&(Temasys.WebRTCPlugin.documentReadyInterval=setInterval(function(){"complete"===document.readyState&&(clearInterval(Temasys.WebRTCPlugin.documentReadyInterval),Temasys.WebRTCPlugin.isPluginReady=!0,Temasys.WebRTCPlugin.pluginReadyState=Temasys.WebRTCPlugin.pluginReadyStates.ready)},100)),arguments.callee.StaticWasInit++},Temasys.WebRTCPlugin.pluginReadyStates={init:0,ready:1},Temasys.WebRTCPlugin.pluginReadyState=Temasys.WebRTCPlugin.pluginReadyStates.init,Temasys._iceConnectionStates={starting:"starting",checking:"checking",connected:"connected",completed:"connected",done:"completed",disconnected:"disconnected",failed:"failed",closed:"closed"},Temasys._iceConnectionFiredStates=[],parseWebrtcDetectedBrowser=function(){var hasMatch,checkMatch=navigator.userAgent.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i)||[];if(/trident/i.test(checkMatch[1])?(hasMatch=/\brv[ :]+(\d+)/g.exec(navigator.userAgent)||[],webrtcDetectedBrowser="IE",webrtcDetectedVersion=parseInt(hasMatch[1]||"0",10)):"Chrome"===checkMatch[1]&&(hasMatch=navigator.userAgent.match(/\bOPR\/(\d+)/),null!==hasMatch&&(webrtcDetectedBrowser="opera",webrtcDetectedVersion=parseInt(hasMatch[1],10))),navigator.userAgent.indexOf("Safari")&&("undefined"!=typeof InstallTrigger?webrtcDetectedBrowser="firefox":document.documentMode?webrtcDetectedBrowser="IE":Object.prototype.toString.call(window.HTMLElement).indexOf("Constructor")>0?webrtcDetectedBrowser="safari":window.opera||navigator.userAgent.indexOf(" OPR/")>=0?webrtcDetectedBrowser="opera":window.chrome&&(webrtcDetectedBrowser="chrome")),webrtcDetectedBrowser||(webrtcDetectedVersion=checkMatch[1]),!webrtcDetectedVersion)try{checkMatch=checkMatch[2]?[checkMatch[1],checkMatch[2]]:[navigator.appName,navigator.appVersion,"-?"],null!==(hasMatch=navigator.userAgent.match(/version\/(\d+)/i))&&checkMatch.splice(1,1,hasMatch[1]),webrtcDetectedVersion=parseInt(checkMatch[1],10)}catch(error){}},webrtcDetectedType=null,webrtcDetectedDCSupport=null,maybeFixConfiguration=function(pcConfig){if(null!==pcConfig)for(var i=0;i30,isPeerFirefox="firefox"===peerBrowserAgent,isPeerFirefoxInterop="firefox"===peerBrowserAgent&&(peerBrowserVersion?peerBrowserVersion>30:!1);if(isLocalFirefox&&isPeerFirefox||isLocalFirefoxInterop)try{delete constraints.mandatory.MozDontOfferDataChannel}catch(error){console.error("Failed deleting MozDontOfferDataChannel"),console.error(error)}else isLocalFirefox&&!isPeerFirefox&&(constraints.mandatory.MozDontOfferDataChannel=!0);if(!isLocalFirefox)for(var prop in constraints.mandatory)constraints.mandatory.hasOwnProperty(prop)&&-1!==prop.indexOf("Moz")&&delete constraints.mandatory[prop];!isLocalFirefox||isPeerFirefox||isPeerFirefoxInterop||(beOfferer=!1),callback(beOfferer,constraints)}},checkIceConnectionState=function(peerId,iceConnectionState,callback){return"function"!=typeof callback?void console.warn("No callback specified in checkIceConnectionState. Aborted."):(peerId=peerId?peerId:"peer",Temasys._iceConnectionStates[peerId]&&iceConnectionState!==Temasys._iceConnectionStates.disconnected&&iceConnectionState!==Temasys._iceConnectionStates.failed&&iceConnectionState!==Temasys._iceConnectionStates.closed||(Temasys._iceConnectionStates[peerId]=[]),iceConnectionState=Temasys._iceConnectionStates[iceConnectionState],void(Temasys._iceConnectionStates[peerId].indexOf(iceConnectionState)<0&&(Temasys._iceConnectionStates[peerId].push(iceConnectionState),iceConnectionState===Temasys._iceConnectionStates.connected&&setTimeout(function(){Temasys._iceConnectionStates[peerId].push(Temasys._iceConnectionStates.done),callback(Temasys._iceConnectionStates.done)},1e3),callback(iceConnectionState))))},checkMediaDataChannel=function(stream,constraints){var testedOptions={audio:!1,video:!1,data:!1};constraints.audio&&stream.getAudioTracks().length>0&&(testedOptions.audio=!0),constraints.video&&stream.getVideoTracks().length>0&&(testedOptions.video=!0);var testPeer=new RTCPeerConnection;try{var dc=testPeer.createDataChannel("_");dc&&(testedOptions.data=!0)}catch(error){console.error("Failed creating DataChannel"),console.error(error)}return testedOptions},RTCPeerConnection=null,RTCSessionDescription="function"==typeof RTCSessionDescription?RTCSessionDescription:null,RTCIceCandidate="function"==typeof RTCIceCandidate?RTCIceCandidate:null,getUserMedia=null,attachMediaStream=null,reattachMediaStream=null,createIceServer=null,createIceServers=null,createIceServers=null,webrtcDetectedBrowser=null,webrtcDetectedVersion=null,navigator.mozGetUserMedia)webrtcDetectedBrowser="firefox",webrtcDetectedVersion=parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1],10),webrtcDetectedType="moz",webrtcDetectedDCSupport="SCTP",RTCPeerConnection=function(pcConfig,pcConstraints){return maybeFixConfiguration(pcConfig),new mozRTCPeerConnection(pcConfig,pcConstraints)},RTCSessionDescription=mozRTCSessionDescription,RTCIceCandidate=mozRTCIceCandidate,getUserMedia=navigator.mozGetUserMedia.bind(navigator),navigator.getUserMedia=getUserMedia,createIceServer=function(url,username,password){var iceServer=null,url_parts=url.split(":");if(0===url_parts[0].indexOf("stun"))iceServer={url:url};else if(0===url_parts[0].indexOf("turn"))if(27>webrtcDetectedVersion){var turn_url_parts=url.split("?");(1===turn_url_parts.length||0===turn_url_parts[1].indexOf("transport=udp"))&&(iceServer={url:turn_url_parts[0],credential:password,username:username})}else iceServer={url:url,credential:password,username:username};return iceServer},createIceServers=function(urls,username,password){var iceServers=[];for(i=0;i=31||"opera"===webrtcDetectedBrowser&&webrtcDetectedVersion>=20?"SCTP":"chrome"===webrtcDetectedBrowser&&30>webrtcDetectedVersion&&webrtcDetectedVersion>24?"RTP":"",createIceServer=function(url,username,password){var iceServer=null,url_parts=url.split(":");return 0===url_parts[0].indexOf("stun")?iceServer={url:url}:0===url_parts[0].indexOf("turn")&&(iceServer={url:url,credential:password,username:username}),iceServer},createIceServers=function(urls,username,password){var iceServers=[];if(webrtcDetectedVersion>=34)iceServers={urls:urls,credential:password,username:username};else for(i=0;iwebrtcDetectedVersion&&maybeFixConfiguration(pcConfig),new webkitRTCPeerConnection(pcConfig,pcConstraints)},getUserMedia=navigator.webkitGetUserMedia.bind(navigator),navigator.getUserMedia=getUserMedia,attachMediaStream=function(element,stream){return"undefined"!=typeof element.srcObject?element.srcObject=stream:"undefined"!=typeof element.mozSrcObject?element.mozSrcObject=stream:"undefined"!=typeof element.src?element.src=URL.createObjectURL(stream):console.log("Error attaching stream to element."),element},reattachMediaStream=function(to,from){return to.src=from.src,to}}else{if("object"!=typeof console||"function"!=typeof console.log){var console=console||{};console.log=function(){}}webrtcDetectedType="plugin",webrtcDetectedDCSupport="plugin",parseWebrtcDetectedBrowser(),isIE="IE"===webrtcDetectedBrowser,Temasys.WebRTCPlugin.WaitForPluginReady=function(){for(;!Temasys.WebRTCPlugin.isPluginReady;);},Temasys.WebRTCPlugin.callWhenPluginReady=function(callback){var checkPluginReadyState=setInterval(function(){Temasys.WebRTCPlugin.isPluginReady&&(clearInterval(checkPluginReadyState),callback())},100)},Temasys.WebRTCPlugin.injectPlugin=function(){if("IE"===webrtcDetectedBrowser&&9>=webrtcDetectedVersion){var frag=document.createDocumentFragment();for(Temasys.WebRTCPlugin.TemRTCPlugin=document.createElement("div"),Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML='';Temasys.WebRTCPlugin.TemRTCPlugin.firstChild;)frag.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin.firstChild);document.body.appendChild(frag),Temasys.WebRTCPlugin.TemRTCPlugin=document.getElementById(Temasys.WebRTCPlugin.temPluginInfo.pluginId)}else Temasys.WebRTCPlugin.TemRTCPlugin=document.createElement("object"),Temasys.WebRTCPlugin.TemRTCPlugin.id=Temasys.WebRTCPlugin.temPluginInfo.pluginId,isIE&&(Temasys.WebRTCPlugin.TemRTCPlugin.width="1px",Temasys.WebRTCPlugin.TemRTCPlugin.height="1px"),Temasys.WebRTCPlugin.TemRTCPlugin.width="1px",Temasys.WebRTCPlugin.TemRTCPlugin.height="1px",Temasys.WebRTCPlugin.TemRTCPlugin.type=Temasys.WebRTCPlugin.temPluginInfo.type,Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML=' ',document.body.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin)},Temasys.WebRTCPlugin.isPluginInstalled=function(comName,plugName,installedCb,notInstalledCb){if(isIE){try{{new ActiveXObject(comName+"."+plugName)}}catch(e){return void notInstalledCb()}installedCb()}else{for(var pluginArray=navigator.plugins,i=0;i=0)return void installedCb();notInstalledCb()}},Temasys.WebRTCPlugin.defineWebRTCInterface=function(){Temasys.WebRTCPlugin.isDefined=function(variable){return null!==variable&&void 0!==variable},createIceServer=function(url,username,password){var iceServer=null,url_parts=url.split(":");return 0===url_parts[0].indexOf("stun")?iceServer={url:url,hasCredentials:!1}:0===url_parts[0].indexOf("turn")&&(iceServer={url:url,hasCredentials:!0,credential:password,username:username}),iceServer},createIceServers=function(urls,username,password){for(var iceServers=[],i=0;i ';temp.firstChild;)frag.appendChild(temp.firstChild);var rectObject=element.getBoundingClientRect();element.parentNode.insertBefore(frag,element),frag=document.getElementById(elementId),frag.width=rectObject.width+"px",frag.height=rectObject.height+"px",element.parentNode.removeChild(element)}var newElement=document.getElementById(elementId);return newElement.onplaying=element.onplaying?element.onplaying:function(){},isIE&&(newElement.attachEvent("onplaying",newElement.onplaying),newElement.onclick=element.onclick?element.onclick:function(){},newElement._TemOnClick=function(id){var arg={srcElement:document.getElementById(id)};newElement.onclick(arg)}),newElement}return element},reattachMediaStream=function(to,from){for(var stream=null,children=from.children,i=0;i!==children.length;++i)if("streamId"===children[i].name){Temasys.WebRTCPlugin.WaitForPluginReady(),stream=Temasys.WebRTCPlugin.TemRTCPlugin.getStreamWithId(Temasys.WebRTCPlugin.TemPageId,children[i].value);break}return null!==stream?attachMediaStream(to,stream):void console.log("Could not find the stream associated with this element")},RTCIceCandidate=function(candidate){return candidate.sdpMid||(candidate.sdpMid=""),Temasys.WebRTCPlugin.WaitForPluginReady(),Temasys.WebRTCPlugin.TemRTCPlugin.ConstructIceCandidate(candidate.sdpMid,candidate.sdpMLineIndex,candidate.candidate)},Temasys.WebRTCPlugin.injectPlugin()},Temasys.WebRTCPlugin.getWebsiteLink=function(){return"http://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins"},Temasys.WebRTCPlugin.getDownloadLink=function(){return navigator.platform.match(/^Mac/i)?"http://bit.ly/1n77hco":navigator.platform.match(/^Win/i)?"http://bit.ly/1kkS4FN":null},Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb=function(){var downloadLink=Temasys.WebRTCPlugin.getDownloadLink();downloadLink?Temasys.WebRTCPlugin.renderNotificationBar('This website needs to install the Temasys WebRTC Plugin to upgrade your browser.',"Install Now",downloadLink):Temasys.WebRTCPlugin.renderNotificationBar("Your browser does not support WebRTC.")},Temasys.WebRTCPlugin.renderNotificationBar=function(text,buttonText,buttonLink){var w=window,i=document.createElement("iframe");i.style.position="fixed",i.style.top="-41px",i.style.left=0,i.style.right=0,i.style.width="100%",i.style.height="40px",i.style.backgroundColor="#ffffe1",i.style.border="none",i.style.borderBottom="1px solid #888888",i.style.zIndex="9999999","string"==typeof i.style.webkitTransition?i.style.webkitTransition="all .5s ease-out":"string"==typeof i.style.transition&&(i.style.transition="all .5s ease-out"),document.body.appendChild(i),c=i.contentWindow?i.contentWindow:i.contentDocument.document?i.contentDocument.document:i.contentDocument,c.document.open(),c.document.write(''+text+""),buttonText&&buttonLink?(c.document.write('"),c.document.close(),c.document.getElementById("okay").addEventListener("click",function(e){window.open(buttonLink,"_top"),e.preventDefault();try{event.cancelBubble=!0}catch(error){}})):c.document.close(),c.document.addEventListener("click",function(){w.document.body.removeChild(i)}),setTimeout(function(){"string"==typeof i.style.webkitTransform?i.style.webkitTransform="translateY(40px)":"string"==typeof i.style.transform?i.style.transform="translateY(40px)":i.style.top="0px"},300)},Temasys.WebRTCPlugin.isPluginInstalled("Tem","TemWebRTCPlugin",Temasys.WebRTCPlugin.defineWebRTCInterface,Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb)}
\ No newline at end of file
diff --git a/server.js b/server.js
new file mode 100644
index 0000000..98e429c
--- /dev/null
+++ b/server.js
@@ -0,0 +1,4 @@
+/* Copyright Temasys Communications, 2014 */
+var connect = require('connect');
+connect.createServer(connect.static(__dirname)).listen(8021);
+console.log("Server start @ 8021");
\ No newline at end of file
diff --git a/source/adapter.js b/source/adapter.js
index 876bbb8..137e5ca 100644
--- a/source/adapter.js
+++ b/source/adapter.js
@@ -1,77 +1,191 @@
/**
- * Note:
- * The RTCPeerConnection object.
- * [attribute] RTCPeerConnection
- * [type] Function
+ * Temasys reserved namespace.
+ * - This are where all Temasys implemented functions are.
+ * - Interface are called "classes" because yuidoc does not support interfaces.
+ * - Functions and variables are not encapsulated except Temasys private
+ * functions and variables.
+ * @class Temasys
*/
-RTCPeerConnection = null;
+var Temasys = Temasys || {};
/**
- * Note:
- * Get UserMedia (only difference is the prefix).
- * [Credits] Code from Adam Barth.
- *
- * [attribute] RTCIceCandidate
- * [type] Function
+ * Temasys plugin interface.
+ * - WARNING: You may be required to [download our plugin](https:
+ * /temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins) if you are using
+ * Internet Explorer, Safari or older supported browsers (Chrome, Opera, Firefox).
+ * @class Temasys.WebRTCPlugin
+ * @for Temasys
*/
-getUserMedia = null;
+Temasys.WebRTCPlugin = Temasys.WebRTCPlugin || {};
/**
- * Note:
- * Attach a media stream to an element.
- *
- * [attribute] attachMediaStream
- * [type] Function
+ * Adapter's interface.
+ * @class Temasys.AdapterJS
+ * @extends Temasys
*/
-attachMediaStream = null;
+Temasys.AdapterJS = {
+ VERSION: '@@version'
+};
/**
- * Note:
- * Re-attach a media stream to an element.
- *
- * [attribute] reattachMediaStream
- * [type] Function
+ * This function detects whether or not a plugin is installed.
+ * Checks if Not IE (firefox, for example), else if it's IE,
+ * we're running IE and do something. If not it is not supported.
+ * @method isPluginInstalled
+ * @param {String} comName The company name.
+ * @param {String} plugName The plugin name.
+ * @param {Function} installedCb The callback fired if the plugin is detected
+ * @param {Function} notInstalledCb The callback fired
+ * if the plugin is not detected (no argument).
+ * @return {Boolean} Is plugin installed.
+ * @for Temasys.WebRTCPlugin
*/
-reattachMediaStream = null;
+Temasys.WebRTCPlugin.isPluginInstalled = null;
/**
- * Note:
- * This function detects whether or not a plugin is installed
- * - Com name : the company name,
- * - plugName : the plugin name
- * - installedCb : callback if the plugin is detected (no argument)
- * - notInstalledCb : callback if the plugin is not detected (no argument)
- * @method isPluginInstalled
- * @protected
+ * Check if WebRTC Interface is defined.
+ * @method isDefined
+ * @param {String} variable The variable to check.
+ * @return {Boolean} If variable is defined.
+ * @private
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.isDefined = null;
+/**
+ * Inject the HTML DOM object element into the page.
+ * @method injectPlugin
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.injectPlugin = null;
+/**
+ * Does a waiting check before proceeding to load the plugin.
+ * @method WaitForPluginReady
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.WaitForPluginReady = null;
+/**
+ * This methid will use an interval to wait for the plugin to be ready.
+ * @for Temasys.WebRTCPlugin
+*/
+Temasys.WebRTCPlugin.callWhenPluginReady = null;
+/**
+ * This function will be called if the plugin is needed (browser different
+ * from Chrome or Firefox), but the plugin is not installed.
+ * Override it according to your application logic.
+ * @method pluginNeededButNotInstalledCb
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb = null;
+/**
+ * The object to store plugin information
+ * @attribute temPluginInfo
+ * @type JSON
+ * @readOnly
+ * @required
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.temPluginInfo = {
+ pluginId : 'plugin0',
+ type : 'application/x-temwebrtcplugin',
+ onload : '__TemWebRTCReady0'
+};
+/**
+ * Unique identifier of each opened page
+ * @attribute TemPageId
+ * @type String
+ * @readOnly
+ * @required
+ * @for Temasys.WebRTCPlugin
+ */
+Temasys.WebRTCPlugin.TemPageId = Math.random().toString(36).slice(2);
+/**
+ * Use this whenever you want to call the plugin.
+ * @attribute TemRTCPlugin
+ * @type <>Object
+ * @readOnly
+ * @for Temasys.WebRTCPlugin
*/
-isPluginInstalled = null;
+Temasys.WebRTCPlugin.TemRTCPlugin = null;
/**
- * Note:
- * defines webrtc's JS interface according to the plugin's implementation
- * [attribute] defineWebRTCInterface
- * [type] Function
+ * Plugin ready status.
+ * @attribute isPluginReady
+ * @type Boolean
+ * @for Temasys.WebRTCPlugin
*/
-defineWebRTCInterface = null;
+Temasys.WebRTCPlugin.isPluginReady = false;
+/**
+ * Defines webrtc's JS interface according to the plugin's implementation.
+ * - Define plugin Browsers as WebRTC Interface.
+ * @method defineWebRTCInterface
+ * @for Temasys.WebRTCPlugin
+ * @private
+ */
+Temasys.WebRTCPlugin.defineWebRTCInterface = null;
+/**
+ * This function will be called when plugin is ready. It sends necessary
+ * details to the plugin.
+ * - WARNING: DO NOT OVERRIDE THIS FUNCTION.
+ * - If you need to do something once the page/plugin is ready, override
+ * window.onwebrtcready instead.
+ * - This function is not in the IE/Safari condition brackets so that
+ * TemPluginLoaded function might be called on Chrome/Firefox.
+ * - This function is the only private function that is not encapsulated to
+ * allow the plugin method to be called.
+ * @method __TemWebRTCReady0
+ * @for Temasys
+ * @private
+ */
+__TemWebRTCReady0 = function () {
+ arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
+ if (arguments.callee.StaticWasInit === 1) {
+ Temasys.WebRTCPlugin.documentReadyInterval = setInterval(function () {
+ if (document.readyState === 'complete') {
+ // TODO: update comments, we wait for the document to be ready
+ clearInterval(Temasys.WebRTCPlugin.documentReadyInterval);
+ Temasys.WebRTCPlugin.isPluginReady = true;
+ Temasys.WebRTCPlugin.pluginReadyState =
+ Temasys.WebRTCPlugin.pluginReadyStates.ready;
+ }
+ }, 100);
+ }
+ arguments.callee.StaticWasInit++;
+};
/**
- * Note:
- * This function will be called if the plugin is needed
- * (browser different from Chrome or Firefox),
- * but the plugin is not installed
- * Override it according to your application logic.
- * [attribute] pluginNeededButNotInstalledCb
- * [type] Function
+ * The results of each states returns.
+ * @attribute pluginReadyStates
+ * @type JSON
+ * @param {Integer} init Plugin is loading.
+ * @param {Integer} ready Plugin has been loaded and is ready to use.
+ * @readOnly
+ * @for Temasys.WebRTCPlugin
*/
-pluginNeededButNotInstalledCb = null;
+Temasys.WebRTCPlugin.pluginReadyStates = {
+ init : 0,
+ ready : 1
+};
/**
- * Note:
- * The Object used in SkywayJS to check the WebRTC Detected type
- * [attribute] WebRTCDetectedBrowser
- * [type] JSON
+ * State of Plugin ready
+ * @attribute pluginReadyState
+ * @type String
+ * @readyOnly
+ * @for Temasys.WebRTCPlugin
*/
-webrtcDetectedBrowser = {};
+Temasys.WebRTCPlugin.pluginReadyState = Temasys.WebRTCPlugin.pluginReadyStates.init;
/**
- * Note:
- * The results of each states returns
- * @attribute ICEConnectionState
+ * The result of ice connection states.
+ * @attribute _iceConnectionStates
* @type JSON
+ * @param {String} starting: Ice connection is starting.
+ * @param {String} checking: Ice connection is checking.
+ * @param {String} connected Ice connection is connected.
+ * @param {String} completed Ice connection is connected.
+ * @param {String} done Ice connection has been completed.
+ * @param {String} disconnected Ice connection has been disconnected.
+ * @param {String} failed Ice connection has failed.
+ * @param {String} closed Ice connection is closed.
+ * @for Temasys
+ * @private
*/
-ICEConnectionState = {
+Temasys._iceConnectionStates = {
starting : 'starting',
checking : 'checking',
connected : 'connected',
@@ -82,178 +196,94 @@ ICEConnectionState = {
closed : 'closed'
};
/**
- * Note:
- * The states of each Peer
- * @attribute ICEConnectionFiredStates
- * @type JSON
+ * The IceConnection states that has been fired for each peer.
+ * @attribute _iceConnectionFiredStates
+ * @type Array
+ * @for Temasys
+ * @private
*/
-ICEConnectionFiredStates = {};
+Temasys._iceConnectionFiredStates = [];
/**
- * Note:
- * The Object to store the list of DataChannels
- * [attribute] RTCDataChannels
- * [type] JSON
+ * This function helps to retrieve the webrtc detected browser information.
+ * This sets:
+ * - webrtcDetectedBrowser: The browser agent name.
+ * - webrtcDetectedVersion: The browser version.
+ * - webrtcDetectedType: The types of webRTC support.
+ * - 'moz': Mozilla implementation of webRTC.
+ * - 'webkit': WebKit implementation of webRTC.
+ * - 'plugin': Using Temasys's plugin implementation.
+ * @method parseWebrtcDetectedBrowser
+ * @for Temasys
*/
-RTCDataChannels = {};
-/**
- * Note:
- * The Object to store Plugin information
- * [attribute] temPluginInfo
- * [type] JSON
- */
-temPluginInfo = {
- pluginId : 'plugin0',
- type : 'application/x-temwebrtcplugin',
- onload : 'TemInitPlugin0'
-};
-/**
- * Note:
- * Unique identifier of each opened page
- * [attribute] TemPageId
- * [type] String
- */
-TemPageId = Math.random().toString(36).slice(2);
-/**
- * Note:
- * - Latest Opera supports Webkit WebRTC
- * - IE is detected as Safari
- * - Older Firefox and Chrome does not support WebRTC
- * - Detected "Safari" Browsers:
- * - Firefox 1.0+
- * - IE 6+
- * - Safari 3+: '[object HTMLElementConstructor]'
- * - Opera 8.0+ (UA detection to detect Blink/v8-powered Opera)
- * - Chrome 1+
- * 1st Step: Get browser OS
- * 2nd Step: Check browser DataChannels Support
- * 3rd Step: Check browser WebRTC Support type
- * 4th Step: Get browser version
- * @author Get version of Browser. Code provided by kennebec@stackoverflow.com
- * @author IsSCTP/isRTPD Supported. Code provided by DetectRTC by Muaz Khan
- *
- * @method getBrowserVersion
- * @protected
- */
-getBrowserVersion = function () {
- var agent = {},
- na = navigator,
- ua = na.userAgent,
- tem;
- var M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
-
- if (na.mozGetUserMedia) {
- agent.mozWebRTC = true;
- } else if (na.webkitGetUserMedia) {
- agent.webkitWebRTC = true;
- } else {
- if (ua.indexOf('Safari')) {
- if (typeof InstallTrigger !== 'undefined') {
- agent.browser = 'Firefox';
- } else if (/*@cc_on!@*/
- false || !!document.documentMode) {
- agent.browser = 'IE';
- } else if (
- Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
- agent.browser = 'Safari';
- } else if (!!window.opera || na.userAgent.indexOf(' OPR/') >= 0) {
- agent.browser = 'Opera';
- } else if (!!window.chrome) {
- agent.browser = 'Chrome';
- }
- agent.pluginWebRTC = true;
+parseWebrtcDetectedBrowser = function () {
+ var hasMatch, checkMatch = navigator.userAgent.match(
+ /(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
+ if (/trident/i.test(checkMatch[1])) {
+ hasMatch = /\brv[ :]+(\d+)/g.exec(navigator.userAgent) || [];
+ webrtcDetectedBrowser = 'IE';
+ webrtcDetectedVersion = parseInt(hasMatch[1] || '0', 10);
+ } else if (checkMatch[1] === 'Chrome') {
+ hasMatch = navigator.userAgent.match(/\bOPR\/(\d+)/);
+ if (hasMatch !== null) {
+ webrtcDetectedBrowser = 'opera';
+ webrtcDetectedVersion = parseInt(hasMatch[1], 10);
}
}
- if (/trident/i.test(M[1])) {
- tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
- agent.browser = 'IE';
- agent.version = parseInt(tem[1] || '0', 10);
- } else if (M[1] === 'Chrome') {
- tem = ua.match(/\bOPR\/(\d+)/);
- if (tem !== null) {
- agent.browser = 'Opera';
- agent.version = parseInt(tem[1], 10);
+ if (navigator.userAgent.indexOf('Safari')) {
+ if (typeof InstallTrigger !== 'undefined') {
+ webrtcDetectedBrowser = 'firefox';
+ } else if (/*@cc_on!@*/ false || !!document.documentMode) {
+ webrtcDetectedBrowser = 'IE';
+ } else if (
+ Object.prototype.toString.call(window.HTMLElement).indexOf('Constructor') > 0) {
+ webrtcDetectedBrowser = 'safari';
+ } else if (!!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0) {
+ webrtcDetectedBrowser = 'opera';
+ } else if (!!window.chrome) {
+ webrtcDetectedBrowser = 'chrome';
}
}
- if (!agent.browser) {
- agent.browser = M[1];
+ if (!webrtcDetectedBrowser) {
+ webrtcDetectedVersion = checkMatch[1];
}
- if (!agent.version) {
+ if (!webrtcDetectedVersion) {
try {
- M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
- if ((tem = ua.match(/version\/(\d+)/i)) !== null) {
- M.splice(1, 1, tem[1]);
+ checkMatch = (checkMatch[2]) ? [checkMatch[1], checkMatch[2]] :
+ [navigator.appName, navigator.appVersion, '-?'];
+ if ((hasMatch = navigator.userAgent.match(/version\/(\d+)/i)) !== null) {
+ checkMatch.splice(1, 1, hasMatch[1]);
}
- agent.version = parseInt(M[1], 10);
- } catch (err) {
- agent.version = 0;
- }
+ webrtcDetectedVersion = parseInt(checkMatch[1], 10);
+ } catch (error) { }
}
- agent.os = navigator.platform;
- agent.isSCTPDCSupported = agent.mozWebRTC ||
- (agent.browser === 'Chrome' && agent.version > 30) ||
- (agent.browser === 'Opera' && agent.version > 19);
- agent.isRTPDCSupported = agent.browser === 'Chrome' && agent.version < 30 && agent.version > 24;
- agent.isPluginSupported = !agent.isSCTPDCSupported && !agent.isRTPDCSupported;
- return agent;
-};
-webrtcDetectedBrowser = getBrowserVersion();
-/**
- * Note:
- * use this whenever you want to call the plugin
- * [attribute] plugin
- * [type DOM] {Object}
- * [protected]
- */
-TemRTCPlugin = null;
-/**
- * Note:
- * webRTC readu Cb, should only be called once.
- * Need to prevent Chrome + plugin form calling WebRTCReadyCb twice
- * --------------------------------------------------------------------------
- * WebRTCReadyCb is callback function called when the browser is webrtc ready
- * this can be because of the browser or because of the plugin
- * Override WebRTCReadyCb and use it to do whatever you need to do when the
- * page is ready
- * [attribute] TemPrivateWebRTCReadyCb
- * [type] Function
- * [private]
- */
-TemPrivateWebRTCReadyCb = function () {
- arguments.callee.StaticWasInit = arguments.callee.StaticWasInit || 1;
- if (arguments.callee.StaticWasInit === 1) {
- if (typeof WebRTCReadyCb === 'function') {
- WebRTCReadyCb();
- }
- }
- arguments.callee.StaticWasInit++;
};
/**
- * Note:
- * !!! DO NOT OVERRIDE THIS FUNCTION !!!
- * This function will be called when plugin is ready
- * it sends necessary details to the plugin.
- * If you need to do something once the page/plugin is ready, override
- * TemPrivateWebRTCReadyCb instead.
- * This function is not in the IE/Safari condition brackets so that
- * TemPluginLoaded function might be called on Chrome/Firefox
- * [attribute] TemInitPlugin0
- * [type] Function
- * [protected]
- */
-TemInitPlugin0 = function () {
- TemRTCPlugin.setPluginId(TemPageId, temPluginInfo.pluginId);
- TemRTCPlugin.setLogFunction(console);
- TemPrivateWebRTCReadyCb();
-};
+ * Detected webrtc implementation. Types are:
+ * - 'moz': Mozilla implementation of webRTC.
+ * - 'webkit': WebKit implementation of webRTC.
+ * - 'plugin': Using Temasys's plugin implementation.
+ * @attribute webrtcDetectedType
+ * @type String
+ * @readOnly
+ * @for Temasys
+ */
+webrtcDetectedType = null;
+/**
+ * Detected webrtc datachannel support. Types are:
+ * - 'SCTP': SCTP datachannel support.
+ * - 'RTP': RTP datachannel support.
+ * @attribute webrtcDetectedDCSupport
+ * @type String
+ * @readOnly
+ * @for Temasys
+ */
+webrtcDetectedDCSupport = null;
/**
- * Note:
- * To Fix Configuration as some browsers,
- * some browsers does not support the 'urls' attribute
- * - .urls is not supported in FF yet.
- * [attribute] maybeFixConfiguration
- * [type] Function
- * _ [param] {JSON} pcConfig
- * [private]
+ * To fix configuration as some browsers does not support
+ * the 'urls' attribute.
+ * @method maybeFixConfiguration
+ * @param {JSON} pcConfig
+ * @for Temasys
*/
maybeFixConfiguration = function (pcConfig) {
if (pcConfig === null) {
@@ -267,129 +297,321 @@ maybeFixConfiguration = function (pcConfig) {
}
};
/**
- * Note:
- * Handles the differences for all Browsers
- *
+ * Set the settings for creating DataChannels, MediaStream for
+ * Cross-browser compability.
+ * - This is only for SCTP based support browsers.
+ * the 'urls' attribute.
+ * @method checkMediaDataChannelSettings
+ * @param {Boolean} isParseOC If function just needs to parse the offer constraints.
+ * @param {String} peerBrowserAgent Peer browser agent.
+ * @param {String} peerBrowserVersion Peer browser version.
+ * @param {Function} callback The callback once it's done.
+ * @param {JSON} constraints The offer constraints.
+ * @example
+ * checkMediaDataChannelSettings(peerAgentBrowser, peerAgentVersion,
+ * function (beOfferer, unifiedOfferConstraints) {
+ * if (beOfferer) {
+ * peerConnection.createOffer(function (offer) {
+ * // success
+ * }, function (error) {
+ * // failure
+ * }, unifiedOfferConstraints);
+ * } else {
+ * // let someone else do the job
+ * }
+ * }, inputConstraints);
+ * @for Temasys
+ */
+checkMediaDataChannelSettings =
+ function (peerBrowserAgent, peerBrowserVersion, callback, constraints) {
+ if (typeof callback !== 'function') {
+ return;
+ }
+ var beOfferer = true;
+ var isLocalFirefox = webrtcDetectedBrowser === 'firefox';
+ // Nightly version does not require MozDontOfferDataChannel for interop
+ var isLocalFirefoxInterop = webrtcDetectedType === 'moz' && webrtcDetectedVersion > 30;
+ var isPeerFirefox = peerBrowserAgent === 'firefox';
+ var isPeerFirefoxInterop = peerBrowserAgent === 'firefox' &&
+ ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
+
+ // Resends an updated version of constraints for MozDataChannel to work
+ // If other userAgent is firefox and user is firefox, remove MozDataChannel
+ if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
+ try {
+ delete constraints.mandatory.MozDontOfferDataChannel;
+ } catch (error) {
+ console.error('Failed deleting MozDontOfferDataChannel');
+ console.error(error);
+ }
+ } else if ((isLocalFirefox && !isPeerFirefox)) {
+ constraints.mandatory.MozDontOfferDataChannel = true;
+ }
+ if (!isLocalFirefox) {
+ // temporary measure to remove Moz* constraints in non Firefox browsers
+ for (var prop in constraints.mandatory) {
+ if (constraints.mandatory.hasOwnProperty(prop)) {
+ if (prop.indexOf('Moz') !== -1) {
+ delete constraints.mandatory[prop];
+ }
+ }
+ }
+ }
+ // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
+ // interopability of the media stream
+ if (isLocalFirefox && !isPeerFirefox && !isPeerFirefoxInterop) {
+ beOfferer = false;
+ }
+ callback(beOfferer, constraints);
+};
+/**
+ * Handles the differences for all browsers ice connection state output.
+ * - Tested outcomes are:
+ * - Chrome (offerer) : 'checking' > 'completed' > 'completed'
+ * - Chrome (answerer) : 'checking' > 'connected'
+ * - Firefox (offerer) : 'checking' > 'connected'
+ * - Firefox (answerer): 'checking' > 'connected'
* @method checkIceConnectionState
- * @param {String} peerID
- * @param {String} iceConnectionState
- * @param {Function} callback
- * @param {Boolean} returnStateAlways
- * @protected
+ * @param {String} peerId A unique identifier for the peer.
+ * @param {String} iceConnectionState The current ice connection state.
+ * @param {Function} callback The callback fired once the state is loaded.
+ * @return {String} The updated ice connection state.
+ * @example
+ * peerConnection.oniceconnectionstatechange = function () {
+ * checkICEConnectionState(peerId, peerConnection.iceConnectionState,
+ * function (updatedIceConnectionState) {
+ * // do Something every time there's a new state
+ * });
+ * };
+ * @for Temasys
*/
-checkIceConnectionState = function (peerID, iceConnectionState, callback, returnStateAlways) {
+checkIceConnectionState = function (peerId, iceConnectionState, callback) {
if (typeof callback !== 'function') {
+ console.warn('No callback specified in checkIceConnectionState. Aborted.');
return;
}
- peerID = (peerID) ? peerID : 'peer';
- var returnState = false, err = null;
- console.log('ICECONNECTIONSTATE: ' + iceConnectionState);
-
- if (!ICEConnectionFiredStates[peerID] ||
- iceConnectionState === ICEConnectionState.disconnected ||
- iceConnectionState === ICEConnectionState.failed ||
- iceConnectionState === ICEConnectionState.closed) {
- ICEConnectionFiredStates[peerID] = [];
+ peerId = (peerId) ? peerId : 'peer';
+
+ if (!Temasys._iceConnectionStates[peerId] ||
+ iceConnectionState === Temasys._iceConnectionStates.disconnected ||
+ iceConnectionState === Temasys._iceConnectionStates.failed ||
+ iceConnectionState === Temasys._iceConnectionStates.closed) {
+ Temasys._iceConnectionStates[peerId] = [];
}
- iceConnectionState = ICEConnectionState[iceConnectionState];
- if (ICEConnectionFiredStates[peerID].indexOf(iceConnectionState) === -1) {
- ICEConnectionFiredStates[peerID].push(iceConnectionState);
- if (iceConnectionState === ICEConnectionState.connected) {
+ iceConnectionState = Temasys._iceConnectionStates[iceConnectionState];
+ if (Temasys._iceConnectionStates[peerId].indexOf(iceConnectionState) < 0) {
+ Temasys._iceConnectionStates[peerId].push(iceConnectionState);
+ if (iceConnectionState === Temasys._iceConnectionStates.connected) {
setTimeout(function () {
- ICEConnectionFiredStates[peerID].push(ICEConnectionState.done);
- callback(ICEConnectionState.done);
+ Temasys._iceConnectionStates[peerId]
+ .push(Temasys._iceConnectionStates.done);
+ callback(Temasys._iceConnectionStates.done);
}, 1000);
}
- returnState = true;
- }
- if (returnStateAlways || returnState) {
callback(iceConnectionState);
}
return;
};
/**
- * Note:
- * Set the settings for creating DataChannels, MediaStream for Cross-browser compability.
- * This is only for SCTP based support browsers
- *
- * @method checkMediaDataChannelSettings
- * @param {Boolean} isOffer
- * @param {String} peerBrowserAgent
- * @param {Function} callback
+ * Check the availability of the MediaStream and DataChannel.
+ * Method to be called after getUserMedia
+ * @method checkMediaDataChannel
+ * @param {MediaStream} stream
* @param {JSON} constraints
- * @protected
+ * @for Temasys
*/
-checkMediaDataChannelSettings = function (isOffer, peerBrowserAgent, callback, constraints) {
- if (typeof callback !== 'function') {
- return;
+checkMediaDataChannel = function (stream, constraints) {
+ var testedOptions = {
+ audio : false,
+ video : false,
+ data : false
+ };
+ // Test MediaStream
+ if (constraints.audio && stream.getAudioTracks().length > 0) {
+ testedOptions.audio = true;
}
- var peerBrowserVersion, beOfferer = false;
-
- console.log('Self: ' + webrtcDetectedBrowser.browser + ' | Peer: ' + peerBrowserAgent);
-
- if (peerBrowserAgent.indexOf('|') > -1) {
- peerBrowser = peerBrowserAgent.split('|');
- peerBrowserAgent = peerBrowser[0];
- peerBrowserVersion = parseInt(peerBrowser[1], 10);
- console.info('Peer Browser version: ' + peerBrowserVersion);
+ if (constraints.video && stream.getVideoTracks().length > 0) {
+ testedOptions.video = true;
}
- var isLocalFirefox = webrtcDetectedBrowser.mozWebRTC;
- // Nightly version does not require MozDontOfferDataChannel for interop
- var isLocalFirefoxInterop = webrtcDetectedBrowser.mozWebRTC &&
- webrtcDetectedBrowser.version > 30;
- var isPeerFirefox = peerBrowserAgent === 'Firefox';
- var isPeerFirefoxInterop = peerBrowserAgent === 'Firefox' &&
- ((peerBrowserVersion) ? (peerBrowserVersion > 30) : false);
-
- // Resends an updated version of constraints for MozDataChannel to work
- // If other userAgent is firefox and user is firefox, remove MozDataChannel
- if (isOffer) {
- if ((isLocalFirefox && isPeerFirefox) || (isLocalFirefoxInterop)) {
- try {
- delete constraints.mandatory.MozDontOfferDataChannel;
- } catch (err) {
- console.error('Failed deleting MozDontOfferDataChannel');
- console.exception(err);
- }
- } else if ((isLocalFirefox && !isPeerFirefox)) {
- constraints.mandatory.MozDontOfferDataChannel = true;
- }
- if (!isLocalFirefox) {
- // temporary measure to remove Moz* constraints in non Firefox browsers
- for (var prop in constraints.mandatory) {
- if (constraints.mandatory.hasOwnProperty(prop)) {
- if (prop.indexOf('Moz') !== -1) {
- delete constraints.mandatory[prop];
- }
- }
- }
- }
- console.log('Set Offer constraints for DataChannel and MediaStream interopability');
- console.dir(constraints);
- callback(constraints);
- } else {
- // Tells user to resend an 'enter' again
- // Firefox (not interopable) cannot offer DataChannel as it will cause problems to the
- // interopability of the media stream
- if (!isLocalFirefox && isPeerFirefox && !isPeerFirefoxInterop) {
- beOfferer = true;
+ // Test DataChannel
+ var testPeer = new RTCPeerConnection();
+ try {
+ var dc = testPeer.createDataChannel('_');
+ if (dc) {
+ testedOptions.data = true;
}
- console.info('Resend Enter: ' + beOfferer);
- callback(beOfferer);
+ } catch (error) {
+ console.error('Failed creating DataChannel');
+ console.error(error);
}
+ return testedOptions;
};
-/*******************************************************************
- Check for browser types and react accordingly
-*******************************************************************/
-if (webrtcDetectedBrowser.mozWebRTC) {
- /**
- * Note:
- * Creates a RTCPeerConnection object for moz
- *
- * [method] RTCPeerConnection
- * [param] {JSON} pcConfig
- * [param] {JSON} pcConstraints
- */
+/**
+ * AdapterJS original google code.
+ * - Adapted from: https://code.google.com/p/webrtc/source/
+ * browse/trunk/samples/js/base/adapter.js?r=3905
+ * @class Original
+ */
+/**
+ * The RTCPeerConnection object.
+ * @function RTCPeerConnection
+ * @param {JSON} pcConfig Servers configuration
+ * @param {JSON} pcConstraints Constraints
+ * @return {Object} The PeerConnection object.
+ * @for Original
+ */
+RTCPeerConnection = null;
+/**
+ * Plugin:
+ * - Creates RTCSessionDescription object for Plugin Browsers
+ * - This is a WebRTC Function
+ * @method RTCSessionDescription
+ * @param {JSON} info
+ * @return {Object} The RTCSessionDescription object
+ * @for Original
+ */
+RTCSessionDescription = (typeof RTCSessionDescription === 'function') ?
+ RTCSessionDescription : null;
+/**
+ * Plugin:
+ * - Creates RTCIceCandidate object for Plugin Browsers
+ * - This is a WebRTC Function
+ * @method RTCIceCandidate
+ * @param {Object} candidate
+ * @return {Object} The RTCIceCandidate object
+ * @for Original
+ */
+RTCIceCandidate = (typeof RTCIceCandidate === 'function') ?
+ RTCIceCandidate : null;
+/**
+ * Get UserMedia (only difference is the prefix).
+ * @function getUserMedia
+ * @param {JSON} mediaConstraints Media constraints
+ * @param {JSON} successCallback Callback when MediaStream is obtained
+ * successfully.
+ * @param {JSON} failuedCallback Callback when MediaStream failed to
+ * be obtained.
+ * @return {Object} The MediaStream object.
+ * @author Adam Barth.
+ * @for Original
+ */
+getUserMedia = null;
+/**
+ * Attach a media stream to an element.
+ * @function attachMediaStream
+ * @param {DOM} videoElement The Video element
+ * @param {Object} mediaStream The MediaStream object
+ * @for Original
+ */
+attachMediaStream = null;
+/**
+ * Re-attach a media stream to an element.
+ * @function reattachMediaStream
+ * @param {DOM} fromVideoElement The Video element with the stream url
+ * @param {DOM} toVideoElement The Video element to be duplicated with
+ * the stream url.
+ * @for Original
+ */
+reattachMediaStream = null;
+/**
+ * Firefox:
+ * - Creates iceServer from the url for Firefox.
+ * - Create iceServer with stun url.
+ * - Create iceServer with turn url.
+ * - Ignore the transport parameter from TURN url for FF version <=27.
+ * - Return null for createIceServer if transport=tcp.
+ * - FF 27 and above supports transport parameters in TURN url,
+ * - So passing in the full url to create iceServer.
+ * Chrome:
+ * - Creates iceServer from the url for Chrome M33 and earlier.
+ * - Create iceServer with stun url.
+ * - Chrome M28 & above uses below TURN format.
+ * Plugin:
+ * - Creates Ice Server for Plugin Browsers
+ * - If Stun - Create iceServer with stun url.
+ * - Else - Create iceServer with turn url
+ * - This is a WebRTC Function
+ * @method createIceServer
+ * @param {String} url
+ * @param {String} username
+ * @param {String} password
+ * @return {JSON} Ice Server Configuration
+ * @for Original
+ */
+createIceServer = null;
+/**
+ * Firefox:
+ * - Creates IceServers for Firefox
+ * - Use .url for FireFox.
+ * - Multiple Urls support
+ * Chrome:
+ * - Creates iceServers from the urls for Chrome M34 and above.
+ * - .urls is supported since Chrome M34.
+ * - Multiple Urls support
+ * Plugin:
+ * - Creates Ice Servers for Plugin Browsers
+ * - Multiple Urls support
+ * - This is a WebRTC Function
+ * @method createIceServers
+ * @param {Array} urls
+ * @param {String} username
+ * @param {String} password
+ * @return {Array} List of Ice Servers Configuration
+ * @for Original
+ */
+createIceServers = null;
+/**
+ * Firefox:
+ * - Creates IceServers for Firefox
+ * - Use .url for FireFox.
+ * - Multiple Urls support
+ * Chrome:
+ * - Creates iceServers from the urls for Chrome M34 and above.
+ * - .urls is supported since Chrome M34.
+ * - Multiple Urls support
+ * Plugin:
+ * - Creates Ice Servers for Plugin Browsers
+ * - Multiple Urls support
+ * - This is a WebRTC Function
+ * @method createIceServers
+ * @param {Array} urls
+ * @param {String} username
+ * @param {String} password
+ * @return {Array} List of Ice Servers Configuration
+ * @for Original
+ */
+createIceServers = null;
+/**
+ * Detected browser agent name. Types are:
+ * - 'firefox': Firefox browser.
+ * - 'chrome': Chrome browser.
+ * - 'opera': Opera browser.
+ * - 'safari': Safari browser.
+ * - 'IE' - Internet Explorer browser.
+ * @attribute webrtcDetectedBrowser
+ * @type String
+ * @readOnly
+ * @required
+ * @for Original
+ */
+webrtcDetectedBrowser = null;
+/**
+ * Detected browser version.
+ * @attribute webrtcDetectedVersion
+ * @type Integer
+ * @readOnly
+ * @required
+ * @for Original
+ */
+webrtcDetectedVersion = null;
+// Check for browser types and react accordingly
+if (navigator.mozGetUserMedia) {
+ webrtcDetectedBrowser = 'firefox';
+ webrtcDetectedVersion = parseInt(navigator
+ .userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+ webrtcDetectedType = 'moz';
+ webrtcDetectedDCSupport = 'SCTP';
+
RTCPeerConnection = function (pcConfig, pcConstraints) {
maybeFixConfiguration(pcConfig);
return new mozRTCPeerConnection(pcConfig, pcConstraints);
@@ -400,57 +622,33 @@ if (webrtcDetectedBrowser.mozWebRTC) {
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Creates iceServer from the url for Firefox.
- * - Create iceServer with stun url.
- * - Create iceServer with turn url.
- * - Ignore the transport parameter from TURN url for FF version <=27.
- * - Return null for createIceServer if transport=tcp.
- * - FF 27 and above supports transport parameters in TURN url,
- * - So passing in the full url to create iceServer.
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
if (url_parts[0].indexOf('stun') === 0) {
- iceServer = { 'url' : url };
+ iceServer = { url : url };
} else if (url_parts[0].indexOf('turn') === 0) {
- if (webrtcDetectedBrowser.version < 27) {
+ if (webrtcDetectedVersion < 27) {
var turn_url_parts = url.split('?');
- if (turn_url_parts.length === 1 || turn_url_parts[1].indexOf('transport=udp') === 0) {
+ if (turn_url_parts.length === 1 ||
+ turn_url_parts[1].indexOf('transport=udp') === 0) {
iceServer = {
- 'url' : turn_url_parts[0],
- 'credential' : password,
- 'username' : username
+ url : turn_url_parts[0],
+ credential : password,
+ username : username
};
}
} else {
iceServer = {
- 'url' : url,
- 'credential' : password,
- 'username' : username
+ url : url,
+ credential : password,
+ username : username
};
}
}
return iceServer;
};
- /**
- * Note:
- * Creates IceServers for Firefox
- * - Use .url for FireFox.
- * - Multiple Urls support
- *
- * [method] createIceServers
- * [param] {JSON} pcConfig
- * [param] {JSON} pcConstraints
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
for (i = 0; i < urls.length; i++) {
@@ -462,39 +660,19 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Attach Media Stream for moz
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
- console.log('Attaching media stream');
element.mozSrcObject = stream;
element.play();
return element;
};
- /**
- * Note:
- * Re-attach Media Stream for moz
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
- console.log('Reattaching media stream');
to.mozSrcObject = from.mozSrcObject;
to.play();
return to;
};
- /*******************************************************
- Fake get{Video,Audio}Tracks
- ********************************************************/
+ // Fake get{Video,Audio}Tracks
if (!MediaStream.prototype.getVideoTracks) {
MediaStream.prototype.getVideoTracks = function () {
return [];
@@ -505,19 +683,28 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return [];
};
}
- TemPrivateWebRTCReadyCb();
-} else if (webrtcDetectedBrowser.webkitWebRTC) {
- /**
- * Note:
- * Creates iceServer from the url for Chrome M33 and earlier.
- * - Create iceServer with stun url.
- * - Chrome M28 & above uses below TURN format.
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
+} else if (navigator.webkitGetUserMedia) {
+ webrtcDetectedBrowser = 'chrome';
+ webrtcDetectedType = 'webkit';
+ webrtcDetectedVersion = parseInt(navigator
+ .userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+ // check if browser is opera 20+
+ var checkIfOpera = navigator.userAgent.match(/\bOPR\/(\d+)/);
+ if (checkIfOpera !== null) {
+ webrtcDetectedBrowser = 'opera';
+ webrtcDetectedVersion = parseInt(checkIfOpera[1], 10);
+ }
+ // check browser datachannel support
+ if ((webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion >= 31) ||
+ (webrtcDetectedBrowser === 'opera' && webrtcDetectedVersion >= 20)) {
+ webrtcDetectedDCSupport = 'SCTP';
+ } else if (webrtcDetectedBrowser === 'chrome' && webrtcDetectedVersion < 30 &&
+ webrtcDetectedVersion > 24) {
+ webrtcDetectedDCSupport = 'RTP';
+ } else {
+ webrtcDetectedDCSupport = '';
+ }
+
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
@@ -533,20 +720,9 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServer;
};
- /**
- * Note:
- * Creates iceServers from the urls for Chrome M34 and above.
- * - .urls is supported since Chrome M34.
- * - Multiple Urls support
- *
- * [method] createIceServers
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
- if (webrtcDetectedBrowser.version >= 34) {
+ if (webrtcDetectedVersion >= 34) {
iceServers = {
'urls' : urls,
'credential' : password,
@@ -563,17 +739,8 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Creates an RTCPeerConection Object for webkit
- * - .urls is supported since Chrome M34.
- * [method] RTCPeerConnection
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
RTCPeerConnection = function (pcConfig, pcConstraints) {
- if (webrtcDetectedBrowser.version < 34) {
+ if (webrtcDetectedVersion < 34) {
maybeFixConfiguration(pcConfig);
}
return new webkitRTCPeerConnection(pcConfig, pcConstraints);
@@ -582,14 +749,6 @@ if (webrtcDetectedBrowser.mozWebRTC) {
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Attach Media Stream for webkit
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
if (typeof element.srcObject !== 'undefined') {
element.srcObject = stream;
@@ -603,60 +762,90 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return element;
};
- /**
- * Note:
- * Re-attach Media Stream for webkit
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
to.src = from.src;
return to;
};
- TemPrivateWebRTCReadyCb();
-} else if (webrtcDetectedBrowser.pluginWebRTC) {
- // var isOpera = webrtcDetectedBrowser.browser === 'Opera'; // Might not be used.
- var isFirefox = webrtcDetectedBrowser.browser === 'Firefox';
- var isSafari = webrtcDetectedBrowser.browser === 'Safari';
- var isChrome = webrtcDetectedBrowser.browser === 'Chrome';
- var isIE = webrtcDetectedBrowser.browser === 'IE';
-
- /********************************************************************************
- Load Plugin
- ********************************************************************************/
- TemRTCPlugin = document.createElement('object');
- TemRTCPlugin.id = temPluginInfo.pluginId;
- TemRTCPlugin.style.visibility = 'hidden';
- TemRTCPlugin.type = temPluginInfo.type;
- TemRTCPlugin.innerHTML = '' +
- '' +
- '';
- document.getElementsByTagName('body')[0].appendChild(TemRTCPlugin);
- TemRTCPlugin.onreadystatechange = function (state) {
- console.log('Plugin: Ready State : ' + state);
- if (state === 4) {
- console.log('Plugin has been loaded');
+} else { // TRY TO USE PLUGIN
+ // IE 9 is not offering an implementation of console.log until you open a console
+ if (typeof console !== 'object' || typeof console.log !== 'function') {
+ var console = console || {};
+ console.log = function (arg) {
+ // You may override this function
+ };
+ }
+ webrtcDetectedType = 'plugin';
+ webrtcDetectedDCSupport = 'plugin';
+ parseWebrtcDetectedBrowser();
+ isIE = webrtcDetectedBrowser === 'IE';
+
+ Temasys.WebRTCPlugin.WaitForPluginReady = function() {
+ while (!Temasys.WebRTCPlugin.isPluginReady) {
+ /* empty because it needs to prevent the function from running. */
+ }
+ };
+
+ Temasys.WebRTCPlugin.callWhenPluginReady = function (callback) {
+ var checkPluginReadyState = setInterval(function () {
+ if (Temasys.WebRTCPlugin.isPluginReady) {
+ clearInterval(checkPluginReadyState);
+ callback();
+ }
+ }, 100);
+ };
+
+ Temasys.WebRTCPlugin.injectPlugin = function () {
+ if (webrtcDetectedBrowser === 'IE' && webrtcDetectedVersion <= 9) {
+ var frag = document.createDocumentFragment();
+ Temasys.WebRTCPlugin.TemRTCPlugin = document.createElement('div');
+ Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML = '';
+ while (Temasys.WebRTCPlugin.TemRTCPlugin.firstChild) {
+ frag.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin.firstChild);
+ }
+ document.body.appendChild(frag);
+
+ // Need to re-fetch the plugin
+ Temasys.WebRTCPlugin.TemRTCPlugin =
+ document.getElementById(Temasys.WebRTCPlugin.temPluginInfo.pluginId);
+ } else {
+ // Load Plugin
+ Temasys.WebRTCPlugin.TemRTCPlugin = document.createElement('object');
+ Temasys.WebRTCPlugin.TemRTCPlugin.id =
+ Temasys.WebRTCPlugin.temPluginInfo.pluginId;
+ // IE will only start the plugin if it's ACTUALLY visible
+ if (isIE) {
+ Temasys.WebRTCPlugin.TemRTCPlugin.width = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.height = '1px';
+ }
+ Temasys.WebRTCPlugin.TemRTCPlugin.width = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.height = '1px';
+ Temasys.WebRTCPlugin.TemRTCPlugin.type = Temasys.WebRTCPlugin.temPluginInfo.type;
+ Temasys.WebRTCPlugin.TemRTCPlugin.innerHTML = '' +
+ '' +
+ ' ' +
+ // uncomment to be able to use virtual cams
+ // '' +
+ '';
+ document.body.appendChild(Temasys.WebRTCPlugin.TemRTCPlugin);
}
};
- /**
- * Note:
- * Checks if the Plugin is installed
- * - Check If Not IE (firefox, for example)
- * - Else If it's IE - we're running IE and do something
- * - Else Unsupported
- *
- * [method] isPluginInstalled
- * [param] {String} comName
- * [param] {String} plugName
- * [param] {Function} installedCb
- * [param] {Function} notInstalledCb
- */
- isPluginInstalled = function (comName, plugName, installedCb, notInstalledCb) {
- if (isChrome || isSafari || isFirefox) {
+
+ Temasys.WebRTCPlugin.isPluginInstalled =
+ function (comName, plugName, installedCb, notInstalledCb) {
+ if (!isIE) {
var pluginArray = navigator.plugins;
for (var i = 0; i < pluginArray.length; i++) {
if (pluginArray[i].name.indexOf(plugName) >= 0) {
@@ -665,7 +854,7 @@ if (webrtcDetectedBrowser.mozWebRTC) {
}
}
notInstalledCb();
- } else if (isIE) {
+ } else {
try {
var axo = new ActiveXObject(comName + '.' + plugName);
} catch (e) {
@@ -673,42 +862,14 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return;
}
installedCb();
- } else {
- return;
}
};
- /**
- * Note:
- * Define Plugin Browsers as WebRTC Interface
- *
- * [method] defineWebRTCInterface
- */
- defineWebRTCInterface = function () {
- /**
- * Note:
- * Check if WebRTC Interface is Defined
- * - This is a Util Function
- *
- * [method] isDefined
- * [param] {String} variable
- */
- isDefined = function (variable) {
+ Temasys.WebRTCPlugin.defineWebRTCInterface = function () {
+ Temasys.WebRTCPlugin.isDefined = function (variable) {
return variable !== null && variable !== undefined;
};
- /**
- * Note:
- * Creates Ice Server for Plugin Browsers
- * - If Stun - Create iceServer with stun url.
- * - Else - Create iceServer with turn url
- * - This is a WebRTC Function
- *
- * [method] createIceServer
- * [param] {String} url
- * [param] {String} username
- * [param] {String} password
- */
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
@@ -728,17 +889,6 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServer;
};
- /**
- * Note:
- * Creates Ice Servers for Plugin Browsers
- * - Multiple Urls support
- * - This is a WebRTC Function
- *
- * [method] createIceServers
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
createIceServers = function (urls, username, password) {
var iceServers = [];
for (var i = 0; i < urls.length; ++i) {
@@ -747,29 +897,12 @@ if (webrtcDetectedBrowser.mozWebRTC) {
return iceServers;
};
- /**
- * Note:
- * Creates RTCSessionDescription object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCSessionDescription
- * [param] {Array} urls
- * [param] {String} username
- * [param] {String} password
- */
RTCSessionDescription = function (info) {
- return TemRTCPlugin.ConstructSessionDescription(info.type, info.sdp);
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.
+ ConstructSessionDescription(info.type, info.sdp);
};
- /**
- * Note:
- * Creates RTCPeerConnection object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCSessionDescription
- * [param] {JSON} servers
- * [param] {JSON} contstraints
- */
RTCPeerConnection = function (servers, constraints) {
var iceServers = null;
if (servers) {
@@ -778,41 +911,41 @@ if (webrtcDetectedBrowser.mozWebRTC) {
if (iceServers[i].urls && !iceServers[i].url) {
iceServers[i].url = iceServers[i].urls;
}
- iceServers[i].hasCredentials = isDefined(iceServers[i].username) &&
- isDefined(iceServers[i].credential);
+ iceServers[i].hasCredentials = Temasys.WebRTCPlugin.
+ isDefined(iceServers[i].username) &&
+ Temasys.WebRTCPlugin.isDefined(iceServers[i].credential);
}
}
- var mandatory = (constraints && constraints.mandatory) ? constraints.mandatory : null;
- var optional = (constraints && constraints.optional) ? constraints.optional : null;
- return TemRTCPlugin.PeerConnection(TemPageId, iceServers, mandatory, optional);
+ var mandatory = (constraints && constraints.mandatory) ?
+ constraints.mandatory : null;
+ var optional = (constraints && constraints.optional) ?
+ constraints.optional : null;
+
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.
+ PeerConnection(Temasys.WebRTCPlugin.TemPageId,
+ iceServers, mandatory, optional);
};
MediaStreamTrack = {};
MediaStreamTrack.getSources = function (callback) {
- TemRTCPlugin.GetSources(callback);
+ Temasys.WebRTCPlugin.callWhenPluginReady(function() {
+ Temasys.WebRTCPlugin.TemRTCPlugin.GetSources(callback);
+ });
};
- /*******************************************************
- getUserMedia
- ********************************************************/
getUserMedia = function (constraints, successCallback, failureCallback) {
if (!constraints.audio) {
constraints.audio = false;
}
- TemRTCPlugin.getUserMedia(constraints, successCallback, failureCallback);
+
+ Temasys.WebRTCPlugin.callWhenPluginReady(function() {
+ Temasys.WebRTCPlugin.TemRTCPlugin.
+ getUserMedia(constraints, successCallback, failureCallback);
+ });
};
navigator.getUserMedia = getUserMedia;
- /**
- * Note:
- * Attach Media Stream for Plugin Browsers
- * - If Check is audio element
- * - Else The sound was enabled, there is nothing to do here
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} element
- * [param] {Blob} Stream
- */
attachMediaStream = function (element, stream) {
stream.enableSoundTracks(true);
if (element.nodeName.toLowerCase() !== 'audio') {
@@ -824,7 +957,8 @@ if (webrtcDetectedBrowser.mozWebRTC) {
temp.innerHTML = '';
while (temp.firstChild) {
@@ -847,66 +981,135 @@ if (webrtcDetectedBrowser.mozWebRTC) {
element.setStreamId(stream.id);
}
var newElement = document.getElementById(elementId);
- newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
- newElement._TemOnClick = function (id) {
- var arg = {
- srcElement : document.getElementById(id)
+ newElement.onplaying = (element.onplaying) ? element.onplaying : function (arg) {};
+ if (isIE) { // on IE the event needs to be plugged manually
+ newElement.attachEvent('onplaying', newElement.onplaying);
+ newElement.onclick = (element.onclick) ? element.onclick : function (arg) {};
+ newElement._TemOnClick = function (id) {
+ var arg = {
+ srcElement : document.getElementById(id)
+ };
+ newElement.onclick(arg);
};
- newElement.onclick(arg);
- };
+ }
return newElement;
} else {
return element;
}
};
- /**
- * Note:
- * Re-attach Media Stream for Plugin Browsers
- *
- * [method] attachMediaStream
- * [param] {HTMLVideoDOM} to
- * [param] {HTMLVideoDOM} from
- */
reattachMediaStream = function (to, from) {
var stream = null;
var children = from.children;
for (var i = 0; i !== children.length; ++i) {
if (children[i].name === 'streamId') {
- stream = TemRTCPlugin.getStreamWithId(TemPageId, children[i].value);
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ stream = Temasys.WebRTCPlugin.TemRTCPlugin
+ .getStreamWithId(Temasys.WebRTCPlugin.TemPageId, children[i].value);
break;
}
}
if (stream !== null) {
return attachMediaStream(to, stream);
} else {
- alert('Could not find the stream associated with this element');
+ console.log('Could not find the stream associated with this element');
}
};
- /**
- * Note:
- * Creates RTCIceCandidate object for Plugin Browsers
- * - This is a WebRTC Function
- *
- * [method] RTCIceCandidate
- * [param] {JSON} candidate
- */
RTCIceCandidate = function (candidate) {
if (!candidate.sdpMid) {
candidate.sdpMid = '';
}
- return TemRTCPlugin.ConstructIceCandidate(
+
+ Temasys.WebRTCPlugin.WaitForPluginReady();
+ return Temasys.WebRTCPlugin.TemRTCPlugin.ConstructIceCandidate(
candidate.sdpMid, candidate.sdpMLineIndex, candidate.candidate
);
};
+
+ Temasys.WebRTCPlugin.injectPlugin();
};
- pluginNeededButNotInstalledCb = function () {
- alert('Your browser is not webrtc ready and Temasys plugin is not installed');
+ Temasys.WebRTCPlugin.getWebsiteLink = function() {
+ return 'http://temasys.atlassian.net/wiki/display/TWPP/WebRTC+Plugins';
+ };
+
+ Temasys.WebRTCPlugin.getDownloadLink = function() {
+ if(!!navigator.platform.match(/^Mac/i)) {
+ return 'http://bit.ly/1n77hco';
+ }
+ else if(!!navigator.platform.match(/^Win/i)) {
+ return 'http://bit.ly/1kkS4FN';
+ }
+ return null;
+ };
+
+ Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb = function () {
+ var downloadLink = Temasys.WebRTCPlugin.getDownloadLink();
+ if(downloadLink) {
+ Temasys.WebRTCPlugin.renderNotificationBar('This website needs to install the Temasys WebRTC Plugin' +
+ ' to upgrade your browser.', 'Install Now', downloadLink);
+ }
+ else {
+ Temasys.WebRTCPlugin.renderNotificationBar('Your browser does not support WebRTC.');
+ }
+ };
+
+ Temasys.WebRTCPlugin.renderNotificationBar = function (text, buttonText, buttonLink) {
+ var w = window;
+ var i = document.createElement('iframe');
+ i.style.position = 'fixed';
+ i.style.top = '-41px';
+ i.style.left = 0;
+ i.style.right = 0;
+ i.style.width = '100%';
+ i.style.height = '40px';
+ i.style.backgroundColor = '#ffffe1';
+ i.style.border = 'none';
+ i.style.borderBottom = '1px solid #888888';
+ i.style.zIndex = '9999999';
+ if(typeof i.style.webkitTransition === 'string') {
+ i.style.webkitTransition = 'all .5s ease-out';
+ } else if(typeof i.style.transition === 'string') {
+ i.style.transition = 'all .5s ease-out';
+ }
+ document.body.appendChild(i);
+ c = (i.contentWindow) ? i.contentWindow :
+ (i.contentDocument.document) ? i.contentDocument.document : i.contentDocument;
+ c.document.open();
+ c.document.write('' + text + '');
+ if(buttonText && buttonLink) {
+ c.document.write('');
+ c.document.close();
+ c.document.getElementById('okay').addEventListener('click', function(e) {
+ window.open(buttonLink, '_top');
+ e.preventDefault();
+ try {
+ event.cancelBubble = true;
+ } catch(error) { }
+ });
+ }
+ else {
+ c.document.close();
+ }
+ c.document.addEventListener('click', function() {
+ w.document.body.removeChild(i);
+ });
+ setTimeout(function() {
+ if(typeof i.style.webkitTransform === 'string') {
+ i.style.webkitTransform = 'translateY(40px)';
+ } else if(typeof i.style.transform === 'string') {
+ i.style.transform = 'translateY(40px)';
+ } else {
+ i.style.top = '0px';
+ }
+ }, 300);
};
// Try to detect the plugin and act accordingly
- isPluginInstalled('Tem', 'TemWebRTCPlugin', defineWebRTCInterface, pluginNeededButNotInstalledCb);
-} else {
- console.log('Browser does not appear to be WebRTC-capable');
+ Temasys.WebRTCPlugin.isPluginInstalled('Tem', 'TemWebRTCPlugin',
+ Temasys.WebRTCPlugin.defineWebRTCInterface,
+ Temasys.WebRTCPlugin.pluginNeededButNotInstalledCb);
}
diff --git a/tests/adapter_test.js b/tests/adapter_test.js
index d256f76..640f740 100644
--- a/tests/adapter_test.js
+++ b/tests/adapter_test.js
@@ -10,4 +10,4 @@ test('RTCPeerConnection is defined', function (t) {
test('getUserMedia is defined', function (t) {
t.plan(1);
t.notEqual(window.getUserMedia, undefined);
-});
+});
\ No newline at end of file