From 689e2e0c15ff4a73a78c8d413ed3a0c4fc7d5414 Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 11 Aug 2015 22:43:06 +0200 Subject: [PATCH 01/19] Fix mixed tabs/spaces. --- static/js/main.js | 4 ++-- static/js/services/desktopnotify.js | 4 ++-- static/js/services/geolocation.js | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) 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/services/desktopnotify.js b/static/js/services/desktopnotify.js index 5484e720..d133dfa6 100644 --- a/static/js/services/desktopnotify.js +++ b/static/js/services/desktopnotify.js @@ -29,8 +29,8 @@ define(['jquery', 'underscore', 'desktop-notify'], function($, _, notify) { var iconElement = $("").addClass("desktopnotify-icon hidden"); iconElement.appendTo("body"); var url = iconElement.css('background-image'); - url = /^url\((['"]?)(.*)\1\)$/.exec(url); - url = url ? url[2] : ""; + url = /^url\((['"]?)(.*)\1\)$/.exec(url); + url = url ? url[2] : ""; iconElement.remove(); return url; }()); 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 { From 6cec7e88c420af6b3e1e94e09693141be343f85d Mon Sep 17 00:00:00 2001 From: Joachim Bauch Date: Tue, 11 Aug 2015 22:43:52 +0200 Subject: [PATCH 02/19] Invoke constructor with "new". --- static/js/services/alertify.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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) { From c20a819914d1c2008e946ba7bb7afe2b1a981ccb Mon Sep 17 00:00:00 2001 From: ava1ar Date: Mon, 17 Aug 2015 02:02:06 -0400 Subject: [PATCH 03/19] make install target now respect --- Makefile.am | 52 ++++++++++++++++++++++++++-------------------------- 1 file changed, 26 insertions(+), 26 deletions(-) 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 From e9a3a599e2c08f4317b591d5a5a9814b99f6ad6f Mon Sep 17 00:00:00 2001 From: Evan Theurer Date: Fri, 21 Aug 2015 17:25:54 +0200 Subject: [PATCH 04/19] Document how to enable javascript console logging. --- README.md | 3 +++ 1 file changed, 3 insertions(+) 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 From ef533d174e991dbfafd21c47759c150cbae6ca7e Mon Sep 17 00:00:00 2001 From: Evan Theurer Date: Thu, 1 Oct 2015 09:52:07 +0200 Subject: [PATCH 05/19] Autoprefixer moved to postcss-cli, limit version for now to keep autoprefixer binary. --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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" } From ef935fccd73550b659bd7ab883dd8b060d98076a Mon Sep 17 00:00:00 2001 From: Evan Theurer Date: Mon, 2 Nov 2015 11:39:17 +0100 Subject: [PATCH 06/19] Ensure that files and folders under static/js/libs/ are ignored by hound. --- .javascript_ignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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/ From a6ded93b2fd9f31188a7e9538b0efea3d7eeb4a4 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 15:15:04 +0100 Subject: [PATCH 07/19] Fixed jshint latedef and strict errors. --- src/hooks/pre-commit.hook | 3 +-- static/js/base.js | 1 + static/js/directives/buddylist.js | 18 ++++++++------ static/js/directives/buddypicturecapture.js | 27 +++++++++++++-------- static/js/directives/buddypictureupload.js | 24 ++++++++++++------ static/js/directives/youtubevideo.js | 22 ++++++++++------- static/js/mediastream/peerscreenshare.js | 3 ++- static/js/mediastream/peerxfer.js | 3 ++- static/js/mediastream/tokens.js | 4 ++- static/js/mediastream/utils.js | 1 + static/js/services/animationframe.js | 16 ++++++++---- static/js/services/desktopnotify.js | 2 +- static/js/services/filedownload.js | 13 ++++------ static/js/services/mediastream.js | 5 ++-- static/js/services/rooms.js | 20 ++++++++++----- 15 files changed, 100 insertions(+), 62 deletions(-) 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/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/mediastream/peerscreenshare.js b/static/js/mediastream/peerscreenshare.js index 63df53a8..97a0b49b 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++; diff --git a/static/js/mediastream/peerxfer.js b/static/js/mediastream/peerxfer.js index bba8d6e7..e19a5412 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++; 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..619151b9 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 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..d767b4c3 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++); + this.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/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) === ""; }, From bbd0b29ad7ae2efeccbccb9b940326bf32ad8405 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 15:28:45 +0100 Subject: [PATCH 08/19] Add Go 1.5. --- .travis.yml | 1 + 1 file changed, 1 insertion(+) 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: From f5a77ca0ba4e93cddec116cd54e4792265701d8b Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 16:10:38 +0100 Subject: [PATCH 09/19] Updated adapter.js to a0b40f20221c4633bd1e54e50255392c3459a6d9 --- static/js/libs/webrtc.adapter.js | 165 ++++++++++++++++++++++--------- 1 file changed, 118 insertions(+), 47 deletions(-) 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. }; From ce9f8f98741b6a23c5c898eeb3bf8b29ad29e689 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 17:18:36 +0100 Subject: [PATCH 10/19] Moved from offerConstraints to offerOptions which follows latest spec. This fixes offer creation in Firefox >=43. --- static/js/mediastream/peercall.js | 15 +++++++-------- static/js/mediastream/peerscreenshare.js | 5 ++--- static/js/mediastream/peerxfer.js | 5 +---- static/js/mediastream/webrtc.js | 17 +++++------------ 4 files changed, 15 insertions(+), 27 deletions(-) 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 97a0b49b..5673ef74 100644 --- a/static/js/mediastream/peerscreenshare.js +++ b/static/js/mediastream/peerscreenshare.js @@ -51,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. @@ -61,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 e19a5412..2867a312 100644 --- a/static/js/mediastream/peerxfer.js +++ b/static/js/mediastream/peerxfer.js @@ -49,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. @@ -60,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/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 }; From 61b17ecdf847fdb0d141c5464d03a7ce66eef716 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 17:24:05 +0100 Subject: [PATCH 11/19] Fixed scope regression after latedef fixes. --- static/js/services/filedownload.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/services/filedownload.js b/static/js/services/filedownload.js index d767b4c3..9e36eecb 100644 --- a/static/js/services/filedownload.js +++ b/static/js/services/filedownload.js @@ -176,7 +176,7 @@ define(["jquery", "underscore"], function($, _) { session.done(this); return; } - this.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)); From 72cf9797338957039ff0bac879d02cf0bf03524b Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 17:34:59 +0100 Subject: [PATCH 12/19] Force presentation canvas to white background, to properly show files which have no background. --- html/sandboxes/odfcanvas_sandbox.html | 1 + html/sandboxes/pdfcanvas_sandbox.html | 1 + 2 files changed, 2 insertions(+) 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; } From cbb2a18b36ec663cd232686c2a10aab3d51aa66e Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Mon, 4 Jan 2016 18:20:46 +0100 Subject: [PATCH 13/19] Added noreferrer rel to chat links. --- static/js/services/enrichmessage.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/services/enrichmessage.js b/static/js/services/enrichmessage.js index 379f0bd5..55866bab 100644 --- a/static/js/services/enrichmessage.js +++ b/static/js/services/enrichmessage.js @@ -29,7 +29,7 @@ define([], function() { var enrichMessage = { url: function(s) { s = linky(s); - s = s.replace(/ Date: Mon, 4 Jan 2016 18:46:10 +0100 Subject: [PATCH 14/19] Improved codec check to include undefined. --- static/js/mediastream/utils.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/mediastream/utils.js b/static/js/mediastream/utils.js index 619151b9..8872b90a 100644 --- a/static/js/mediastream/utils.js +++ b/static/js/mediastream/utils.js @@ -233,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; } From c5c62b3b0ce0750dbb9f38dd758bbcbe2c76b7d8 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Tue, 5 Jan 2016 10:26:20 +0100 Subject: [PATCH 15/19] Setting link-type noreferrer does not work, set global referrer-policy instead (see http://w3c.github.io/webappsec/specs/referrer-policy/). --- html/head.html | 1 + static/js/services/enrichmessage.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) 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/static/js/services/enrichmessage.js b/static/js/services/enrichmessage.js index 55866bab..379f0bd5 100644 --- a/static/js/services/enrichmessage.js +++ b/static/js/services/enrichmessage.js @@ -29,7 +29,7 @@ define([], function() { var enrichMessage = { url: function(s) { s = linky(s); - s = s.replace(/ Date: Tue, 5 Jan 2016 11:51:29 +0100 Subject: [PATCH 16/19] Use mediaDevices.enumerateDevices to retrieve media input devices. --- static/js/services/mediadevices.js | 34 +----------------------------- static/js/services/mediasources.js | 29 ++++++++++++++----------- 2 files changed, 18 insertions(+), 45 deletions(-) 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)); }; From d007b69c68f9c1b9ca4e6a1fc28f1b3cb53aa87f Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Tue, 5 Jan 2016 12:32:09 +0100 Subject: [PATCH 17/19] Automatically focus chat input when activating a room, implementing a part of #246 --- static/js/directives/chat.js | 19 +++++++++---------- static/partials/chat.html | 2 +- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/static/js/directives/chat.js b/static/js/directives/chat.js index d764b09e..66954e88 100644 --- a/static/js/directives/chat.js +++ b/static/js/directives/chat.js @@ -415,11 +415,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,14 +456,11 @@ 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) { @@ -524,7 +516,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 +547,13 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro if (flip) { pane.toggleClass("flip"); } + if (active && autofocus) { + _.defer(function() { + if (scope.layout.chat) { + subscope.$broadcast("focus"); + } + }); + } }; scope.deactivateRoom = function() { 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 @@
{{_("Chat sessions")}}
- + {{room.pending}} {{room.id|displayName}} {{_("Room chat")}} {{currentRoomName}} From 95c898a4c3d67d0a7412b90ff4b2300f2a72de9d Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Tue, 5 Jan 2016 13:30:23 +0100 Subject: [PATCH 18/19] Automatically focus current chat input when chat pannel is shown manually, implementing part of #246 --- static/js/directives/chat.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/static/js/directives/chat.js b/static/js/directives/chat.js index 66954e88..69eeb814 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 = []; @@ -465,6 +466,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro if (options.restore && !options.noenable) { if (!scope.layout.chat) { + scope.autoFocusDisabled = true; scope.layout.chat = true; } } @@ -547,7 +549,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro if (flip) { pane.toggleClass("flip"); } - if (active && autofocus) { + if (active && autofocus && !scope.autoFocusDisabled) { _.defer(function() { if (scope.layout.chat) { subscope.$broadcast("focus"); @@ -565,6 +567,15 @@ 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) { From 66aba12c639e1daa0582fbe2f9df1e2206fb0482 Mon Sep 17 00:00:00 2001 From: Simon Eisenmann Date: Tue, 5 Jan 2016 13:46:29 +0100 Subject: [PATCH 19/19] Automatically activate room chat when no other chat is activated when chat panel becomes visible, partially implemnting #246 --- static/js/directives/chat.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/static/js/directives/chat.js b/static/js/directives/chat.js index 69eeb814..1da17e69 100644 --- a/static/js/directives/chat.js +++ b/static/js/directives/chat.js @@ -582,7 +582,7 @@ define(['jquery', 'underscore', 'text!partials/chat.html', 'text!partials/chatro 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));