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 """Facade to access the CFM functionality.""" 6 7 import time 8 9 from autotest_lib.client.common_lib import error 10 from autotest_lib.client.common_lib.cros import cfm_hangouts_api 11 from autotest_lib.client.common_lib.cros import cfm_meetings_api 12 from autotest_lib.client.common_lib.cros import enrollment 13 from autotest_lib.client.common_lib.cros import kiosk_utils 14 15 16 class TimeoutException(Exception): 17 """Timeout Exception class.""" 18 pass 19 20 21 class CFMFacadeNative(object): 22 """Facade to access the CFM functionality. 23 24 The methods inside this class only accept Python native types. 25 """ 26 _USER_ID = 'cfmtest (at] croste.tv' 27 _PWD = 'test0000' 28 _EXT_ID = 'ikfcpmgefdpheiiomgmhlmmkihchmdlj' 29 _ENROLLMENT_DELAY = 15 30 _DEFAULT_TIMEOUT = 30 31 32 33 def __init__(self, resource): 34 """Initializes a CFMFacadeNative. 35 36 @param resource: A FacadeResource object. 37 """ 38 self._resource = resource 39 40 41 def enroll_device(self): 42 """Enroll device into CFM.""" 43 self._resource.start_custom_chrome({"auto_login": False, 44 "disable_gaia_services": False}) 45 enrollment.RemoraEnrollment(self._resource._browser, self._USER_ID, 46 self._PWD) 47 # Timeout to allow for the device to stablize and go back to the 48 # login screen before proceeding. 49 time.sleep(self._ENROLLMENT_DELAY) 50 self.restart_chrome_for_cfm() 51 self.check_hangout_extension_context() 52 53 54 def restart_chrome_for_cfm(self): 55 """Restart chrome with custom values for CFM.""" 56 custom_chrome_setup = {"clear_enterprise_policy": False, 57 "dont_override_profile": True, 58 "disable_gaia_services": False, 59 "disable_default_apps": False, 60 "auto_login": False} 61 self._resource.start_custom_chrome(custom_chrome_setup) 62 63 64 def check_hangout_extension_context(self): 65 """Check to make sure hangout app launched. 66 67 @raises error.TestFail if the URL checks fails. 68 """ 69 ext_contexts = kiosk_utils.wait_for_kiosk_ext( 70 self._resource._browser, self._EXT_ID) 71 ext_urls = set([context.EvaluateJavaScript('location.href;') 72 for context in ext_contexts]) 73 if len(ext_urls) == 2: 74 expected_urls = set( 75 ['chrome-extension://' + self._EXT_ID + '/' + path 76 for path in ['hangoutswindow.html?windowid=0', 77 '_generated_background_page.html']]) 78 if len(ext_urls) == 3: 79 expected_urls = set( 80 ['chrome-extension://' + self._EXT_ID + '/' + path 81 for path in ['hangoutswindow.html?windowid=0', 82 'hangoutswindow.html?windowid=1', 83 '_generated_background_page.html']]) 84 if expected_urls != ext_urls: 85 raise error.TestFail( 86 'Unexpected extension context urls, expected %s, got %s' 87 % (expected_urls, ext_urls)) 88 89 90 def skip_oobe_after_enrollment(self): 91 """Skips oobe and goes to the app landing page after enrollment.""" 92 self.restart_chrome_for_cfm() 93 self.wait_for_hangouts_telemetry_commands() 94 self.wait_for_oobe_start_page() 95 self.skip_oobe_screen() 96 97 98 @property 99 def _webview_context(self): 100 """Get webview context object.""" 101 return kiosk_utils.get_webview_context( 102 self._resource._browser, self._EXT_ID) 103 104 105 @property 106 def cfmApi(self): 107 """Instantiate appropriate cfm api wrapper""" 108 if self._webview_context.EvaluateJavaScript( 109 "typeof window.hrRunDiagnosticsForTest == 'function'"): 110 return cfm_hangouts_api.CfmHangoutsAPI(self._webview_context) 111 return cfm_meetings_api.CfmMeetingsAPI(self._webview_context) 112 113 114 #TODO: This is a legacy api. Deprecate this api and update existing hotrod 115 # tests to use the new wait_for_hangouts_telemetry_commands api. 116 def wait_for_telemetry_commands(self): 117 """Wait for telemetry commands.""" 118 self.wait_for_hangouts_telemetry_commands() 119 120 121 def wait_for_hangouts_telemetry_commands(self): 122 """Wait for Hangouts App telemetry commands.""" 123 self._webview_context.WaitForJavaScriptCondition( 124 "typeof window.hrOobIsStartPageForTest == 'function'", 125 timeout=self._DEFAULT_TIMEOUT) 126 127 128 def wait_for_meetings_telemetry_commands(self): 129 """Wait for Meet App telemetry commands """ 130 self._webview_context.WaitForJavaScriptCondition( 131 'window.hasOwnProperty("hrTelemetryApi")', 132 timeout=self._DEFAULT_TIMEOUT) 133 134 135 def wait_for_meetings_in_call_page(self): 136 """Waits for the in-call page to launch.""" 137 self.wait_for_meetings_telemetry_commands() 138 self.cfmApi.wait_for_meetings_in_call_page() 139 140 141 def wait_for_meetings_landing_page(self): 142 """Waits for the landing page screen.""" 143 self.wait_for_meetings_telemetry_commands() 144 self.cfmApi.wait_for_meetings_landing_page() 145 146 147 # UI commands/functions 148 def wait_for_oobe_start_page(self): 149 """Wait for oobe start screen to launch.""" 150 self.cfmApi.wait_for_oobe_start_page() 151 152 153 def skip_oobe_screen(self): 154 """Skip Chromebox for Meetings oobe screen.""" 155 self.cfmApi.skip_oobe_screen() 156 157 158 def is_oobe_start_page(self): 159 """Check if device is on CFM oobe start screen. 160 161 @return a boolean, based on oobe start page status. 162 """ 163 return self.cfmApi.is_oobe_start_page() 164 165 166 # Hangouts commands/functions 167 def start_new_hangout_session(self, session_name): 168 """Start a new hangout session. 169 170 @param session_name: Name of the hangout session. 171 """ 172 self.cfmApi.start_new_hangout_session(session_name) 173 174 175 def end_hangout_session(self): 176 """End current hangout session.""" 177 self.cfmApi.end_hangout_session() 178 179 180 def is_in_hangout_session(self): 181 """Check if device is in hangout session. 182 183 @return a boolean, for hangout session state. 184 """ 185 return self.cfmApi.is_in_hangout_session() 186 187 188 def is_ready_to_start_hangout_session(self): 189 """Check if device is ready to start a new hangout session. 190 191 @return a boolean for hangout session ready state. 192 """ 193 return self.cfmApi.is_ready_to_start_hangout_session() 194 195 196 def join_meeting_session(self, session_name): 197 """Joins a meeting. 198 199 @param session_name: Name of the meeting session. 200 """ 201 self.cfmApi.join_meeting_session(session_name) 202 203 204 def start_meeting_session(self): 205 """Start a meeting.""" 206 self.cfmApi.start_meeting_session() 207 208 209 def end_meeting_session(self): 210 """End current meeting session.""" 211 self.cfmApi.end_meeting_session() 212 213 214 # Diagnostics commands/functions 215 def is_diagnostic_run_in_progress(self): 216 """Check if hotrod diagnostics is running. 217 218 @return a boolean for diagnostic run state. 219 """ 220 return self.cfmApi.is_diagnostic_run_in_progress() 221 222 223 def wait_for_diagnostic_run_to_complete(self): 224 """Wait for hotrod diagnostics to complete.""" 225 self.cfmApi.wait_for_diagnostic_run_to_complete() 226 227 228 def run_diagnostics(self): 229 """Run hotrod diagnostics.""" 230 self.cfmApi.run_diagnostics() 231 232 233 def get_last_diagnostics_results(self): 234 """Get latest hotrod diagnostics results. 235 236 @return a dict with diagnostic test results. 237 """ 238 return self.cfmApi.get_last_diagnostics_results() 239 240 241 # Mic audio commands/functions 242 def is_mic_muted(self): 243 """Check if mic is muted. 244 245 @return a boolean for mic mute state. 246 """ 247 return self.cfmApi.is_mic_muted() 248 249 250 def mute_mic(self): 251 """Local mic mute from toolbar.""" 252 self.cfmApi.mute_mic() 253 254 255 def unmute_mic(self): 256 """Local mic unmute from toolbar.""" 257 self.cfmApi.unmute_mic() 258 259 260 def remote_mute_mic(self): 261 """Remote mic mute request from cPanel.""" 262 self.cfmApi.remote_mute_mic() 263 264 265 def remote_unmute_mic(self): 266 """Remote mic unmute request from cPanel.""" 267 self.cfmApi.remote_unmute_mic() 268 269 270 def get_mic_devices(self): 271 """Get all mic devices detected by hotrod. 272 273 @return a list of mic devices. 274 """ 275 return self.cfmApi.get_mic_devices() 276 277 278 def get_preferred_mic(self): 279 """Get mic preferred for hotrod. 280 281 @return a str with preferred mic name. 282 """ 283 return self.cfmApi.get_preferred_mic() 284 285 286 def set_preferred_mic(self, mic): 287 """Set preferred mic for hotrod. 288 289 @param mic: String with mic name. 290 """ 291 self.cfmApi.set_preferred_mic(mic) 292 293 294 # Speaker commands/functions 295 def get_speaker_devices(self): 296 """Get all speaker devices detected by hotrod. 297 298 @return a list of speaker devices. 299 """ 300 return self.cfmApi.get_speaker_devices() 301 302 303 def get_preferred_speaker(self): 304 """Get speaker preferred for hotrod. 305 306 @return a str with preferred speaker name. 307 """ 308 return self.cfmApi.get_preferred_speaker() 309 310 311 def set_preferred_speaker(self, speaker): 312 """Set preferred speaker for hotrod. 313 314 @param speaker: String with speaker name. 315 """ 316 self.cfmApi.set_preferred_speaker(speaker) 317 318 319 def set_speaker_volume(self, volume_level): 320 """Set speaker volume. 321 322 @param volume_level: String value ranging from 0-100 to set volume to. 323 """ 324 self.cfmApi.set_speaker_volume(volume_level) 325 326 327 def get_speaker_volume(self): 328 """Get current speaker volume. 329 330 @return a str value with speaker volume level 0-100. 331 """ 332 return self.cfmApi.get_speaker_volume() 333 334 335 def play_test_sound(self): 336 """Play test sound.""" 337 self.cfmApi.play_test_sound() 338 339 340 # Camera commands/functions 341 def get_camera_devices(self): 342 """Get all camera devices detected by hotrod. 343 344 @return a list of camera devices. 345 """ 346 return self.cfmApi.get_camera_devices() 347 348 349 def get_preferred_camera(self): 350 """Get camera preferred for hotrod. 351 352 @return a str with preferred camera name. 353 """ 354 return self.cfmApi.get_preferred_camera() 355 356 357 def set_preferred_camera(self, camera): 358 """Set preferred camera for hotrod. 359 360 @param camera: String with camera name. 361 """ 362 self.cfmApi.set_preferred_camera(camera) 363 364 365 def is_camera_muted(self): 366 """Check if camera is muted (turned off). 367 368 @return a boolean for camera muted state. 369 """ 370 return self.cfmApi.is_camera_muted() 371 372 373 def mute_camera(self): 374 """Turned camera off.""" 375 self.cfmApi.mute_camera() 376 377 378 def unmute_camera(self): 379 """Turned camera on.""" 380 self.cfmApi.unmute_camera() 381