1 # Copyright 2015 The Chromium 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.
5 """ Script that exercises the Smart Lock setup flow, testing that a nearby phone
6 can be found and used to unlock a Chromebook.
8 Note: This script does not currently automate Android phones, so make sure that
9 a phone is properly configured and online before starting the test.
12 python setup_test.py --remote_address REMOTE_ADDRESS
17 [--cryptauth_staging_url STAGING_URL]
18 If |--app_path| is provided, then a copy of the Smart Lock app on the local
19 machine will be used instead of the app on the ChromeOS device.
31 logger
= logging
.getLogger('proximity_auth.%s' % __name__
)
33 class SmartLockSetupError(Exception):
36 def pingable_address(address
):
38 subprocess
.check_output(['ping', '-c', '1', '-W', '1', address
])
39 except subprocess
.CalledProcessError
:
40 raise argparse
.ArgumentError('%s cannot be reached.' % address
)
44 tokens
= arg
.lower().split('@')
45 if len(tokens
) != 2 or '.' not in tokens
[1]:
46 raise argparse
.ArgumentError('%s is not a valid email address' % arg
)
48 if domain
== 'gmail.com':
49 name
= name
.replace('.', '')
50 return '@'.join([name
, domain
])
53 if not os
.path
.isdir(path
):
54 raise argparse
.ArgumentError('%s is not a directory' % path
)
58 parser
= argparse
.ArgumentParser(prog
='python setup_test.py')
59 parser
.add_argument('--remote_address', required
=True, type=pingable_address
)
60 parser
.add_argument('--username', required
=True, type=email
)
61 parser
.add_argument('--password', required
=True)
62 parser
.add_argument('--ssh_port', type=int)
63 parser
.add_argument('--app_path', type=directory
)
64 parser
.add_argument('--cryptauth_staging_url', type=str)
65 args
= parser
.parse_args()
68 def CheckCryptAuthState(access_token
):
69 cryptauth_client
= cryptauth
.CryptAuthClient(access_token
)
71 # Check if we can make CryptAuth requests.
72 if cryptauth_client
.GetMyDevices() is None:
73 logger
.error('Cannot reach CryptAuth on test machine.')
76 if cryptauth_client
.GetUnlockKey() is not None:
77 logger
.info('Smart Lock currently enabled, turning off on Cryptauth...')
78 if not cryptauth_client
.ToggleEasyUnlock(False):
79 logger
.error('ToggleEasyUnlock request failed.')
82 result
= cryptauth_client
.FindEligibleUnlockDevices()
84 logger
.error('FindEligibleUnlockDevices request failed')
86 eligibleDevices
, _
= result
87 if len(eligibleDevices
) == 0:
88 logger
.warn('No eligible phones found, trying to ping phones...')
89 result
= cryptauth_client
.PingPhones()
90 if result
is None or not len(result
[0]):
91 logger
.error('Pinging phones failed :(')
94 logger
.info('Pinging phones succeeded!')
96 logger
.info('Found eligible device: %s' % (
97 eligibleDevices
[0]['friendlyDeviceName']))
100 def _NavigateSetupDialog(chromeos
, app
):
101 logger
.info('Scanning for nearby phones...')
102 btmon
= chromeos
.RunBtmon()
103 find_phone_success
= app
.FindPhone()
106 if not find_phone_success
:
107 fd
, filepath
= tempfile
.mkstemp(prefix
='btmon-')
108 os
.write(fd
, btmon
.stdout
.read())
110 logger
.info('Logs for btmon can be found at %s' % filepath
)
111 raise SmartLockSetupError("Failed to find nearby phone.")
113 logger
.info('Phone found! Starting pairing...')
114 if not app
.PairPhone():
115 raise SmartLockSetupError("Failed to pair with phone.")
116 logger
.info('Pairing success! Starting trial run...')
119 logger
.info('Unlocking for trial run...')
120 lock_screen
= chromeos
.GetAccountPickerScreen()
121 lock_screen
.WaitForSmartLockState(
122 lock_screen
.SmartLockState
.AUTHENTICATED
)
123 lock_screen
.UnlockWithClick()
125 logger
.info('Trial run success! Dismissing app...')
128 def RunSetupTest(args
):
129 logger
.info('Starting test for %s at %s' % (
130 args
.username
, args
.remote_address
))
131 if args
.app_path
is not None:
132 logger
.info('Replacing Smart Lock app with %s' % args
.app_path
)
134 chromeos
= cros
.ChromeOS(
135 args
.remote_address
, args
.username
, args
.password
, ssh_port
=args
.ssh_port
)
136 with chromeos
.Start(local_app_path
=args
.app_path
):
137 logger
.info('Chrome initialized')
139 # TODO(tengs): The access token is currently fetched from the Smart Lock
140 # app's background page. To be more robust, we should instead mint the
141 # access token ourselves.
142 if not CheckCryptAuthState(chromeos
.cryptauth_access_token
):
143 raise SmartLockSetupError('Failed to check CryptAuth state')
145 logger
.info('Opening Smart Lock settings...')
146 settings
= chromeos
.GetSmartLockSettings()
147 assert(not settings
.is_smart_lock_enabled
)
149 if args
.cryptauth_staging_url
is not None:
150 chromeos
.SetCryptAuthStaging(args
.cryptauth_staging_url
)
152 logger
.info('Starting Smart Lock setup flow...')
153 app
= settings
.StartSetupAndReturnApp()
156 raise SmartLockSetupError('Failed to obtain set up app window')
158 _NavigateSetupDialog(chromeos
, app
)
161 logging
.basicConfig()
162 logging
.getLogger('proximity_auth').setLevel(logging
.INFO
)
166 if __name__
== '__main__':