diff --git a/.javascript_ignore b/.javascript_ignore
index 8aa969c3..3149090d 100644
--- a/.javascript_ignore
+++ b/.javascript_ignore
@@ -1 +1 @@
-static/js/libs/**.js
\ No newline at end of file
+static/js/libs/
diff --git a/.travis.yml b/.travis.yml
index 4cb5ae9a..86610262 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -7,6 +7,7 @@ go:
- 1.2
- 1.3
- 1.4
+ - 1.5
- tip
env:
diff --git a/Makefile.am b/Makefile.am
index 8c7fc254..3d9623ca 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -124,32 +124,32 @@ release: OUTPUT = $(DIST_BIN)
release: $(DIST_BIN) binary releaseassets
install:
- @echo "Installing binaries to: $(BIN)"
- @echo "Installing static resources to: $(SHARE)"
- $(INSTALL) -d $(BIN)
- $(INSTALL) -d $(SHARE)/www/html
- $(INSTALL) -d $(SHARE)/www/html/sandboxes
- $(INSTALL) -d $(SHARE)/www/static
- $(INSTALL) -d $(SHARE)/www/static/img
- $(INSTALL) -d $(SHARE)/www/static/sounds
- $(INSTALL) -d $(SHARE)/www/static/fonts
- $(INSTALL) -d $(SHARE)/www/static/translation
- $(INSTALL) -d $(SHARE)/www/static/css
- $(INSTALL) -d $(SHARE)/www/static/js/libs/pdf
- $(INSTALL) -d $(SHARE)/www/static/js/sandboxes
- $(INSTALL) bin/$(EXENAME) $(BIN)
- $(INSTALL) html/*.html $(SHARE)/www/html
- $(INSTALL) html/sandboxes/*.html $(SHARE)/www/html/sandboxes
- $(INSTALL) static/img/* $(SHARE)/www/static/img
- $(INSTALL) static/sounds/* $(SHARE)/www/static/sounds
- $(INSTALL) static/fonts/* $(SHARE)/www/static/fonts
- $(INSTALL) static/translation/* $(SHARE)/www/static/translation
- $(INSTALL) static/css/* $(SHARE)/www/static/css
- $(INSTALL) -D static/js/libs/require/require.js $(SHARE)/www/static/js/libs/require/require.js
- $(INSTALL) $(OUTPUT_JS)/*.js $(SHARE)/www/static/js
- $(INSTALL) $(OUTPUT_JS)/libs/pdf/*.js $(SHARE)/www/static/js/libs/pdf
- $(INSTALL) -D static/js/libs/webodf.js $(SHARE)/www/static/js/libs/webodf.js
- $(INSTALL) $(OUTPUT_JS)/sandboxes/*.js $(SHARE)/www/static/js/sandboxes
+ @echo "Installing binaries to: $(DESTDIR)$(BIN)"
+ @echo "Installing static resources to: $(DESTDIR)$(SHARE)"
+ $(INSTALL) -d $(DESTDIR)$(BIN)
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/html
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/html/sandboxes
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/img
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/sounds
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/fonts
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/translation
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/css
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/js/libs/pdf
+ $(INSTALL) -d $(DESTDIR)$(SHARE)/www/static/js/sandboxes
+ $(INSTALL) bin/$(EXENAME) $(DESTDIR)$(BIN)
+ $(INSTALL) html/*.html $(DESTDIR)$(SHARE)/www/html
+ $(INSTALL) html/sandboxes/*.html $(DESTDIR)$(SHARE)/www/html/sandboxes
+ $(INSTALL) static/img/* $(DESTDIR)$(SHARE)/www/static/img
+ $(INSTALL) static/sounds/* $(DESTDIR)$(SHARE)/www/static/sounds
+ $(INSTALL) static/fonts/* $(DESTDIR)$(SHARE)/www/static/fonts
+ $(INSTALL) static/translation/* $(DESTDIR)$(SHARE)/www/static/translation
+ $(INSTALL) static/css/* $(DESTDIR)$(SHARE)/www/static/css
+ $(INSTALL) -D static/js/libs/require/require.js $(DESTDIR)$(SHARE)/www/static/js/libs/require/require.js
+ $(INSTALL) $(OUTPUT_JS)/*.js $(DESTDIR)$(SHARE)/www/static/js
+ $(INSTALL) $(OUTPUT_JS)/libs/pdf/*.js $(DESTDIR)$(SHARE)/www/static/js/libs/pdf
+ $(INSTALL) -D static/js/libs/webodf.js $(DESTDIR)$(SHARE)/www/static/js/libs/webodf.js
+ $(INSTALL) $(OUTPUT_JS)/sandboxes/*.js $(DESTDIR)$(SHARE)/www/static/js/sandboxes
clean:
$(GO) clean -i -r app/... 2>/dev/null || true
diff --git a/README.md b/README.md
index aaa71dfc..b465df12 100644
--- a/README.md
+++ b/README.md
@@ -102,6 +102,9 @@ Styles can be found in src/styles. Translations are found in src/i18n.
Each folder has its own Makefile to build the corresponding files. Check the
Makefile.am templates for available make targets.
+Javascript console logging is automatically _disabled_ and can be enabled by
+adding the query parameter `debug` to your url `https://my_url?debug`.
+
## Running server for development
diff --git a/html/head.html b/html/head.html
index 888bb468..5efedc9e 100644
--- a/html/head.html
+++ b/html/head.html
@@ -4,6 +4,7 @@
+
<%if.Csp%><%end%>
diff --git a/html/sandboxes/odfcanvas_sandbox.html b/html/sandboxes/odfcanvas_sandbox.html
index 2fa64ba5..a334a4fc 100644
--- a/html/sandboxes/odfcanvas_sandbox.html
+++ b/html/sandboxes/odfcanvas_sandbox.html
@@ -28,6 +28,7 @@
user-select:none;
-webkit-user-select:none;
-moz-user-select:none;
+ background:white;
}
diff --git a/html/sandboxes/pdfcanvas_sandbox.html b/html/sandboxes/pdfcanvas_sandbox.html
index 73840787..c193e31e 100644
--- a/html/sandboxes/pdfcanvas_sandbox.html
+++ b/html/sandboxes/pdfcanvas_sandbox.html
@@ -22,6 +22,7 @@
margin:0 auto;
position:relative;
display:none;
+ background:white;
}
diff --git a/package.json b/package.json
index 167ee1f8..f991d074 100644
--- a/package.json
+++ b/package.json
@@ -1,7 +1,7 @@
{
"private": true,
"dependencies": {
- "autoprefixer": ">= 3.1.0",
+ "autoprefixer": ">= 3.1.0 <= 5.2.1",
"po2json": ">= 0.4.1",
"jshint": ">= 2.5.5"
}
diff --git a/src/hooks/pre-commit.hook b/src/hooks/pre-commit.hook
index 990d0350..998388f3 100755
--- a/src/hooks/pre-commit.hook
+++ b/src/hooks/pre-commit.hook
@@ -27,7 +27,6 @@ echo "==========================================================================
fi
done
-
for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "\.js$"` ; do
case "$file" in
*/libs/*)
@@ -39,7 +38,7 @@ for file in `git diff-index --cached --name-only HEAD --diff-filter=ACMR| grep "
*)
echo "Checking ${file}"
nf=`git checkout-index --temp ${file} | cut -f 1`
- jshint --config .jshint "${nf}"
+ PATH="node_modules/.bin:${PATH}" jshint --config .jshint "${nf}"
r=$?
rm "${nf}"
if [ $r != 0 ] ; then
diff --git a/static/js/base.js b/static/js/base.js
index 92b324b0..4367027c 100644
--- a/static/js/base.js
+++ b/static/js/base.js
@@ -19,6 +19,7 @@
*
*/
+"use strict";
define([ // Helper module to put non dependency base libraries together.
'modernizr',
'moment',
diff --git a/static/js/directives/buddylist.js b/static/js/directives/buddylist.js
index 38efcc17..ed4d000b 100644
--- a/static/js/directives/buddylist.js
+++ b/static/js/directives/buddylist.js
@@ -29,10 +29,19 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
var controller = ['$scope', '$element', '$attrs', function($scope, $element, $attrs) {
+ var buddylist = $scope.buddylist = buddyList.buddylist($element, $scope, {});
+ var onJoined = _.bind(buddylist.onJoined, buddylist);
+ var onLeft = _.bind(buddylist.onLeft, buddylist);
+ var onStatus = _.bind(buddylist.onStatus, buddylist);
+ var onContactAdded = _.bind(buddylist.onContactAdded, buddylist);
+ var onContactRemoved = _.bind(buddylist.onContactRemoved, buddylist);
+ var onContactUpdated = _.bind(buddylist.onContactUpdated, buddylist);
+
+ var inRoom = false;
+
$scope.layout.buddylist = false;
$scope.layout.buddylistAutoHide = true;
- var inRoom = false;
var updateBuddyListVisibility = function() {
if (inRoom && !$scope.peer) {
$scope.layout.buddylist = true;
@@ -87,13 +96,6 @@ define(['underscore', 'text!partials/buddylist.html'], function(_, template) {
};
- var buddylist = $scope.buddylist = buddyList.buddylist($element, $scope, {});
- var onJoined = _.bind(buddylist.onJoined, buddylist);
- var onLeft = _.bind(buddylist.onLeft, buddylist);
- var onStatus = _.bind(buddylist.onStatus, buddylist);
- var onContactAdded = _.bind(buddylist.onContactAdded, buddylist);
- var onContactRemoved = _.bind(buddylist.onContactRemoved, buddylist);
- var onContactUpdated = _.bind(buddylist.onContactUpdated, buddylist);
api.e.on("received.userleftorjoined", function(event, dataType, data) {
if (dataType === "Left") {
onLeft(data);
diff --git a/static/js/directives/buddypicturecapture.js b/static/js/directives/buddypicturecapture.js
index 73e1a865..87d44108 100644
--- a/static/js/directives/buddypicturecapture.js
+++ b/static/js/directives/buddypicturecapture.js
@@ -27,6 +27,17 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
var controller = ['$scope', 'safeApply', '$timeout', '$q', "mediaDevices", "userMedia", function($scope, safeApply, $timeout, $q, mediaDevices, userMedia) {
+ var localStream = null;
+ var delayToTakePicture = 3000;
+ var countDownFrom = 3;
+
+ var takePictureCountDown;
+ var writeVideoToCanvas;
+ var writePreviewPic;
+ var makePicture;
+ var videoStop;
+ var videoStart;
+
// Buddy picutre capture size.
$scope.captureSize = {
width: 128,
@@ -41,12 +52,8 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
$scope.canvasPic = null;
$scope.canvasPrev = null;
- var localStream = null;
- var delayToTakePicture = 3000;
- var countDownFrom = 3;
-
// Counts down from start to 1
- var takePictureCountDown = function(start, delayTotal) {
+ takePictureCountDown = function(start, delayTotal) {
$scope.countingDown = true;
$scope.countdown = {};
$scope.countdown.num = start;
@@ -63,7 +70,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}
};
- var writeVideoToCanvas = function(canvas) {
+ writeVideoToCanvas = function(canvas) {
var videoWidth = $scope.video.videoWidth;
var videoHeight = $scope.video.videoHeight;
@@ -89,12 +96,12 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
};
- var writePreviewPic = function() {
+ writePreviewPic = function() {
writeVideoToCanvas($scope.canvasPrev);
$scope.preview = $scope.canvasPrev.toDataURL("image/jpeg");
};
- var makePicture = function(stream, cntFrom, delayTotal) {
+ makePicture = function(stream, cntFrom, delayTotal) {
takePictureCountDown(cntFrom, delayTotal);
$timeout(function() {
$scope.flash.addClass("flash");
@@ -107,7 +114,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}, delayTotal);
};
- var videoStop = function(stream, video) {
+ videoStop = function(stream, video) {
if (stream) {
video.pause();
userMedia.stopUserMediaStream(stream);
@@ -115,7 +122,7 @@ define(['jquery', 'underscore', 'text!partials/buddypicturecapture.html'], funct
}
};
- var videoStart = function() {
+ videoStart = function() {
$scope.waitingForPermission = true;
var videoConstraints = true;
var videoAllowed = $q.defer();
diff --git a/static/js/directives/buddypictureupload.js b/static/js/directives/buddypictureupload.js
index 65533ace..c7ec049e 100644
--- a/static/js/directives/buddypictureupload.js
+++ b/static/js/directives/buddypictureupload.js
@@ -39,8 +39,16 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
var previewWidth = 205;
var previewHeight = 205;
- $scope.maxUploadMb = 8;
- var maxUploadBytes = $scope.maxUploadMb * 1024 * 1024;
+ var maxUploadBytes = 8388608; // 8MB
+
+ var completedUpload;
+ var setUploadImageDimension;
+ var getAutoFitDimensions;
+ var getScaledDimensions;
+ var writePictureToCanvas;
+ var clearPicture;
+
+ $scope.maxUploadMb = maxUploadBytes / 1024 / 1024;
$scope.showUploadPicture = false;
$scope.previewUpload = false;
$scope.imgData = null;
@@ -54,11 +62,11 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
$scope.aspectRatio = 1;
- var completedUpload = function() {
+ completedUpload = function() {
$scope.upload.status = 100;
};
- var setUploadImageDimension = function(data) {
+ setUploadImageDimension = function(data) {
$scope.prevImage.onload = function() {
// clear old dimensions
this.style.cssText = null;
@@ -76,7 +84,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
// Auto fit by smallest dimension
- var getAutoFitDimensions = function(from, to) {
+ getAutoFitDimensions = function(from, to) {
if (!from.width && !from.height && !to.width && !to.height) {
return null;
}
@@ -94,7 +102,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
};
// (image, canvas) -> object
- var getScaledDimensions = function(from, to) {
+ getScaledDimensions = function(from, to) {
if (!from.style.width && !from.style.height && !to.width && !to.height) {
return null;
}
@@ -120,7 +128,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
return {width: width, height: height, x: x, y: y};
};
- var writePictureToCanvas = function(canvas) {
+ writePictureToCanvas = function(canvas) {
var img = $scope.prevImage;
var dim = getScaledDimensions(img, canvas);
var context = canvas.getContext("2d");
@@ -129,7 +137,7 @@ define(['jquery', 'underscore', 'text!partials/buddypictureupload.html'], functi
//console.log('writeUploadToCanvas', dim);
};
- var clearPicture = function() {
+ clearPicture = function() {
$(".file-input-name").empty();
$scope.imgData = null;
$scope.prevImage.src = "";
diff --git a/static/js/directives/chat.js b/static/js/directives/chat.js
index d764b09e..1da17e69 100644
--- a/static/js/directives/chat.js
+++ b/static/js/directives/chat.js
@@ -44,6 +44,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
$scope.currentRoom = null;
$scope.currentRoomActive = false;
$scope.maxMessageSize = maxMessageSize;
+ $scope.autoFocusDisabled = false;
$scope.getVisibleRooms = function() {
var res = [];
@@ -415,11 +416,6 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
pane.append(clonedElement);
$scope.element = clonedElement;
$scope.visible = true;
- if (options.autofocus) {
- _.defer(function() {
- $scope.$broadcast("focus");
- });
- }
var sendFiles = function(files) {
_.each(files, function(f) {
@@ -461,18 +457,16 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
subscope.enabled = true;
}
}
- if (options.autofocus && subscope.visible) {
- subscope.$broadcast("focus");
- }
}
if (!options.noactivate) {
- scope.activateRoom(subscope.id, true);
+ scope.activateRoom(subscope.id, true, !!options.autofocus);
}
if (options.restore && !options.noenable) {
if (!scope.layout.chat) {
+ scope.autoFocusDisabled = true;
scope.layout.chat = true;
}
}
@@ -524,7 +518,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
scope.layout.chatMaximized = !scope.layout.chatMaximized;
};
- scope.activateRoom = function(id, active) {
+ scope.activateRoom = function(id, active, autofocus) {
var subscope = controller.rooms[id];
if (!subscope) {
return;
@@ -555,6 +549,13 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
if (flip) {
pane.toggleClass("flip");
}
+ if (active && autofocus && !scope.autoFocusDisabled) {
+ _.defer(function() {
+ if (scope.layout.chat) {
+ subscope.$broadcast("focus");
+ }
+ });
+ }
};
scope.deactivateRoom = function() {
@@ -566,13 +567,22 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro
pane.removeClass("flip");
}
scope.layout.chatMaximized = false;
+ if (chat) {
+ if (!scope.autoFocusDisabled) {
+ if (scope.currentRoom && scope.currentRoom.active) {
+ scope.activateRoom(scope.currentRoom.id, true, true);
+ }
+ } else {
+ scope.autoFocusDisabled = false;
+ }
+ }
});
scope.$on("room.updated", function(event, room) {
var subscope = scope.showGroupRoom(null, {
restore: true,
noenable: true,
- noactivate: true
+ noactivate: !!scope.currentRoomActive
});
if (scope.currentRoomName != room.Name) {
var msg = $("").text(translation._("You are now in room %s ...", room.Name));
diff --git a/static/js/directives/youtubevideo.js b/static/js/directives/youtubevideo.js
index 90d79f03..7f1d6dcf 100644
--- a/static/js/directives/youtubevideo.js
+++ b/static/js/directives/youtubevideo.js
@@ -106,6 +106,16 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
var initialState = null;
var sandboxApi = null;
+ var peers = {};
+ var youtubevideos = [];
+ var youtubevideoCount = 0;
+ var currentToken = null;
+ var tokenHandler = null;
+
+ var mediaStreamSendYouTubeVideo;
+ var connector;
+ var updater;
+
var createSandboxApi = function(force, template) {
if (sandboxApi && force) {
sandboxApi.destroy();
@@ -475,13 +485,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
}
});
- var peers = {};
- var youtubevideos = [];
- var youtubevideoCount = 0;
- var currentToken = null;
- var tokenHandler = null;
-
- var mediaStreamSendYouTubeVideo = function(peercall, token, params) {
+ mediaStreamSendYouTubeVideo = function(peercall, token, params) {
mediaStream.api.apply("sendYouTubeVideo", {
send: function(type, data) {
if (!peercall.peerconnection.datachannelReady) {
@@ -495,7 +499,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
})(peercall.id, token, params);
};
- var connector = function(token, peercall) {
+ connector = function(token, peercall) {
if (peers.hasOwnProperty(peercall.id)) {
// Already got a connection.
return;
@@ -522,7 +526,7 @@ define(['require', 'jquery', 'underscore', 'moment', 'text!partials/youtubevideo
};
// Updater function to bring in new calls.
- var updater = function(event, state, currentcall) {
+ updater = function(event, state, currentcall) {
switch (state) {
case "completed":
case "connected":
diff --git a/static/js/libs/webrtc.adapter.js b/static/js/libs/webrtc.adapter.js
index 4ab95c73..d79beb48 100644
--- a/static/js/libs/webrtc.adapter.js
+++ b/static/js/libs/webrtc.adapter.js
@@ -30,6 +30,8 @@ THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+'use strict';
+
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
@@ -39,24 +41,79 @@ var webrtcMinimumVersion = null;
var webrtcUtils = {
log: function() {
// suppress console.log output when being included as a module.
- if (!(typeof module !== 'undefined' ||
- typeof require === 'function') && (typeof define === 'function')) {
- console.log.apply(console, arguments);
+ if (typeof module !== 'undefined' ||
+ typeof require === 'function' && typeof define === 'function') {
+ return;
}
+ console.log.apply(console, arguments);
+ },
+ extractVersion: function(uastring, expr, pos) {
+ var match = uastring.match(expr);
+ return match && match.length >= pos && parseInt(match[pos], 10);
+ }
+};
+
+/*
+function trace(text) {
+ // This function is used for logging.
+ if (text[text.length - 1] === '\n') {
+ text = text.substring(0, text.length - 1);
+ }
+ if (window.performance) {
+ var now = (window.performance.now() / 1000).toFixed(3);
+ webrtcUtils.log(now + ': ' + text);
+ } else {
+ webrtcUtils.log(text);
+ }
+}
+*/
+
+if (typeof window === 'object') {
+ if (window.HTMLMediaElement &&
+ !('srcObject' in window.HTMLMediaElement.prototype)) {
+ // Shim the srcObject property, once, when HTMLMediaElement is found.
+ Object.defineProperty(window.HTMLMediaElement.prototype, 'srcObject', {
+ get: function() {
+ // If prefixed srcObject property exists, return it.
+ // Otherwise use the shimmed property, _srcObject
+ return 'mozSrcObject' in this ? this.mozSrcObject : this._srcObject;
+ },
+ set: function(stream) {
+ if ('mozSrcObject' in this) {
+ this.mozSrcObject = stream;
+ } else {
+ // Use _srcObject as a private property for this shim
+ this._srcObject = stream;
+ // TODO: revokeObjectUrl(this.src) when !stream to release resources?
+ this.src = URL.createObjectURL(stream);
+ }
+ }
+ });
}
+ // Proxy existing globals
+ getUserMedia = window.navigator && window.navigator.getUserMedia;
+}
+
+// Attach a media stream to an element.
+attachMediaStream = function(element, stream) {
+ element.srcObject = stream;
+};
+
+reattachMediaStream = function(to, from) {
+ to.srcObject = from.srcObject;
};
if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('This does not appear to be a browser');
webrtcDetectedBrowser = 'not a browser';
-} else if (navigator.mozGetUserMedia) {
+} else if (navigator.mozGetUserMedia && window.mozRTCPeerConnection) {
webrtcUtils.log('This appears to be Firefox');
webrtcDetectedBrowser = 'firefox';
// the detected firefox version.
- webrtcDetectedVersion =
- parseInt(navigator.userAgent.match(/Firefox\/([0-9]+)\./)[1], 10);
+ webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
+ /Firefox\/([0-9]+)\./, 1);
// the minimum firefox version still supported by adapter.
webrtcMinimumVersion = 31;
@@ -88,14 +145,18 @@ if (typeof window === 'undefined' || !window.navigator) {
pcConfig.iceServers = newIceServers;
}
}
- return new mozRTCPeerConnection(pcConfig, pcConstraints);
+ return new mozRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
};
// The RTCSessionDescription object.
- window.RTCSessionDescription = mozRTCSessionDescription;
+ if (!window.RTCSessionDescription) {
+ window.RTCSessionDescription = mozRTCSessionDescription;
+ }
// The RTCIceCandidate object.
- window.RTCIceCandidate = mozRTCIceCandidate;
+ if (!window.RTCIceCandidate) {
+ window.RTCIceCandidate = mozRTCIceCandidate;
+ }
// getUserMedia constraints shim.
getUserMedia = function(constraints, onSuccess, onError) {
@@ -168,8 +229,8 @@ if (typeof window === 'undefined' || !window.navigator) {
navigator.mediaDevices.enumerateDevices || function() {
return new Promise(function(resolve) {
var infos = [
- {kind: 'audioinput', deviceId: 'default', label:'', groupId:''},
- {kind: 'videoinput', deviceId: 'default', label:'', groupId:''}
+ {kind: 'audioinput', deviceId: 'default', label: '', groupId: ''},
+ {kind: 'videoinput', deviceId: 'default', label: '', groupId: ''}
];
resolve(infos);
});
@@ -180,7 +241,7 @@ if (typeof window === 'undefined' || !window.navigator) {
var orgEnumerateDevices =
navigator.mediaDevices.enumerateDevices.bind(navigator.mediaDevices);
navigator.mediaDevices.enumerateDevices = function() {
- return orgEnumerateDevices().catch(function(e) {
+ return orgEnumerateDevices().then(undefined, function(e) {
if (e.name === 'NotFoundError') {
return [];
}
@@ -188,30 +249,27 @@ if (typeof window === 'undefined' || !window.navigator) {
});
};
}
- // Attach a media stream to an element.
- attachMediaStream = function(element, stream) {
- element.mozSrcObject = stream;
- };
-
- reattachMediaStream = function(to, from) {
- to.mozSrcObject = from.mozSrcObject;
- };
-
-} else if (navigator.webkitGetUserMedia) {
+} else if (navigator.webkitGetUserMedia && window.webkitRTCPeerConnection) {
webrtcUtils.log('This appears to be Chrome');
webrtcDetectedBrowser = 'chrome';
// the detected chrome version.
- webrtcDetectedVersion =
- parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2], 10);
+ webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
+ /Chrom(e|ium)\/([0-9]+)\./, 2);
// the minimum chrome version still supported by adapter.
webrtcMinimumVersion = 38;
// The RTCPeerConnection object.
window.RTCPeerConnection = function(pcConfig, pcConstraints) {
- var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints);
+ // Translate iceTransportPolicy to iceTransports,
+ // see https://code.google.com/p/webrtc/issues/detail?id=4869
+ if (pcConfig && pcConfig.iceTransportPolicy) {
+ pcConfig.iceTransports = pcConfig.iceTransportPolicy;
+ }
+
+ var pc = new webkitRTCPeerConnection(pcConfig, pcConstraints); // jscs:ignore requireCapitalizedConstructors
var origGetStats = pc.getStats.bind(pc);
pc.getStats = function(selector, successCallback, errorCallback) { // jshint ignore: line
var self = this;
@@ -251,7 +309,14 @@ if (typeof window === 'undefined' || !window.navigator) {
// promise-support
return new Promise(function(resolve, reject) {
- origGetStats.apply(self, [resolve, reject]);
+ if (args.length === 1 && selector === null) {
+ origGetStats.apply(self, [
+ function(response) {
+ resolve.apply(null, [fixChromeStats(response)]);
+ }, reject]);
+ } else {
+ origGetStats.apply(self, [resolve, reject]);
+ }
});
};
@@ -417,7 +482,7 @@ if (typeof window === 'undefined' || !window.navigator) {
// Attach a media stream to an element.
attachMediaStream = function(element, stream) {
- if (typeof element.srcObject !== 'undefined') {
+ if (webrtcDetectedVersion >= 43) {
element.srcObject = stream;
} else if (typeof element.src !== 'undefined') {
element.src = URL.createObjectURL(stream);
@@ -425,9 +490,12 @@ if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('Error attaching stream to element.');
}
};
-
reattachMediaStream = function(to, from) {
- to.src = from.src;
+ if (webrtcDetectedVersion >= 43) {
+ to.srcObject = from.srcObject;
+ } else {
+ to.src = from.src;
+ }
};
} else if (navigator.mediaDevices && navigator.userAgent.match(
@@ -435,20 +503,11 @@ if (typeof window === 'undefined' || !window.navigator) {
webrtcUtils.log('This appears to be Edge');
webrtcDetectedBrowser = 'edge';
- webrtcDetectedVersion =
- parseInt(navigator.userAgent.match(/Edge\/(\d+).(\d+)$/)[2], 10);
+ webrtcDetectedVersion = webrtcUtils.extractVersion(navigator.userAgent,
+ /Edge\/(\d+).(\d+)$/, 2);
// the minimum version still supported by adapter.
webrtcMinimumVersion = 12;
-
- getUserMedia = navigator.getUserMedia;
-
- attachMediaStream = function(element, stream) {
- element.srcObject = stream;
- };
- reattachMediaStream = function(to, from) {
- to.srcObject = from.srcObject;
- };
} else {
webrtcUtils.log('Browser does not appear to be WebRTC-capable');
}
@@ -461,26 +520,35 @@ function requestUserMedia(constraints) {
}
var webrtcTesting = {};
-Object.defineProperty(webrtcTesting, 'version', {
- set: function(version) {
- webrtcDetectedVersion = version;
- }
-});
+try {
+ Object.defineProperty(webrtcTesting, 'version', {
+ set: function(version) {
+ webrtcDetectedVersion = version;
+ }
+ });
+} catch (e) {}
if (typeof module !== 'undefined') {
var RTCPeerConnection;
+ var RTCIceCandidate;
+ var RTCSessionDescription;
if (typeof window !== 'undefined') {
RTCPeerConnection = window.RTCPeerConnection;
+ RTCIceCandidate = window.RTCIceCandidate;
+ RTCSessionDescription = window.RTCSessionDescription;
}
module.exports = {
RTCPeerConnection: RTCPeerConnection,
+ RTCIceCandidate: RTCIceCandidate,
+ RTCSessionDescription: RTCSessionDescription,
getUserMedia: getUserMedia,
attachMediaStream: attachMediaStream,
reattachMediaStream: reattachMediaStream,
webrtcDetectedBrowser: webrtcDetectedBrowser,
webrtcDetectedVersion: webrtcDetectedVersion,
webrtcMinimumVersion: webrtcMinimumVersion,
- webrtcTesting: webrtcTesting
+ webrtcTesting: webrtcTesting,
+ webrtcUtils: webrtcUtils
//requestUserMedia: not exposed on purpose.
//trace: not exposed on purpose.
};
@@ -489,13 +557,16 @@ if (typeof module !== 'undefined') {
define([], function() {
return {
RTCPeerConnection: window.RTCPeerConnection,
+ RTCIceCandidate: window.RTCIceCandidate,
+ RTCSessionDescription: window.RTCSessionDescription,
getUserMedia: getUserMedia,
attachMediaStream: attachMediaStream,
reattachMediaStream: reattachMediaStream,
webrtcDetectedBrowser: webrtcDetectedBrowser,
webrtcDetectedVersion: webrtcDetectedVersion,
webrtcMinimumVersion: webrtcMinimumVersion,
- webrtcTesting: webrtcTesting
+ webrtcTesting: webrtcTesting,
+ webrtcUtils: webrtcUtils
//requestUserMedia: not exposed on purpose.
//trace: not exposed on purpose.
};
diff --git a/static/js/main.js b/static/js/main.js
index 10371c04..1f347627 100644
--- a/static/js/main.js
+++ b/static/js/main.js
@@ -181,8 +181,8 @@ if (Object.create) {
custom: {
families: ["FontAwesome"],
testStrings: {
- "FontAwesome": '\uf004\uf005'
- }
+ "FontAwesome": '\uf004\uf005'
+ }
},
active: function() {
console.log("Web fonts loaded.");
diff --git a/static/js/mediastream/peercall.js b/static/js/mediastream/peercall.js
index fe4a55d0..a1a26f84 100644
--- a/static/js/mediastream/peercall.js
+++ b/static/js/mediastream/peercall.js
@@ -34,9 +34,8 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
this.mediaConstraints = $.extend(true, {}, this.webrtc.settings.mediaConstraints);
this.pcConfig = $.extend(true, {}, this.webrtc.settings.pcConfig);
this.pcConstraints = $.extend(true, {}, this.webrtc.settings.pcConstraints);
- this.sdpConstraints = $.extend(true, {}, this.webrtc.settings.sdpConstraints);
- this.offerConstraints = $.extend(true, {}, this.webrtc.settings.offerConstraints);
this.sdpParams = $.extend(true, {}, this.webrtc.settings.sdpParams);
+ this.offerOptions = $.extend(true, {}, this.webrtc.settings.offerOptions);
this.peerconnection = null;
this.datachannels = {};
@@ -69,17 +68,17 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
PeerCall.prototype.createOffer = function(cb) {
- var constraints = utils.mergeConstraints(this.offerConstraints, this.sdpConstraints);
- console.log('Creating offer with constraints: \n' +
- ' \'' + JSON.stringify(constraints, null, '\t') + '\'.', this.negotiationNeeded);
- this.peerconnection.createOffer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), constraints);
+ var options = this.offerOptions;
+ console.log('Creating offer with options: \n' +
+ ' \'' + JSON.stringify(options, null, '\t') + '\'.', this.negotiationNeeded);
+ this.peerconnection.createOffer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), options);
};
PeerCall.prototype.createAnswer = function(cb) {
console.log("Creating answer.", this.negotiationNeeded);
- this.peerconnection.createAnswer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this), this.peerconnection.sdpConstraints);
+ this.peerconnection.createAnswer(_.bind(this.onCreateAnswerOffer, this, cb), _.bind(this.onErrorAnswerOffer, this));
};
@@ -151,7 +150,7 @@ define(['jquery', 'underscore', 'mediastream/utils', 'mediastream/peerconnection
streams++;
}
}, this));
- if (streams === 0 && this.sdpConstraints.mandatory && (this.sdpConstraints.mandatory.OfferToReceiveAudio || this.sdpConstraints.mandatory.OfferToReceiveVideo)) {
+ if (streams === 0 && (this.offerOptions.offerToReceiveAudio || this.offerOptions.offerToReceiveVideo)) {
// We assume that we will eventually receive a stream, so we trigger the event to let the UI prepare for it.
this.e.triggerHandler("remoteStreamAdded", [null, this]);
}
diff --git a/static/js/mediastream/peerscreenshare.js b/static/js/mediastream/peerscreenshare.js
index 63df53a8..5673ef74 100644
--- a/static/js/mediastream/peerscreenshare.js
+++ b/static/js/mediastream/peerscreenshare.js
@@ -23,6 +23,7 @@
define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], function($, _, PeerCall, tokens) {
var screenshareIds = 0;
+ var PeerScreenshare;
// Register ourselves for tokens.
tokens.registerHandler("screenshare", function(webrtc, id, token, from) {
@@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
});
// PeerScreenshare inherits from PeerCall.
- var PeerScreenshare = function(webrtc, id, token, to) {
+ PeerScreenshare = function(webrtc, id, token, to) {
if (id === null) {
id = screenshareIds++;
@@ -50,9 +51,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
audio: false,
video: false
}
- this.sdpConstraints.mandatory.OfferToReceiveAudio = false;
- this.sdpConstraints.mandatory.OfferToReceiveVideo = true;
-
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
@@ -60,6 +58,8 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens'], f
mandatory: {},
optional: []
};
+ this.offerOptions.offerToReceiveAudio = false;
+ this.offerOptions.offerToReceiveVideo = true;
// Inject token into sessiondescription and ice candidate data.
this.e.on("sessiondescription icecandidate", _.bind(function(event, data) {
diff --git a/static/js/mediastream/peerxfer.js b/static/js/mediastream/peerxfer.js
index bba8d6e7..2867a312 100644
--- a/static/js/mediastream/peerxfer.js
+++ b/static/js/mediastream/peerxfer.js
@@ -23,6 +23,7 @@
define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'webrtc.adapter'], function($, _, PeerCall, tokens) {
var xfersIds = 0;
+ var PeerXfer;
// Register ourselves for tokens.
tokens.registerHandler("xfer", function(webrtc, id, token, from) {
@@ -32,7 +33,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
});
// PeerXfer inherits from PeerCall.
- var PeerXfer = function(webrtc, id, token, to) {
+ PeerXfer = function(webrtc, id, token, to) {
if (id === null) {
id = xfersIds++;
@@ -48,10 +49,6 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
audio: false,
video: false
};
- this.sdpConstraints = {
- mandatory: {},
- optional: []
- };
// SCTP is supported from Chrome M31.
// No need to pass DTLS constraint as it is on by default in Chrome M31.
// For SCTP, reliable and ordered is true by default.
@@ -59,6 +56,7 @@ define(['jquery', 'underscore', 'mediastream/peercall', 'mediastream/tokens', 'w
mandatory: {},
optional: []
};
+ this.offerOptions = {};
// Inject token into sessiondescription and ice candidate data.
this.e.on("sessiondescription icecandidate", _.bind(function(event, data) {
diff --git a/static/js/mediastream/tokens.js b/static/js/mediastream/tokens.js
index bf3dc98d..600be142 100644
--- a/static/js/mediastream/tokens.js
+++ b/static/js/mediastream/tokens.js
@@ -22,6 +22,8 @@
"use strict";
define(['jquery', 'underscore'], function($, _) {
+ var tokens;
+
var Token = function(handlerKey) {
this.e = $({});
this.count = 0;
@@ -179,7 +181,7 @@ define(['jquery', 'underscore'], function($, _) {
};
- var tokens = new Tokens();
+ tokens = new Tokens();
return tokens;
});
diff --git a/static/js/mediastream/utils.js b/static/js/mediastream/utils.js
index d5bd62b1..8872b90a 100644
--- a/static/js/mediastream/utils.js
+++ b/static/js/mediastream/utils.js
@@ -41,6 +41,7 @@
"use strict";
define([], function() {
+ /*jshint strict: true, latedef: false */
function trace(text) {
// noop
@@ -232,7 +233,7 @@ define([], function() {
// The format of |codec| is 'NAME/RATE', e.g. 'opus/48000'.
function maybePreferCodec(sdp, type, dir, codec) {
var str = type + ' ' + dir + ' codec';
- if (codec === '') {
+ if (!codec) {
trace('No preference on ' + str + '.');
return sdp;
}
diff --git a/static/js/mediastream/webrtc.js b/static/js/mediastream/webrtc.js
index ed8e77c5..5ac1185e 100644
--- a/static/js/mediastream/webrtc.js
+++ b/static/js/mediastream/webrtc.js
@@ -80,18 +80,6 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
mandatory: {},
optional: []
},
- // Set up audio and video regardless of what devices are present.
- sdpConstraints: {
- mandatory: {
- OfferToReceiveAudio: true,
- OfferToReceiveVideo: true
- },
- optional: []
- },
- offerConstraints: {
- mandatory: {},
- optional: []
- },
screensharing: {
mediaConstraints: {
audio: false,
@@ -115,6 +103,11 @@ function($, _, PeerCall, PeerConference, PeerXfer, PeerScreenshare, UserMedia, u
//videoRecvBitrate: ,
//videoRecvCodec
},
+ // Set up audio and video regardless of what devices are present.
+ offerOptions: {
+ offerToReceiveAudio: true,
+ offerToReceiveVideo: true
+ },
renegotiation: true
};
diff --git a/static/js/services/alertify.js b/static/js/services/alertify.js
index cbf7c32a..f00e1c67 100644
--- a/static/js/services/alertify.js
+++ b/static/js/services/alertify.js
@@ -108,7 +108,7 @@ define(["angular"], function(angular) {
if (!conf ||
conf && !conf.type ||
conf && !conf.baseType) {
- throw Error("Custom template not configured correctly.");
+ throw new Error("Custom template not configured correctly.");
}
var templateUrl = '/dialogs/' + conf.type + '.html';
if (conf.template) {
diff --git a/static/js/services/animationframe.js b/static/js/services/animationframe.js
index 228b834b..71651e57 100644
--- a/static/js/services/animationframe.js
+++ b/static/js/services/animationframe.js
@@ -28,20 +28,26 @@ define(["underscore", "rAF"], function(_) {
var requestAnimationFrame = $window.requestAnimationFrame;
var registry = [];
- var caller = function(f) {
+ var caller;
+ var runner;
+ var timer;
+ var worker;
+ var animationFrame;
+
+ caller = function(f) {
f();
};
- var runner = function(c) {
+ runner = function(c) {
registry.forEach(caller);
requestAnimationFrame(worker)
}
- var timer = $window.setTimeout;
- var worker = function() {
+ timer = $window.setTimeout;
+ worker = function() {
timer(runner, 100);
};
// Public api.
- var animationFrame = {
+ animationFrame = {
register: function(f) {
registry.push(f);
}
diff --git a/static/js/services/desktopnotify.js b/static/js/services/desktopnotify.js
index 706ba8d5..a2d70cfe 100644
--- a/static/js/services/desktopnotify.js
+++ b/static/js/services/desktopnotify.js
@@ -74,7 +74,7 @@ define(['jquery', 'underscore', 'desktop-notify', 'webrtc.adapter'], function($,
// on Android, where Notifications raise an exception.
// See https://code.google.com/p/chromium/issues/detail?id=481856
try {
- /*jshint nonew: false */
+ /*jshint strict: true, nonew: false */
new $window.Notification('');
} catch(e) {
if (e.name == 'TypeError') {
diff --git a/static/js/services/filedownload.js b/static/js/services/filedownload.js
index 9bcd167d..9e36eecb 100644
--- a/static/js/services/filedownload.js
+++ b/static/js/services/filedownload.js
@@ -26,8 +26,9 @@ define(["jquery", "underscore"], function($, _) {
var downloads = 0;
- var Session = function(id, token, scope) {
+ var Session = function(fileDownload, id, token, scope) {
+ this.fileDownload = fileDownload;
this.id = id;
this.token = token;
this.scope = scope;
@@ -175,7 +176,7 @@ define(["jquery", "underscore"], function($, _) {
session.done(this);
return;
}
- fileDownload.sendRequest(xfer, this.chunk++);
+ session.fileDownload.sendRequest(xfer, this.chunk++);
}, job);
//console.log("Starting new job", job, this.fragments, xfer.id);
xfer.e.on("sessionData", _.bind(this.handleData, this, job));
@@ -287,7 +288,7 @@ define(["jquery", "underscore"], function($, _) {
FileDownload.prototype.createSession = function(scope, token) {
var id = Session.makeId(token, this.downloads++);
- var session = this.sessions[id] = new Session(id, token, scope);
+ var session = this.sessions[id] = new Session(this, id, token, scope);
//console.log("Created new file download session", id, session);
return session;
};
@@ -330,11 +331,7 @@ define(["jquery", "underscore"], function($, _) {
};
-
- // Create signleton.
- var fileDownload = new FileDownload();
-
- return fileDownload;
+ return new FileDownload();
}];
diff --git a/static/js/services/geolocation.js b/static/js/services/geolocation.js
index 5eb7fe19..a9e7ed55 100644
--- a/static/js/services/geolocation.js
+++ b/static/js/services/geolocation.js
@@ -29,8 +29,8 @@ define(['underscore', 'modernizr'], function(_, Modernizr) {
var defaults = {
enableHighAccuracy: true,
- timeout: 5000,
- maximumAge: 0
+ timeout: 5000,
+ maximumAge: 0
};
return {
diff --git a/static/js/services/mediadevices.js b/static/js/services/mediadevices.js
index e11c9fce..352b54ba 100644
--- a/static/js/services/mediadevices.js
+++ b/static/js/services/mediadevices.js
@@ -19,44 +19,12 @@
*
*/
-/* global Promise */
"use strict";
define(['webrtc.adapter'], function() {
// mediaDevices
return ["$window", function($window) {
-
- var mediaDevices = $window.navigator.mediaDevices || {};
- var getUserMedia = (function() {
- // Implement a Promise based wrapper around getUserMedia.
- if (mediaDevices.getUserMedia) {
- // mediaDevices calls return Promise native.
- return mediaDevices.getUserMedia.bind(mediaDevices);
- } else {
- return function getUserMedia(constraints) {
- return new Promise(function(resolve, reject) {
- var onSuccess = function(stream) {
- resolve(stream)
- };
- var onError = function(error) {
- reject(error);
- };
- try {
- $window.getUserMedia(constraints, onSuccess, onError);
- } catch(err) {
- onError(err);
- }
- });
- }
- }
- })();
-
- // Public api.
- return {
- shim: mediaDevices.getUserMedia ? false : true,
- getUserMedia: getUserMedia
- }
-
+ return $window.navigator.mediaDevices;
}];
});
\ No newline at end of file
diff --git a/static/js/services/mediasources.js b/static/js/services/mediasources.js
index 22172219..7e5123e2 100644
--- a/static/js/services/mediasources.js
+++ b/static/js/services/mediasources.js
@@ -20,13 +20,14 @@
*/
"use strict";
-define(['jquery', 'underscore'], function($, _) {
+define(['jquery', 'underscore', 'webrtc.adapter'], function($, _, adapter) {
- return ["$window", function($window) {
+ return ["$window", "mediaDevices", function($window, mediaDevices) {
var MediaSources = function() {
- this.supported = $window.MediaStreamTrack && $window.MediaStreamTrack.getSources
+ // For now enable media sources only in Chrome until other browsers have some use for it.
+ this.supported = $window.navigator.mediaDevices.enumerateDevices && adapter.webrtcDetectedBrowser === "chrome";
this.audio = [];
this.video = [];
@@ -57,25 +58,29 @@ define(['jquery', 'underscore'], function($, _) {
MediaSources.prototype._refresh = function(cb) {
- $window.MediaStreamTrack.getSources(_.bind(function(sources) {
+ mediaDevices.enumerateDevices().then(_.bind(function(devices) {
var audio = this.audio = [];
var video = this.video = [];
- _.each(sources, function(source) {
+ _.each(devices, function(device) {
var o = {
- id: source.id,
- facing: source.facing
- };
- if (source.kind === "audio") {
- o.label = source.label ? source.label : "Microphone " + (audio.length + 1);
+ id: device.deviceId,
+ }
+ if (device.kind === "audioinput") {
+ o.label = device.label ? device.label : "Microphone " + (audio.length + 1);
audio.push(o);
- } else if (source.kind === "video") {
- o.label = source.label ? source.label : "Camera " + (video.length + 1);
+ } else if (device.kind === "videoinput") {
+ o.label = device.label ? device.label : "Camera " + (video.length + 1);
video.push(o);
}
});
if (cb) {
cb(audio, video);
}
+ }, this), _.bind(function(error) {
+ console.error("failed to get media devices: " + error);
+ if (cb) {
+ cb([], []);
+ }
}, this));
};
diff --git a/static/js/services/mediastream.js b/static/js/services/mediastream.js
index a65426a5..5df9edd2 100644
--- a/static/js/services/mediastream.js
+++ b/static/js/services/mediastream.js
@@ -252,8 +252,9 @@ define([
}, 1000);
if (context.Cfg.Tokens) {
+ var prompt, check;
var storedCode = localStorage.getItem("mediastream-access-code");
- var prompt = function() {
+ prompt = function() {
alertify.dialog.prompt(translation._("Access code required"), function(code) {
if (!code) {
prompt();
@@ -264,7 +265,7 @@ define([
}, prompt);
};
var url = restURL.api("tokens");
- var check = function(code) {
+ check = function(code) {
$http({
method: "POST",
url: url,
diff --git a/static/js/services/rooms.js b/static/js/services/rooms.js
index 93c9b0fb..b5a02514 100644
--- a/static/js/services/rooms.js
+++ b/static/js/services/rooms.js
@@ -37,7 +37,14 @@ define([
var canJoinRooms = !mediaStream.config.AuthorizeRoomJoin;
var canCreateRooms = canJoinRooms ? !mediaStream.config.AuthorizeRoomCreation : false;
- var joinFailed = function(error) {
+ var rooms;
+ var joinFailed;
+ var joinRequestedRoom;
+ var setCurrentRoom;
+ var updateRoom;
+ var applyRoomUpdate;
+
+ joinFailed = function(error) {
setCurrentRoom(null);
switch(error.Code) {
@@ -70,7 +77,7 @@ define([
}
};
- var joinRequestedRoom = function() {
+ joinRequestedRoom = function() {
if (!connector.connected || appData.authorizing()) {
// Do nothing while not connected or authorizing.
return;
@@ -95,7 +102,7 @@ define([
}
};
- var setCurrentRoom = function(room) {
+ setCurrentRoom = function(room) {
if (room === currentRoom) {
return;
}
@@ -112,13 +119,13 @@ define([
}
};
- var updateRoom = function(room) {
+ updateRoom = function(room) {
var response = $q.defer();
api.requestRoomUpdate(room, response.resolve, response.reject);
return response.promise.then(applyRoomUpdate);
};
- var applyRoomUpdate = function(room) {
+ applyRoomUpdate = function(room) {
if (room.Credentials) {
roompin.update(currentRoom.Name, room.Credentials.PIN);
delete room.Credentials;
@@ -169,7 +176,8 @@ define([
}
});
- var rooms = {
+ // Public API.
+ rooms = {
inDefaultRoom: function() {
return (currentRoom !== null ? currentRoom.Name : requestedRoomName) === "";
},
diff --git a/static/partials/chat.html b/static/partials/chat.html
index 0493b4b5..5e7a2630 100644
--- a/static/partials/chat.html
+++ b/static/partials/chat.html
@@ -5,7 +5,7 @@