diff --git a/bigbluebutton-html5/imports/api/video/server/handlers/userSharedHtml5Webcam.js b/bigbluebutton-html5/imports/api/video/server/handlers/userSharedHtml5Webcam.js
index e0101f99917c3dd917c380cf83309c1c35d0c397..abf5466ffea602df604717d33c941c39c0b3316b 100644
--- a/bigbluebutton-html5/imports/api/video/server/handlers/userSharedHtml5Webcam.js
+++ b/bigbluebutton-html5/imports/api/video/server/handlers/userSharedHtml5Webcam.js
@@ -1,11 +1,11 @@
 import sharedWebcam from '../modifiers/sharedWebcam';
 import {check} from 'meteor/check';
 
-export default function handleUserSharedHtml5Webcam({ header, payload }) {
-  const meetingId = header.meetingId;
-  const userId = header.userId;
-
+export default function handleUserSharedHtml5Webcam({ header }, meetingId ) {
+  check(header, Object);
+  const { userId } = header;
   check(meetingId, String);
+  check(userId, String);
 
   return sharedWebcam(meetingId, userId);
 }
diff --git a/bigbluebutton-html5/imports/api/video/server/handlers/userUnsharedHtml5Webcam.js b/bigbluebutton-html5/imports/api/video/server/handlers/userUnsharedHtml5Webcam.js
index d982c8daabc718f5f5f59c3efae563a7ef9885c6..bf6ba596e487375e198c671f8fe154f4e4da7c18 100644
--- a/bigbluebutton-html5/imports/api/video/server/handlers/userUnsharedHtml5Webcam.js
+++ b/bigbluebutton-html5/imports/api/video/server/handlers/userUnsharedHtml5Webcam.js
@@ -1,11 +1,11 @@
 import unsharedWebcam from '../modifiers/unsharedWebcam';
 import { check } from 'meteor/check';
 
-export default function handleUserUnsharedHtml5Webcam({ header, payload }) {
-  const meetingId = header.meetingId;
-  const userId = header.userId;
-
+export default function handleUserUnsharedHtml5Webcam({ header }, meetingId) {
+  check(header, Object);
+  const { userId } = header;
   check(meetingId, String);
+  check(userId, String);
 
   return unsharedWebcam(meetingId, userId);
 }
diff --git a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
index 4412ec793fc341fee7836720065ad6f36760bf1b..0ab79ef349c49eaa2d7cd8522d7cfc3712d66eeb 100644
--- a/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/actions-bar/component.jsx
@@ -7,8 +7,6 @@ import JoinVideoOptionsContainer from '../video-dock/video-menu/container';
 
 const ActionsBar = ({
   isUserPresenter,
-  handleExitAudio,
-  handleOpenJoinAudio,
   handleExitVideo,
   handleJoinVideo,
   handleShareScreen,
diff --git a/bigbluebutton-html5/imports/ui/components/app/container.jsx b/bigbluebutton-html5/imports/ui/components/app/container.jsx
index d8d0b54459de4d3f028644695ea34bd7184b6287..88abd7c9b6e1e4d076700b4a8e27247437c05537 100644
--- a/bigbluebutton-html5/imports/ui/components/app/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/app/container.jsx
@@ -7,7 +7,6 @@ import Auth from '/imports/ui/services/auth';
 import Users from '/imports/api/users';
 import Breakouts from '/imports/api/breakouts';
 import Meetings from '/imports/api/meetings';
-import Screenshare from '/imports/api/screenshare';
 
 import ClosedCaptionsContainer from '/imports/ui/components/closed-captions/container';
 
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx
index 58d226c13143fbbe0039f8b76b82fdeee40837ad..4c4271dfe7fb55acf43356deba5dbf3cc9ee280a 100644
--- a/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/component.jsx
@@ -4,10 +4,6 @@ import styles from './styles';
 import { log } from '/imports/ui/services/api';
 
 
-window.addEventListener('resize', () => {
-  window.adjustVideos('webcamArea', true);
-});
-
 class VideoElement extends Component {
   constructor(props) {
     super(props);
@@ -18,32 +14,31 @@ export default class VideoDock extends Component {
   constructor(props) {
     super(props);
 
+    // Set a valid bbb-webrtc-sfu application server socket in the settings
+    this.ws = new ReconnectingWebSocket(Meteor.settings.public.kurento.wsUrl);
+    this.wsQueue = [];
+    this.webRtcPeers = {};
+    this.reconnectWebcam = false;
+    this.reconnectList = false;
+    this.sharedCameraTimeout = null;
+    this.subscribedCamerasTimeouts = [];
+
     this.state = {
-      // Set a valid kurento application server socket in the settings
-      ws: new ReconnectingWebSocket(Meteor.settings.public.kurento.wsUrl),
-      webRtcPeers: {},
-      wsQueue: [],
-      reconnectWebcam: false,
-      reconnectList: [],
-      sharedCameraTimeout: null,
-      subscribedCamerasTimeouts: [],
       videos: {},
     };
 
-    window.ws = this.state.ws;
-
-    this.state.ws.addEventListener('open', () => {
+    this.ws.addEventListener('open', () => {
       log('debug', '------ Websocket connection opened.');
 
       // -- Resend queued messages that happened when socket was not connected
-      while (this.state.wsQueue.length > 0) {
-        this.sendMessage(this.state.wsQueue.pop());
+      while (this.wsQueue.length > 0) {
+        this.sendMessage(this.wsQueue.pop());
       }
 
       this.reconnectVideos();
     });
 
-    this.state.ws.addEventListener('close', (error) => {
+    this.ws.addEventListener('close', (error) => {
       log('debug', '------ Websocket connection closed.');
 
       this.setupReconnectVideos();
@@ -57,18 +52,18 @@ export default class VideoDock extends Component {
   }
 
   setupReconnectVideos() {
-    for (id in this.state.webRtcPeers) {
+    for (id in this.webRtcPeers) {
       this.disconnected(id);
       this.stop(id);
     }
   }
 
   reconnectVideos() {
-    for (i in this.state.reconnectList) {
-      const id = this.state.reconnectList[i];
+    for (i in this.reconnectList) {
+      const id = this.reconnectList[i];
 
       // TODO: base this on BBB API users instead of using memory
-      if (id != this.state.myId) {
+      if (id != this.myId) {
         setTimeout(() => {
           log('debug', ` [camera] Trying to reconnect camera ${id}`);
           this.start(id, false, this.refs.videoInput);
@@ -76,17 +71,17 @@ export default class VideoDock extends Component {
       }
     }
 
-    if (this.state.reconnectWebcam) {
-      log('debug', ` [camera] Trying to re-share ${this.state.myId} after reconnect.`);
-      this.start(this.state.myId, true, this.refs.videoInput);
+    if (this.reconnectWebcam) {
+      log('debug', ` [camera] Trying to re-share ${this.myId} after reconnect.`);
+      this.start(this.myId, true, this.refs.videoInput);
     }
 
-    this.setState({ reconnectWebcam: false, reconnectList: [] });
+    this.reconnectWebcam = false;
+    this.reconnectList = [];
   }
 
   componentDidMount() {
-    const that = this;
-    const ws = this.state.ws;
+    const ws = this.ws;
     const { users } = this.props;
     for (let i = 0; i < users.length; i++) {
       if (users[i].has_stream) {
@@ -94,66 +89,83 @@ export default class VideoDock extends Component {
       }
     }
 
-    document.addEventListener('joinVideo', () => { that.shareWebcam(); });// TODO find a better way to do this
-    document.addEventListener('exitVideo', () => { that.unshareWebcam(); });
+    document.addEventListener('joinVideo', this.shareWebcam.bind(this));// TODO find a better way to do this
+    document.addEventListener('exitVideo', this.unshareWebcam.bind(this));
 
-    ws.addEventListener('message', (msg) => {
-      const parsedMessage = JSON.parse(msg.data);
+    window.addEventListener('resize', this.adjustVideos);
 
-      console.log('Received message new ws message: ');
-      console.log(parsedMessage);
+    ws.addEventListener('message', this.onWsMessage.bind(this));
+  }
 
-      switch (parsedMessage.id) {
-        case 'startResponse':
-          this.startResponse(parsedMessage);
-          break;
+  componentWillMount () {
+    this.ws.onopen = () => {
+      while (this.wsQueue.length > 0) {
+        this.sendMessage(this.wsQueue.pop());
+      }
+    };
+  }
 
-        case 'error':
-          this.handleError(parsedMessage);
-          break;
+  componentWillUnmount () {
+    document.removeEventListener('joinVideo', this.shareWebcam);
+    document.removeEventListener('exitVideo', this.shareWebcam);
+    window.removeEventListener('resize', this.adjustVideos);
+    this.ws.removeEventListener('message', this.onWsMessage);
+  }
 
-        case 'playStart':
-          this.handlePlayStart(parsedMessage);
-          break;
+  adjustVideos () {
+    window.adjustVideos('webcamArea', true);
+  }
 
-        case 'playStop':
-          this.handlePlayStop(parsedMessage);
+  onWsMessage (msg) {
+    const parsedMessage = JSON.parse(msg.data);
 
-          break;
+    console.log('Received message new ws message: ');
+    console.log(parsedMessage);
 
-        case 'iceCandidate':
+    switch (parsedMessage.id) {
 
-          const webRtcPeer = this.state.webRtcPeers[parsedMessage.cameraId];
+      case 'startResponse':
+        this.startResponse(parsedMessage);
+        break;
 
-          if (webRtcPeer !== null) {
-            if (webRtcPeer.didSDPAnswered) {
-              webRtcPeer.addIceCandidate(parsedMessage.candidate, (err) => {
-                if (err) {
-                  return log('error', `Error adding candidate: ${err}`);
-                }
-              });
-            } else {
+      case 'error':
+        this.handleError(parsedMessage);
+        break;
 
-              // If we are ever in a position where iceQueue is not defined by this point
-              if (typeof webRtcPeer.iceQueue === 'undefined') {
-                webRtcPeer.iceQueue = [];
-              }
+      case 'playStart':
+        this.handlePlayStart(parsedMessage);
+        break;
 
-              webRtcPeer.iceQueue.push(parsedMessage.candidate);
-            }
+      case 'playStop':
+        this.handlePlayStop(parsedMessage);
+
+        break;
+
+      case 'iceCandidate':
+
+        const webRtcPeer = this.webRtcPeers[parsedMessage.cameraId];
+
+        if (webRtcPeer !== null) {
+          if (webRtcPeer.didSDPAnswered) {
+            webRtcPeer.addIceCandidate(parsedMessage.candidate, (err) => {
+              if (err) {
+                return log('error', `Error adding candidate: ${err}`);
+              }
+            });
           } else {
-            log('error', ' [ICE] Message arrived before webRtcPeer?');
+            webRtcPeer.iceQueue.push(parsedMessage.candidate);
           }
-
-          break;
-      }
-    });
-  }
+        } else {
+          log('error', ' [ICE] Message arrived before webRtcPeer?');
+        }
+        break;
+    }
+  };
 
   start(id, shareWebcam, videoInput) {
     const that = this;
 
-    const ws = this.state.ws;
+    const ws = this.ws;
 
     console.log(`Starting video call for video: ${id}`);
     log('info', 'Creating WebRtcPeer and generating local sdp offer ...');
@@ -202,7 +214,7 @@ export default class VideoDock extends Component {
       document.getElementById('webcamArea').appendChild(options.remoteVideo);
     }
 
-    this.state.webRtcPeers[id] = new peerObj(options, function (error) {
+    var webRtcPeer = new peerObj(options, function (error) {
       if (error) {
         log('error', ' WebRTC peerObj create error');
 
@@ -215,9 +227,10 @@ export default class VideoDock extends Component {
       this.didSDPAnswered = false;
       this.iceQueue = [];
 
+      that.webRtcPeers[id] = webRtcPeer;
       if (shareWebcam) {
-        that.state.sharedWebcam = that.state.webRtcPeers[id];
-        that.state.myId = id;
+        that.sharedWebcam = webRtcPeer;
+        that.myId = id;
       }
 
       this.generateOffer((error, offerSdp) => {
@@ -254,17 +267,13 @@ export default class VideoDock extends Component {
   }
 
   disconnected(id) {
-    if (this.state.sharedWebcam) {
+    if (this.sharedWebcam) {
       log('debug', ' [camera] Webcam disconnected, will try re-share webcam later.');
-      this.setState({ reconnectWebcam: true });
+      this.reconnectWebcam = true;
     } else {
-      const reconnectList = this.state.reconnectList;
-
-      reconnectList.push(id);
+      this.reconnectList.push(id);
 
       log('debug', ` [camera] ${id} disconnected, will try re-subscribe later.`);
-
-      this.setState({ reconnectList });
     }
   }
 
@@ -309,20 +318,25 @@ export default class VideoDock extends Component {
   }
 
   destroyWebRTCPeer(id) {
-    const webRtcPeer = this.state.webRtcPeers[id];
+    const webRtcPeer = this.webRtcPeers[id];
 
     if (webRtcPeer) {
       log('info', 'Stopping WebRTC peer');
 
+      if (id == this.myId && this.sharedWebcam) {
+        this.sharedWebcam.dispose();
+        this.sharedWebcam = null;
+      }
+
       webRtcPeer.dispose();
-      delete this.state.webRtcPeers[id];
+      delete this.webRtcPeers[id];
     } else {
       log('info', 'No WebRTC peer to stop (not an error)');
     }
 
-    if (this.state.sharedWebcam) {
-      this.state.sharedWebcam.dispose();
-      this.state.sharedWebcam = null;
+    if (this.sharedWebcam) {
+      this.sharedWebcam.dispose();
+      this.sharedWebcam = null;
     } else {
       log('info', 'No shared camera WebRTC peer to stop (not an error)');
     }
@@ -349,7 +363,7 @@ export default class VideoDock extends Component {
 
   startResponse(message) {
     const id = message.cameraId;
-    const webRtcPeer = this.state.webRtcPeers[id];
+    const webRtcPeer = this.webRtcPeers[id];
 
     if (message.sdpAnswer == null) {
       return log('debug', 'Null sdp answer. Camera unplugged?');
@@ -371,7 +385,7 @@ export default class VideoDock extends Component {
   }
 
   sendMessage(message) {
-    const ws = this.state.ws;
+    const ws = this.ws;
 
     if (this.connectedToMediaServer()) {
       const jsonMessage = JSON.stringify(message);
@@ -384,17 +398,17 @@ export default class VideoDock extends Component {
     } else {
       // No need to queue video stop messages
       if (message.id != 'stop') {
-        this.state.wsQueue.push(message);
+        this.wsQueue.push(message);
       }
     }
   }
 
   connectedToMediaServer() {
-    return ws.readyState == WebSocket.OPEN;
+    return this.ws.readyState === WebSocket.OPEN;
   }
 
   connectionStatus() {
-    return ws.readyState;
+    return this.ws.readyState;
   }
 
   handlePlayStop(message) {
@@ -427,9 +441,9 @@ export default class VideoDock extends Component {
 
   componentWillUnmount() {
     // Close websocket connection to prevent multiple reconnects from happening
-    this.state.ws.close();
+    this.ws.close();
 
-    this.state.ws.removeEventListener('message', () => {});
+    this.ws.removeEventListener('message', () => {});
   }
 
   shouldComponentUpdate(nextProps, nextState) {
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx
index 0bd4ea2ee4d5f16a57ee285175169b4c161c94aa..a92bbb3d0989192cca4b2840832df304611843d5 100644
--- a/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/container.jsx
@@ -3,7 +3,6 @@ import { createContainer } from 'meteor/react-meteor-data';
 
 import VideoDock from './component';
 import VideoService from './service';
-import Users from '/imports/api/users';
 
 class VideoDockContainer extends Component {
   constructor(props) {
@@ -22,5 +21,5 @@ class VideoDockContainer extends Component {
 export default createContainer(() => ({
   sendUserShareWebcam: VideoService.sendUserShareWebcam,
   sendUserUnshareWebcam: VideoService.sendUserUnshareWebcam,
-  users: Users.find().fetch(),
+  users: VideoService.getAllUsers(),
 }), VideoDockContainer);
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/service.js b/bigbluebutton-html5/imports/ui/components/video-dock/service.js
index 99a791ecbfa05e767ec0f3155424a387c0c62b1f..5d778fca8f2385b81697876dc7773327f94bcbaa 100644
--- a/bigbluebutton-html5/imports/ui/components/video-dock/service.js
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/service.js
@@ -1,4 +1,6 @@
 import { makeCall } from '/imports/ui/services/api';
+import Users from '/imports/api/users';
+import { createContainer } from 'meteor/react-meteor-data';
 
 const joinVideo = () => {
   var joinVideoEvent = new Event('joinVideo');
@@ -18,6 +20,10 @@ const sendUserUnshareWebcam = (stream) => {
   makeCall('userUnshareWebcam', stream);
 };
 
+const getAllUsers = () => {
+  return Users.find().fetch();
+}
+
 export default {
-  sendUserShareWebcam, sendUserUnshareWebcam, joinVideo, exitVideo,
+  sendUserShareWebcam, sendUserUnshareWebcam, joinVideo, exitVideo, getAllUsers,
 };
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/styles.scss b/bigbluebutton-html5/imports/ui/components/video-dock/styles.scss
index 4157b2c58194558e64ead582c2b654f8464acf8f..0292985c863c1e86a69754f5177b88298b8061f1 100644
--- a/bigbluebutton-html5/imports/ui/components/video-dock/styles.scss
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/styles.scss
@@ -13,9 +13,6 @@
   border-radius: .2rem;
 }
 
-.secretButtons {
-}
-
 .sharedWebcamVideo {
   display: none;
 }
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/component.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/component.jsx
index 9a2ca1c0181283ead37a71a3f41a49a083d8b02a..99d04b28e0dd125938c716f5c514e53ab494e15d 100755
--- a/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/component.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/component.jsx
@@ -1,7 +1,6 @@
 import React from 'react';
 import { createContainer } from 'meteor/react-meteor-data';
 import Button from '/imports/ui/components/button/component';
-import { withRouter } from 'react-router';
 import { defineMessages, injectIntl } from 'react-intl';
 
 const intlMessages = defineMessages({
@@ -50,4 +49,4 @@ class JoinVideoOptions extends React.Component {
   }
 }
 
-export default withRouter(injectIntl(JoinVideoOptions));
+export default injectIntl(JoinVideoOptions);
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/container.jsx b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/container.jsx
index da5950f90a3da413c568f53f93964149487501b2..da7d5517f5147408c91fba55207818fc666b7423 100755
--- a/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/container.jsx
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/container.jsx
@@ -1,17 +1,12 @@
 import React from 'react';
 import { createContainer } from 'meteor/react-meteor-data';
-import Users from '/imports/api/users';
-import Auth from '/imports/ui/services/auth/index';
 import JoinVideoOptions from './component';
+import VideoMenuService from './service';
 
 const JoinVideoOptionsContainer = props => (<JoinVideoOptions {...props} />);
 
 export default createContainer((params) => {
-  const userId = Auth.userID;
-  const user = Users.findOne({ userId: userId });
-
-  const isSharingVideo = user.has_stream ? true : false;
- 
+  const isSharingVideo = VideoMenuService.isSharingVideo();
   return {
     isSharingVideo,
     handleJoinVideo: params.handleJoinVideo,
diff --git a/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/service.js b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/service.js
new file mode 100644
index 0000000000000000000000000000000000000000..92a58cd21afc50dac0196a3d19d325fea668e125
--- /dev/null
+++ b/bigbluebutton-html5/imports/ui/components/video-dock/video-menu/service.js
@@ -0,0 +1,12 @@
+import Users from '/imports/api/users';
+import Auth from '/imports/ui/services/auth/index';
+
+const isSharingVideo = () => {
+  const userId = Auth.userID;
+  const user = Users.findOne({ userId: userId });
+  return user.has_stream ? true : false;
+};
+
+export default {
+  isSharingVideo
+};
diff --git a/bigbluebutton-html5/private/locales/en.json b/bigbluebutton-html5/private/locales/en.json
index be13c502d43198332602b064798cef3bd12b2eaf..fef395731f67acece496fa4aa8d0362f17efa635 100644
--- a/bigbluebutton-html5/private/locales/en.json
+++ b/bigbluebutton-html5/private/locales/en.json
@@ -260,6 +260,6 @@
     "app.guest.waiting": "Waiting for approval to join",
     "app.notification.recordingStart": "This session is now being recorded",
     "app.notification.recordingStop": "This session is not being recorded anymore",
-    "app.video.joinVideo": "Cam off",
-    "app.video.leaveVideo": "Cam on"
+    "app.video.joinVideo": "Share webcam",
+    "app.video.leaveVideo": "Unshare webcam"
 }