OLD | NEW |
(Empty) | |
| 1 # Copyright (c) 2012 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. |
| 4 |
| 5 """Chromoting helper to install/uninstall host and replace pref pane.""" |
| 6 |
| 7 import abc |
| 8 import os |
| 9 import shutil |
| 10 import sys |
| 11 import subprocess |
| 12 |
| 13 |
| 14 class ChromotingHelper(object): |
| 15 """Chromoting helper base class.""" |
| 16 __metaclass__ = abc.ABCMeta |
| 17 |
| 18 @abc.abstractmethod |
| 19 def InstallHost(self, bin_dir): |
| 20 """Installs the chromoting host""" |
| 21 return |
| 22 |
| 23 @abc.abstractmethod |
| 24 def UninstallHost(self, bin_dir): |
| 25 """Uninstalls the chromoting host""" |
| 26 return |
| 27 |
| 28 |
| 29 class ChromotingHelperMac(ChromotingHelper): |
| 30 """Chromoting Helper class for Mac. |
| 31 |
| 32 Installs/uninstalls host and replace the pref pane for testing purpose. |
| 33 """ |
| 34 |
| 35 def InstallHost(self, bin_dir): |
| 36 """Installs host on Mac.""" |
| 37 assert os.geteuid() == 0, 'Need superuser privileges' |
| 38 |
| 39 # Run most of the steps here with login user |
| 40 login_uid = os.getuid() |
| 41 os.seteuid(login_uid) |
| 42 |
| 43 # Change the working dir to the dir that has the host zip file |
| 44 current_dir = os.getcwd() |
| 45 os.chdir(bin_dir) |
| 46 host_dir = 'remoting-me2me-host-mac' |
| 47 output_dir = os.path.join(host_dir, 'output') |
| 48 |
| 49 # Remove remoting-me2me-host-mac dir just in case |
| 50 shutil.rmtree(host_dir, True) |
| 51 |
| 52 # Unzip the host archive and prepare the files/dirs |
| 53 subprocess.call('unzip remoting-me2me-host-mac.zip', shell=True) |
| 54 subprocess.call('mkdir ' + output_dir, shell=True) |
| 55 |
| 56 # Prepare security identity for code signing purpose |
| 57 os.seteuid(0) |
| 58 key_chain = '/Library/Keychains/ChromotingTest' |
| 59 password = '1111' |
| 60 key = os.path.join(current_dir, 'chrome', 'test', |
| 61 'pyautolib', 'chromoting_key.p12') |
| 62 cert = os.path.join(current_dir, 'chrome', 'test', |
| 63 'pyautolib', 'chromoting_cert.p12') |
| 64 subprocess.call(['security', 'delete-keychain', key_chain]) |
| 65 subprocess.call(['security', 'create-keychain', '-p', |
| 66 password, key_chain]) |
| 67 subprocess.call(['security', 'import', key, |
| 68 '-k', key_chain, '-P', password, '-A']) |
| 69 subprocess.call(['security', 'import', cert, |
| 70 '-k', key_chain, '-P', password]) |
| 71 os.seteuid(login_uid) |
| 72 |
| 73 # Sign the host |
| 74 do_signing = os.path.join(host_dir, 'do_signing.sh') |
| 75 subprocess.call(do_signing + ' ' + output_dir + ' ' + host_dir + ' ' + |
| 76 key_chain + ' "Chromoting Test"', shell=True) |
| 77 |
| 78 # Remove security identify |
| 79 os.seteuid(0) |
| 80 subprocess.call(['security', 'delete-keychain', key_chain]) |
| 81 os.seteuid(login_uid) |
| 82 |
| 83 # Figure out the dmg name |
| 84 version = "" |
| 85 for output_file in os.listdir(output_dir): |
| 86 if output_file.endswith('.dmg'): |
| 87 version = os.path.basename(output_file)[len('ChromotingHost-'):-4] |
| 88 |
| 89 # Mount before installation |
| 90 dmg = os.path.join(output_dir, 'ChromotingHost-' + version + '.dmg') |
| 91 subprocess.call('hdiutil' + ' mount ' + dmg, shell=True) |
| 92 |
| 93 # Install host |
| 94 os.seteuid(0) |
| 95 mpkg = os.path.join('/Volumes', 'Chromoting Host ' + version, |
| 96 'Chromoting Host.mpkg') |
| 97 subprocess.call(['/usr/sbin/installer', '-pkg', |
| 98 mpkg, '-target', '/']) |
| 99 os.seteuid(login_uid) |
| 100 |
| 101 # Unmount after installation |
| 102 mounted = os.path.join('/Volumes', 'Chromoting Host ' + version) |
| 103 subprocess.call('hdiutil unmount "' + mounted + '"', shell=True) |
| 104 |
| 105 # Clean up remoting-me2me-host-mac dir |
| 106 shutil.rmtree(host_dir, True) |
| 107 |
| 108 # Resume the original working dir |
| 109 os.chdir(current_dir) |
| 110 |
| 111 def UninstallHost(self, bin_dir): |
| 112 """Uninstalls host on Mac.""" |
| 113 assert os.geteuid() == 0, 'Need superuser privileges' |
| 114 uninstall_app = os.path.join('/', 'Applications', |
| 115 'Chromoting Host Uninstaller.app') |
| 116 subprocess.call(['open', '-a', uninstall_app]) |
| 117 |
| 118 def ReplacePrefPaneMac(self, operation): |
| 119 """Constructs mock pref pane to replace the actual pref pane on Mac.""" |
| 120 assert os.geteuid() == 0, 'Need superuser privileges' |
| 121 |
| 122 pref_pane_dir = os.path.join('/Library', 'PreferencePanes') |
| 123 |
| 124 mock_pref_pane = os.path.join(pref_pane_dir, 'mock_pref_pane') |
| 125 pref_pane = os.path.join(pref_pane_dir, 'org.chromium.chromoting.prefPane') |
| 126 mock_pref_pane_python = os.path.join(os.getcwd(), 'chrome', 'test', |
| 127 'functional', 'chromoting', |
| 128 'mock_pref_pane.py') |
| 129 |
| 130 shutil.rmtree(mock_pref_pane, True) |
| 131 |
| 132 mock_pref_pane_file = open(mock_pref_pane, 'w') |
| 133 mock_pref_pane_file.write('#!/bin/bash\n') |
| 134 mock_pref_pane_file.write('\n') |
| 135 mock_pref_pane_file.write('suid-python' + |
| 136 ' ' + mock_pref_pane_python + ' ' + operation) |
| 137 mock_pref_pane_file.close() |
| 138 |
| 139 subprocess.call(['chmod', 'a+x', mock_pref_pane]) |
| 140 shutil.rmtree(pref_pane, True) |
| 141 subprocess.call(['ln', '-s', mock_pref_pane, pref_pane]) |
| 142 |
| 143 |
| 144 class ChromotingHelperWindows(ChromotingHelper): |
| 145 """Chromoting Helper class for Windows for installing/uninstalling host.""" |
| 146 |
| 147 def InstallHost(self, bin_dir): |
| 148 """Installs host on Windows.""" |
| 149 host_msi = os.path.join(bin_dir, 'remoting-host.msi') |
| 150 subprocess.Popen(['msiexec', '/i', host_msi, '/passive']).wait() |
| 151 |
| 152 def UninstallHost(self, bin_dir): |
| 153 """Uninstalls host on Windows.""" |
| 154 host_msi = os.path.join(bin_dir, 'remoting-host.msi') |
| 155 subprocess.Popen(['msiexec', '/x', host_msi, '/passive']).wait() |
| 156 |
| 157 |
| 158 def Main(): |
| 159 """Main function to dispatch operations.""" |
| 160 assert sys.platform.startswith('win') or \ |
| 161 sys.platform.startswith('darwin'), \ |
| 162 'Only support Windows and Mac' |
| 163 |
| 164 if sys.platform.startswith('win'): |
| 165 helper = ChromotingHelperWindows() |
| 166 elif sys.platform.startswith('darwin'): |
| 167 helper = ChromotingHelperMac() |
| 168 |
| 169 if sys.argv[1] == 'install': |
| 170 helper.InstallHost(sys.argv[2]) |
| 171 elif sys.argv[1] == 'uninstall': |
| 172 helper.UninstallHost(sys.argv[2]) |
| 173 elif sys.argv[1] in ['enable', 'disable', 'changepin']: |
| 174 assert sys.platform.startswith('darwin'), \ |
| 175 'Replacing pref pane is Mac specific' |
| 176 helper.ReplacePrefPaneMac(sys.argv[1]) |
| 177 else: |
| 178 print >>sys.stderr, 'Invalid syntax' |
| 179 return 1 |
| 180 |
| 181 |
| 182 if __name__ == '__main__': |
| 183 Main() |
OLD | NEW |