Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 1 | # Copyright 2017 The Chromium OS Authors. All rights reserved. |
| 2 | # Use of this source code is governed by a BSD-style license that can be |
| 3 | # found in the LICENSE file. |
| 4 | |
| 5 | import logging |
| 6 | |
Denis Tosic | 62f32d4 | 2018-10-11 15:28:34 +0200 | [diff] [blame^] | 7 | from urlparse import urlparse |
| 8 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 9 | DEFAULT_TIMEOUT = 30 |
| 10 | TELEMETRY_API = 'hrTelemetryApi' |
| 11 | |
| 12 | |
| 13 | class CfmMeetingsAPI(object): |
| 14 | """Utility class for interacting with CfMs.""" |
| 15 | |
| 16 | def __init__(self, webview_context): |
| 17 | self._webview_context = webview_context |
| 18 | |
| 19 | def _execute_telemetry_command(self, command): |
| 20 | self._webview_context.ExecuteJavaScript( |
| 21 | 'window.%s.%s' % (TELEMETRY_API, command)) |
| 22 | |
| 23 | def _evaluate_telemetry_command(self, command): |
| 24 | return self._webview_context.EvaluateJavaScript( |
| 25 | 'window.%s.%s' % (TELEMETRY_API, command)) |
| 26 | |
| 27 | # UI commands/functions |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 28 | def wait_for_meetings_landing_page(self): |
| 29 | """Waits for the landing page screen.""" |
| 30 | self._webview_context.WaitForJavaScriptCondition( |
Denis Tosic | 5ff0986 | 2017-07-03 12:47:28 +0200 | [diff] [blame] | 31 | 'window.hasOwnProperty("%s") ' |
| 32 | '&& !window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API), |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 33 | timeout=DEFAULT_TIMEOUT) |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 34 | logging.info('Reached meetings landing page.') |
| 35 | |
| 36 | def wait_for_meetings_in_call_page(self): |
| 37 | """Waits for the in-call page to launch.""" |
| 38 | self._webview_context.WaitForJavaScriptCondition( |
Denis Tosic | 5ff0986 | 2017-07-03 12:47:28 +0200 | [diff] [blame] | 39 | 'window.hasOwnProperty("%s") ' |
| 40 | '&& window.%s.isInMeeting()' % (TELEMETRY_API, TELEMETRY_API), |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 41 | timeout=DEFAULT_TIMEOUT) |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 42 | logging.info('Reached meetings in-call page.') |
| 43 | |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 44 | def wait_for_telemetry_commands(self): |
| 45 | """Wait for hotrod app to load and telemetry commands to be available. |
| 46 | """ |
| 47 | raise NotImplementedError |
| 48 | |
| 49 | def wait_for_oobe_start_page(self): |
| 50 | """Wait for oobe start screen to launch.""" |
| 51 | raise NotImplementedError |
| 52 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 53 | def skip_oobe_screen(self): |
| 54 | """Skip Chromebox for Meetings oobe screen.""" |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 55 | raise NotImplementedError |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 56 | |
| 57 | def is_oobe_start_page(self): |
| 58 | """Check if device is on CFM oobe start screen.""" |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 59 | raise NotImplementedError |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 60 | |
| 61 | # Hangouts commands/functions |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 62 | def start_meeting_session(self): |
Denis Tosic | 62f32d4 | 2018-10-11 15:28:34 +0200 | [diff] [blame^] | 63 | """Start a meeting. |
| 64 | |
| 65 | @return code for the started meeting |
| 66 | """ |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 67 | if self.is_in_meeting_session(): |
| 68 | self.end_meeting_session() |
| 69 | |
| 70 | self._execute_telemetry_command('startMeeting()') |
| 71 | self.wait_for_meetings_in_call_page() |
Denis Tosic | 62f32d4 | 2018-10-11 15:28:34 +0200 | [diff] [blame^] | 72 | meeting_code = self._get_meeting_code() |
| 73 | logging.info('Started meeting session %s', meeting_code) |
| 74 | return meeting_code |
| 75 | |
| 76 | def _get_meeting_code(self): |
| 77 | path = urlparse(self._webview_context.GetUrl()).path |
| 78 | # The meeting code is the last part of the path. |
| 79 | return path.split('/')[-1] |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 80 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 81 | def join_meeting_session(self, meeting_name): |
| 82 | """Joins a meeting. |
| 83 | |
| 84 | @param meeting_name: Name of the meeting session. |
| 85 | """ |
| 86 | if self.is_in_meeting_session(): |
| 87 | self.end_meeting_session() |
| 88 | |
| 89 | self._execute_telemetry_command('joinMeeting("%s")' % meeting_name) |
| 90 | self.wait_for_meetings_in_call_page() |
| 91 | logging.info('Started meeting session: %s', meeting_name) |
| 92 | |
| 93 | def end_meeting_session(self): |
| 94 | """End current meeting session.""" |
| 95 | self._execute_telemetry_command('endCall()') |
| 96 | self.wait_for_meetings_landing_page() |
| 97 | logging.info('Ended meeting session.') |
| 98 | |
| 99 | def is_in_meeting_session(self): |
| 100 | """Check if device is in meeting session.""" |
| 101 | if self._evaluate_telemetry_command('isInMeeting()'): |
| 102 | logging.info('Is in meeting session.') |
| 103 | return True |
| 104 | logging.info('Is not in meeting session.') |
| 105 | return False |
| 106 | |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 107 | def start_new_hangout_session(self, hangout_name): |
| 108 | """Start a new hangout session. |
| 109 | |
| 110 | @param hangout_name: Name of the hangout session. |
| 111 | """ |
| 112 | raise NotImplementedError |
| 113 | |
| 114 | def end_hangout_session(self): |
| 115 | """End current hangout session.""" |
| 116 | raise NotImplementedError |
| 117 | |
| 118 | def is_in_hangout_session(self): |
| 119 | """Check if device is in hangout session.""" |
| 120 | raise NotImplementedError |
| 121 | |
| 122 | def is_ready_to_start_hangout_session(self): |
| 123 | """Check if device is ready to start a new hangout session.""" |
| 124 | raise NotImplementedError |
| 125 | |
Denis Tosic | 06b4365 | 2017-10-26 11:49:10 +0200 | [diff] [blame] | 126 | def get_participant_count(self): |
| 127 | """Returns the total number of participants in a meeting.""" |
| 128 | return self._evaluate_telemetry_command('getParticipantCount()') |
| 129 | |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 130 | # Diagnostics commands/functions |
| 131 | def is_diagnostic_run_in_progress(self): |
| 132 | """Check if hotrod diagnostics is running.""" |
| 133 | raise NotImplementedError |
| 134 | |
| 135 | def wait_for_diagnostic_run_to_complete(self): |
| 136 | """Wait for hotrod diagnostics to complete.""" |
| 137 | raise NotImplementedError |
| 138 | |
| 139 | def run_diagnostics(self): |
| 140 | """Run hotrod diagnostics.""" |
| 141 | raise NotImplementedError |
| 142 | |
| 143 | def get_last_diagnostics_results(self): |
| 144 | """Get latest hotrod diagnostics results.""" |
| 145 | raise NotImplementedError |
| 146 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 147 | # Mic audio commands/functions |
| 148 | def is_mic_muted(self): |
| 149 | """Check if mic is muted.""" |
| 150 | if self._evaluate_telemetry_command('isMicMuted()'): |
| 151 | logging.info('Mic is muted.') |
| 152 | return True |
| 153 | logging.info('Mic is not muted.') |
| 154 | return False |
| 155 | |
| 156 | def mute_mic(self): |
| 157 | """Local mic mute from toolbar.""" |
| 158 | self._execute_telemetry_command('setMicMuted(true)') |
| 159 | logging.info('Locally muted mic.') |
| 160 | |
| 161 | def unmute_mic(self): |
| 162 | """Local mic unmute from toolbar.""" |
| 163 | self._execute_telemetry_command('setMicMuted(false)') |
| 164 | logging.info('Locally unmuted mic.') |
| 165 | |
| 166 | def get_mic_devices(self): |
| 167 | """Get all mic devices detected by hotrod.""" |
| 168 | return self._evaluate_telemetry_command('getAudioInDevices()') |
| 169 | |
| 170 | def get_preferred_mic(self): |
| 171 | """Get preferred microphone for hotrod.""" |
| 172 | return self._evaluate_telemetry_command('getPreferredAudioInDevice()') |
| 173 | |
| 174 | def set_preferred_mic(self, mic_name): |
| 175 | """Set preferred mic for hotrod. |
| 176 | |
| 177 | @param mic_name: String with mic name. |
| 178 | """ |
| 179 | self._execute_telemetry_command('setPreferredAudioInDevice(%s)' |
| 180 | % mic_name) |
| 181 | logging.info('Setting preferred mic to %s.', mic_name) |
| 182 | |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 183 | def remote_mute_mic(self): |
| 184 | """Remote mic mute request from cPanel.""" |
| 185 | raise NotImplementedError |
| 186 | |
| 187 | def remote_unmute_mic(self): |
| 188 | """Remote mic unmute request from cPanel.""" |
| 189 | raise NotImplementedError |
| 190 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 191 | # Speaker commands/functions |
| 192 | def get_speaker_devices(self): |
| 193 | """Get all speaker devices detected by hotrod.""" |
| 194 | return self._evaluate_telemetry_command('getAudioOutDevices()') |
| 195 | |
| 196 | def get_preferred_speaker(self): |
| 197 | """Get speaker preferred for hotrod.""" |
| 198 | return self._evaluate_telemetry_command('getPreferredAudioOutDevice()') |
| 199 | |
| 200 | def set_preferred_speaker(self, speaker_name): |
| 201 | """Set preferred speaker for hotrod. |
| 202 | |
| 203 | @param speaker_name: String with speaker name. |
| 204 | """ |
| 205 | self._execute_telemetry_command('setPreferredAudioOutDevice(%s)' |
| 206 | % speaker_name) |
| 207 | logging.info('Set preferred speaker to %s.', speaker_name) |
| 208 | |
| 209 | def set_speaker_volume(self, volume_level): |
| 210 | """Set speaker volume. |
| 211 | |
| 212 | @param volume_level: Number value ranging from 0-100 to set volume to. |
| 213 | """ |
| 214 | self._execute_telemetry_command('setAudioOutVolume(%d)' % volume_level) |
| 215 | logging.info('Set speaker volume to %d', volume_level) |
| 216 | |
| 217 | def get_speaker_volume(self): |
| 218 | """Get current speaker volume.""" |
| 219 | return self._evaluate_telemetry_command('getAudioOutVolume()') |
| 220 | |
harpreet | 47a23a1 | 2017-06-29 20:21:49 -0700 | [diff] [blame] | 221 | def play_test_sound(self): |
| 222 | """Play test sound.""" |
| 223 | raise NotImplementedError |
| 224 | |
Denis Tosic | 739e8c7 | 2017-06-09 11:23:25 +0200 | [diff] [blame] | 225 | # Camera commands/functions |
| 226 | def get_camera_devices(self): |
| 227 | """Get all camera devices detected by hotrod. |
| 228 | |
| 229 | @return List of camera devices. |
| 230 | """ |
| 231 | return self._evaluate_telemetry_command('getVideoInDevices()') |
| 232 | |
| 233 | def get_preferred_camera(self): |
| 234 | """Get camera preferred for hotrod.""" |
| 235 | return self._evaluate_telemetry_command('getPreferredVideoInDevice()') |
| 236 | |
| 237 | def set_preferred_camera(self, camera_name): |
| 238 | """Set preferred camera for hotrod. |
| 239 | |
| 240 | @param camera_name: String with camera name. |
| 241 | """ |
| 242 | self._execute_telemetry_command('setPreferredVideoInDevice(%s)' |
| 243 | % camera_name) |
| 244 | logging.info('Set preferred camera to %s.', camera_name) |
| 245 | |
| 246 | def is_camera_muted(self): |
| 247 | """Check if camera is muted (turned off).""" |
| 248 | if self._evaluate_telemetry_command('isCameraMuted()'): |
| 249 | logging.info('Camera is muted.') |
| 250 | return True |
| 251 | logging.info('Camera is not muted.') |
| 252 | return False |
| 253 | |
| 254 | def mute_camera(self): |
| 255 | """Mute (turn off) camera.""" |
| 256 | self._execute_telemetry_command('setCameraMuted(true)') |
| 257 | logging.info('Camera muted.') |
| 258 | |
| 259 | def unmute_camera(self): |
| 260 | """Unmute (turn on) camera.""" |
| 261 | self._execute_telemetry_command('setCameraMuted(false)') |
| 262 | logging.info('Camera unmuted.') |
Dennis Wu | a034cb4 | 2017-10-25 17:07:30 -0700 | [diff] [blame] | 263 | |
| 264 | def move_camera(self, camera_motion): |
| 265 | """Move camera(PTZ functions). |
| 266 | |
| 267 | @param camera_motion: String of the desired camera motion. |
| 268 | """ |
| 269 | ptz_motions = ['panLeft','panRight','panStop', |
| 270 | 'tiltUp','tiltDown','tiltStop', |
| 271 | 'zoomIn','zoomOut','resetPosition'] |
| 272 | |
| 273 | if camera_motion in ptz_motions: |
| 274 | self._execute_telemetry_command('ptz.%s()' % camera_motion) |
| 275 | else: |
| 276 | raise ValueError('Unsupported PTZ camera action: "%s"' |
| 277 | % camera_motion) |