Skip to content

Commit d50c4ad

Browse files
authored
Screenshare issue in demo application (#59)
Bugfix : Precall test result was not available when we come from landing page -> meeting page. Bugfix : https://app.clubhouse.io/callstatsio/story/8332/screen-became-black-if-we-cancel-screen-share-and-doesn-t-return-unless-we-stop-screen-share Screen share cancel button bug fix, and video rotation bugfix.
1 parent dc1356e commit d50c4ad

File tree

14 files changed

+177
-97
lines changed

14 files changed

+177
-97
lines changed

src/chrome-extension/background.js

Lines changed: 57 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,60 @@
1-
'use strict';
1+
/*
2+
* Copyright @ 2015 Atlassian Pty Ltd
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
216

3-
chrome.runtime.onConnect.addListener((port) => {
4-
const onScreenSourceID = (sourceId) => {
5-
if (!sourceId || !sourceId.length) {
6-
port.postMessage('PermissionDeniedError');
7-
} else {
8-
port.postMessage({'csioSourceId': sourceId,
9-
'evt': 'onCsioSourceId'});
10-
}
11-
};
17+
// Listens for external messages coming from pages that match url pattern
18+
// defined in manifest.json
19+
chrome.runtime.onMessageExternal.addListener(
20+
function(request, sender, sendResponse) {
21+
console.log('Got request', request, sender);
22+
if (request.getVersion) {
23+
sendResponse({ version: chrome.runtime.getManifest().version });
24+
return false; // Dispose of sendResponse
25+
} else if (request.getStream) {
26+
// Desktop video stream sources
27+
var sources = ['screen', 'window'];
28+
if (request.sources) {
29+
// Default
30+
sources = request.sources;
31+
}
32+
33+
// Tab for which the stream will be created (passed to
34+
// chrome.desktopCapture.chooseDesktopMedia).
35+
var tab = sender.tab;
1236

13-
const onCSIORequest = (evt) => {
14-
if (evt !== 'csioRequestScreenSourceId') {
15-
return;
37+
// If the streamId is requested from frame with different url than
38+
// its parent according to the documentation (
39+
// https://developer.chrome.com/extensions/desktopCapture ) -
40+
// "The stream can only be used by frames in the given tab whose
41+
// security origin matches tab.url." That's why we need to change
42+
// the url to the url of the frame (the frame is the sender).
43+
// Related ticket:
44+
// https://bugs.chromium.org/p/chromium/issues/detail?id=425344
45+
tab.url = sender.url;
46+
47+
// Gets chrome media stream token and returns it in the response.
48+
chrome.desktopCapture.chooseDesktopMedia(
49+
sources, tab,
50+
function(streamId) {
51+
sendResponse({ streamId: streamId });
52+
});
53+
return true; // Preserve sendResponse for future use
54+
} else {
55+
console.error('Unknown request');
56+
sendResponse({ error: 'Unknown request' });
57+
return false;
1658
}
17-
chrome.desktopCapture.chooseDesktopMedia(
18-
['screen', 'window'],
19-
port.sender.tab,
20-
onScreenSourceID
21-
);
22-
};
23-
port.onMessage.addListener(onCSIORequest);
24-
});
59+
}
60+
);

src/chrome-extension/content.js

Lines changed: 0 additions & 15 deletions
This file was deleted.

src/chrome-extension/manifest.json

Lines changed: 16 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,24 @@
11
{
2+
"manifest_version": 2,
23
"name": "Callstats.io WebRTC Screen sharing",
3-
"author": "Callstats.io",
4-
"version": "1.5",
5-
"manifest_version" : 2,
6-
"minimum_chrome_version": "49",
7-
"description" : "An utility extension for callstats.io to support screen sharing",
8-
"homepage_url": "https://github.com/callstats-io/webrtc-demoapp",
9-
"background": {
10-
"scripts": ["background.js"],
11-
"persistent": false
4+
"description": "An utility extension for callstats.io to support screen sharing borrowed from Jitsi codebase",
5+
"version": "0.1.6",
6+
"minimum_chrome_version": "34",
7+
"icons": {
8+
"48": "logo_48_48.png"
129
},
13-
"content_scripts": [{
14-
"js": ["content.js"],
15-
"all_frames": true,
16-
"run_at": "document_end",
17-
"matches": ["http://localhost:4440/*", "https://localhost:4440/*", "*://test-demoapp.callstats.io/*", "*://demo.callstats.io/*"]
18-
}],
19-
"icons" : {
20-
"48" : "logo_48_48.png"
10+
"background": {
11+
"scripts": [
12+
"background.js"
13+
],
14+
"persistent": true
2115
},
2216
"permissions": [
2317
"desktopCapture"
2418
],
25-
"web_accessible_resources": [
26-
"logo_48_48.png"
27-
]
19+
"externally_connectable": {
20+
"matches": [
21+
"*://meet.jit.si/*", "https://localhost:4440/*"
22+
]
23+
}
2824
}

src/client/apis/csiortc/CsioRTC.js

Lines changed: 56 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -101,40 +101,62 @@ class CsioRTC {
101101
}
102102
}
103103
mayBeStartStopScreenShare(isEnable) {
104-
for (const key in this.pcs) {
105-
if (this.pcs.hasOwnProperty(key) && this.pcs[key]) {
106-
this.csoiMedia.removeStream(this.pcs[key].pc);
104+
const getStreamID = (callback) => {
105+
const extensionid = __addon_id__; // getting from environment variable
106+
chrome.runtime.sendMessage(
107+
extensionid, {
108+
getStream: true
109+
},
110+
response => {
111+
if (!response) {
112+
console.error('->', response);
113+
callback(new Error('Failed to start screen share'), response);
114+
return;
115+
}
116+
if (response.streamId === '' || response.streamId.length <= 0) {
117+
callback(new Error('User selected cancel'), null);
118+
return;
119+
}
120+
callback(null, response.streamId);
121+
}
122+
);
123+
};
124+
const resetStream = () => {
125+
for (const key in this.pcs) {
126+
if (this.pcs.hasOwnProperty(key) && this.pcs[key]) {
127+
this.csoiMedia.removeStream(this.pcs[key].pc);
128+
}
107129
}
108-
}
109-
this.csoiMedia.disposeLocalStream();
130+
this.csoiMedia.disposeLocalStream();
131+
};
132+
110133
const isFF = !!navigator.mozGetUserMedia;
111134
if (isEnable) {
112135
if (isFF) {
113136
// show popup
114137
TriggerEvent(CsioEvents.CsioRTC.ON_FF_SCREEN_SHARE_OPTION, {});
115138
} else {
116139
// request screen share for chrome
117-
const extensionid = __addon_id__; // getting from environment variable
118-
chrome.runtime.sendMessage(
119-
extensionid, {
120-
getStream: true
121-
},
122-
response => {
123-
if (!response) {
124-
console.error('->', response);
125-
return;
126-
}
127-
const detail = {
128-
mediaSource: '',
129-
from: 'cmScreenShare',
130-
csioSourceId: response.streamId
131-
};
140+
getStreamID((err, streamId) => {
141+
if (err) {
132142
TriggerEvent(
133-
CsioEvents.CMScreenShare.ON_SCREEN_SHARE_OPTION_SELECTED, detail);
143+
CsioEvents.CsioRTC.ON_USER_CANCEL_SCREENSHARE, {});
144+
return;
134145
}
135-
);
146+
resetStream();
147+
const detail = {
148+
mediaSource: '',
149+
from: 'cmScreenShare',
150+
csioSourceId: streamId
151+
};
152+
TriggerEvent(
153+
CsioEvents.CMScreenShare.ON_SCREEN_SHARE_OPTION_SELECTED, detail);
154+
});
136155
}
137156
} else {
157+
this.notifyMediaStateChange(isEnable, 'screen');
158+
// reset stream first
159+
resetStream();
138160
// restart with getting local audio video
139161
const mediaConfig = this.config ? this.config.media : undefined;
140162
const roomName = this.roomName;
@@ -144,6 +166,7 @@ class CsioRTC {
144166
}
145167
}
146168
onStartedScreenShare(msg) {
169+
this.notifyMediaStateChange(true, 'screen');
147170
if (msg.detail && msg.detail.from === 'ffScreenShare') {
148171
const constraints = {
149172
'mediaSource': msg.detail.mediaSource,
@@ -153,7 +176,7 @@ class CsioRTC {
153176
};
154177
const roomName = this.roomName;
155178
if (constraints && roomName) {
156-
this.csoiMedia.getUserMedia({video: constraints, audio: false});
179+
this.csoiMedia.getUserMedia({video: constraints, audio: false}, true);
157180
}
158181
} else if (msg.detail && msg.detail.from === 'cmScreenShare') {
159182
const constraints = {
@@ -169,7 +192,7 @@ class CsioRTC {
169192
};
170193
const roomName = this.roomName;
171194
if (constraints && roomName) {
172-
this.csoiMedia.getUserMedia({video: constraints, audio: false});
195+
this.csoiMedia.getUserMedia({video: constraints, audio: false}, true);
173196
}
174197
}
175198
}
@@ -178,8 +201,17 @@ class CsioRTC {
178201
// this is screen share
179202
this.mayBeStartStopScreenShare(isEnable);
180203
} else {
204+
this.notifyMediaStateChange(isEnable, mediaType);
181205
this.csoiMedia.toggleMediaStates(isEnable, mediaType);
182206
}
207+
}
208+
notifyMediaStateChange(isEnable, mediaType) {
209+
const detail = {
210+
mediaType: mediaType,
211+
isEnable: isEnable
212+
};
213+
TriggerEvent(
214+
CsioEvents.CsioRTC.ON_MEDIA_STATE_CHANGED, detail);
183215
const getLog = (userId) => {
184216
let _type;
185217
let eventLog;

src/client/apis/csiortc/csiostats/CsioStats.js

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -201,7 +201,9 @@ class CsioStats {
201201
}
202202
onAskPrecallTestResult(e) {
203203
if (this.precallStats) {
204-
const detail = this.precallStats;
204+
const detail = {
205+
precallStats : this.precallStats
206+
};
205207
TriggerEvent(
206208
CsioEvents.CsioStats.ON_PRECALLTEST_RESULT_AVAILABLE,
207209
detail

src/client/apis/csiortc/rtc/CsioMediaCtrl.js

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class CsioMediaCtrl {
4747
TriggerEvent(CsioEvents.MEETING_PAGE.VIDEO_FOCUS_CHANGE, detail);
4848
}
4949
}
50-
getUserMedia(constraints) {
50+
getUserMedia(constraints, isScreenShare) {
5151
const self = this;
5252
let promise = this.isAudioOnly(constraints);
5353
promise.then(function(audioOnly) {
@@ -57,8 +57,11 @@ class CsioMediaCtrl {
5757
}
5858
navigator.mediaDevices.getUserMedia(_contrain)
5959
.then(function(stream) {
60+
stream.isLocal = true;
61+
stream.isScreen = isScreenShare || false;
6062
const detail = {
61-
media: stream
63+
media: stream,
64+
isScreenShare: isScreenShare
6265
};
6366
self.localStream = stream;
6467
TriggerEvent(

src/client/components/handlers/meetingpage/ContentRightHandler.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -136,6 +136,11 @@ class ContentRightHandler {
136136
});
137137
}
138138
}
139+
onCancelScreenShare(e) {
140+
this.setState({
141+
screenShared: e.detail.isEnable
142+
});
143+
}
139144

140145
onClickUserName(e) {
141146
e.preventDefault();

src/client/components/handlers/meetingpage/VideoHandler.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,12 @@ import {CsioEvents, TriggerEvent} from '../../../events/CsioEvents';
44
class VideoHandler {
55
constructor(name) {
66
this.name = name;
7+
this.isLocal = false;
8+
this.isScreen = false;
79
this.muted = false;
810
if (name === 'local') {
911
this.muted = true;
12+
this.isLocal = true;
1013
}
1114
}
1215
getState() {
@@ -18,6 +21,10 @@ class VideoHandler {
1821
this.video.srcObject = this.props.stream;
1922
}
2023
shouldComponentUpdate(props) {
24+
if (this.props.stream) {
25+
this.videoHandler.isLocal = props.stream.isLocal === true;
26+
this.videoHandler.isScreen = props.stream.isScreen === true;
27+
}
2128
return this.props.stream !== props.stream;
2229
}
2330
componentDidUpdate() {

src/client/components/handlers/meetingpage/VideoMainHandler.js

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,12 @@
33
class VideoMainHandler {
44
constructor(name) {
55
this.name = name;
6+
this.isLocal = false;
7+
this.isScreen = false;
68
this.muted = false;
79
if (name === 'local') {
810
this.muted = true;
11+
this.isLocal = true;
912
}
1013
}
1114
getState() {
@@ -20,6 +23,13 @@ class VideoMainHandler {
2023
componentDidUpdate() {
2124
this.video.srcObject = this.props.stream;
2225
}
26+
shouldComponentUpdate() {
27+
if (this.props.stream) {
28+
this.videoHandler.isLocal = this.props.stream.isLocal === true;
29+
this.videoHandler.isScreen = this.props.stream.isScreen === true;
30+
}
31+
return true;
32+
}
2333
onResizeVideoView(e) {
2434
setTimeout(function() {
2535
const height = Math.max(e.detail.height - 200, 360.0);

src/client/components/views/meetingpage/alert/AlertLayout.js

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ class AlertLayout extends React.Component {
1616
this.alertHandler.onNewUserJoined.bind(this), false);
1717
document.addEventListener(CsioEvents.CSIOSignaling.ON_LEAVE,
1818
this.alertHandler.onUserLeave.bind(this), false);
19-
document.addEventListener(CsioEvents.MEETING_PAGE.ON_TOGGLE_MEDIA_STATE,
20-
this.alertHandler.onToggleMediaState.bind(this), false);
2119
document.addEventListener(CsioEvents.CsioRTC.ON_EXTENTION_REQUIRED,
2220
this.alertHandler.onMayBeDownloadExtention.bind(this), false);
21+
document.addEventListener(CsioEvents.CsioRTC.ON_MEDIA_STATE_CHANGED,
22+
this.alertHandler.onToggleMediaState.bind(this), false);
2323
}
2424
render() {
2525
return (

0 commit comments

Comments
 (0)