blob: 24f22b7a6a777d11b82b78d787eb51b551568d9a [file] [log] [blame]
[email protected]deb232b2022-11-28 11:22:161// Copyright 2022 The Chromium Authors
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
dpapad303c92812023-10-31 02:08:355import {$} from 'chrome://resources/js/util.js';
[email protected]deb232b2022-11-28 11:22:166const USER_MEDIA_TAB_ID = 'user-media-tab-id';
7
8/**
9 * A helper function for appending a child element to |parent|.
10 *
11 * @param {!Element} parent The parent element.
12 * @param {string} tag The child element tag.
13 * @param {string} text The textContent of the new DIV.
14 * @return {!Element} the new DIV element.
15 */
16 function appendChildWithText(parent, tag, text) {
17 const child = document.createElement(tag);
18 child.textContent = text;
19 parent.appendChild(child);
20 return child;
21}
22
23export class UserMediaTable {
24 /**
25 * @param {Object} tabView the TabView object to add the user media tab to.
26 */
27 constructor(tabView) {
28 this.tabView = tabView;
29 }
30
31 /**
32 * Populate the tab view with a getUserMedia/getDisplayMedia tab.
33 */
34 createTab() {
35 const container = this.tabView.addTab(USER_MEDIA_TAB_ID,
Philipp Hancke94429ac02023-03-03 16:03:2136 'getUserMedia/getDisplayMedia');
[email protected]deb232b2022-11-28 11:22:1637 // Create the filter input field and label.
38 appendChildWithText(container, 'label', 'Filter by origin including ');
39 const input = document.createElement('input');
40 input.size = 30;
41 input.oninput = this.filterUserMedia.bind(this);
42 container.appendChild(input);
43 }
44
45 /**
46 * Apply a filter to the user media table.
47 * @param event InputEvent from the filter input field.
48 * @private
49 */
50 filterUserMedia(event) {
51 const filter = event.target.value;
52 const requests = $(USER_MEDIA_TAB_ID).childNodes;
53 for (let i = 0; i < requests.length; ++i) {
54 if (!requests[i]['data-origin']) {
55 continue;
56 }
57 if (requests[i]['data-origin'].includes(filter)) {
58 requests[i].style.display = 'block';
59 } else {
60 requests[i].style.display = 'none';
61 }
62 }
63 }
64
65 /**
66 * Adds a getUserMedia/getDisplayMedia request.
67 * @param {!Object} data The object containing rid {number}, pid {number},
68 * origin {string}, request_id {number}, request_type {string},
69 * audio {string}, video {string}.
70 */
71 addMedia(data) {
72 if (!$(USER_MEDIA_TAB_ID)) {
73 this.createTab();
74 }
75
76 const requestDiv = document.createElement('div');
77 requestDiv.className = 'user-media-request-div-class';
78 requestDiv.id = ['gum', data.rid, data.pid, data.request_id].join('-');
79 requestDiv['data-rid'] = data.rid;
80 requestDiv['data-origin'] = data.origin;
Philipp Hancke6f8193b32023-09-19 08:05:3781 // Insert new getUserMedia calls at the top.
82 $(USER_MEDIA_TAB_ID).insertBefore(requestDiv,
83 $(USER_MEDIA_TAB_ID).firstChild);
[email protected]deb232b2022-11-28 11:22:1684
85 appendChildWithText(requestDiv, 'div', 'Caller origin: ' + data.origin);
86 appendChildWithText(requestDiv, 'div', 'Caller process id: ' + data.pid);
87
88 const el = appendChildWithText(requestDiv, 'span',
89 data.request_type + ' call');
90 el.style.fontWeight = 'bold';
91 appendChildWithText(el, 'div', 'Time: ' +
92 (new Date(data.timestamp).toTimeString()))
93 .style.fontWeight = 'normal';
94 if (data.audio !== undefined) {
95 appendChildWithText(el, 'div', 'Audio constraints: ' +
96 (data.audio || 'true'))
97 .style.fontWeight = 'normal';
98 }
99 if (data.video !== undefined) {
100 appendChildWithText(el, 'div', 'Video constraints: ' +
101 (data.video || 'true'))
102 .style.fontWeight = 'normal';
103 }
104 }
105
106 /**
107 * Update a getUserMedia/getDisplayMedia request with a result or error.
108 *
109 * @param {!Object} data The object containing rid {number}, pid {number},
110 * request_id {number}, request_type {string}.
111 * For results there is also the
112 * stream_id {string}, audio_track_info {string} and
113 * video_track_info {string}.
114 * For errors the error {string} and
115 * error_message {string} fields are set.
116 */
117 updateMedia(data) {
118 if (!$(USER_MEDIA_TAB_ID)) {
119 this.createTab();
120 }
121
122 const requestDiv = document.getElementById(
123 ['gum', data.rid, data.pid, data.request_id].join('-'));
124 if (!requestDiv) {
125 console.error('Could not update ' + data.request_type + ' request', data);
126 return;
127 }
128
129 if (data.error) {
130 const el = appendChildWithText(requestDiv, 'span', 'Error');
131 el.style.fontWeight = 'bold';
132 appendChildWithText(el, 'div', 'Time: ' +
133 (new Date(data.timestamp).toTimeString()))
134 .style.fontWeight = 'normal';
135 appendChildWithText(el, 'div', 'Error: ' + data.error)
136 .style.fontWeight = 'normal';
137 appendChildWithText(el, 'div', 'Error message: ' + data.error_message)
138 .style.fontWeight = 'normal';
139 return;
140 }
141
142 const el = appendChildWithText(requestDiv, 'span',
143 data.request_type + ' result');
144 el.style.fontWeight = 'bold';
145 appendChildWithText(el, 'div', 'Time: ' +
146 (new Date(data.timestamp).toTimeString()))
147 .style.fontWeight = 'normal';
148 appendChildWithText(el, 'div', 'Stream id: ' + data.stream_id)
149 .style.fontWeight = 'normal';
150 if (data.audio_track_info) {
151 appendChildWithText(el, 'div', 'Audio track: ' + data.audio_track_info)
152 .style.fontWeight = 'normal';
153 }
154 if (data.video_track_info) {
155 appendChildWithText(el, 'div', 'Video track: ' + data.video_track_info)
156 .style.fontWeight = 'normal';
157 }
158 }
159
160 /**
161 * Removes the getUserMedia/getDisplayMedia requests from the specified |rid|.
162 *
163 * @param {!Object} data The object containing rid {number}, the render id.
164 */
165 removeMediaForRenderer(data) {
166 const requests = $(USER_MEDIA_TAB_ID).childNodes;
167 for (let i = 0; i < requests.length; ++i) {
168 if (!requests[i]['data-origin']) {
169 continue;
170 }
171 if (requests[i]['data-rid'] === data.rid) {
172 $(USER_MEDIA_TAB_ID).removeChild(requests[i]);
173 }
174 }
175 // Remove the tab when only the search field and its label are left.
176 if ($(USER_MEDIA_TAB_ID).childNodes.length === 2) {
177 this.tabView.removeTab(USER_MEDIA_TAB_ID);
178 }
179 }
180}