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