OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 3 # Use of this source code is governed by a BSD-style license that can be |
4 # found in the LICENSE file. | 4 # found in the LICENSE file. |
5 | 5 |
6 # Virtual Me2Me implementation. This script runs and manages the processes | 6 # Virtual Me2Me implementation. This script runs and manages the processes |
7 # required for a Virtual Me2Me desktop, which are: X server, X desktop | 7 # required for a Virtual Me2Me desktop, which are: X server, X desktop |
8 # session, and Host process. | 8 # session, and Host process. |
9 # This script is intended to run continuously as a background daemon | 9 # This script is intended to run continuously as a background daemon |
10 # process, running under an ordinary (non-root) user account. | 10 # process, running under an ordinary (non-root) user account. |
(...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
161 class Desktop: | 161 class Desktop: |
162 """Manage a single virtual desktop""" | 162 """Manage a single virtual desktop""" |
163 | 163 |
164 def __init__(self, sizes): | 164 def __init__(self, sizes): |
165 self.x_proc = None | 165 self.x_proc = None |
166 self.session_proc = None | 166 self.session_proc = None |
167 self.host_proc = None | 167 self.host_proc = None |
168 self.child_env = None | 168 self.child_env = None |
169 self.sizes = sizes | 169 self.sizes = sizes |
170 self.pulseaudio_pipe = None | 170 self.pulseaudio_pipe = None |
| 171 self.server_supports_exact_resize = False |
171 g_desktops.append(self) | 172 g_desktops.append(self) |
172 | 173 |
173 @staticmethod | 174 @staticmethod |
174 def get_unused_display_number(): | 175 def get_unused_display_number(): |
175 """Return a candidate display number for which there is currently no | 176 """Return a candidate display number for which there is currently no |
176 X Server lock file""" | 177 X Server lock file""" |
177 display = FIRST_X_DISPLAY_NUMBER | 178 display = FIRST_X_DISPLAY_NUMBER |
178 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): | 179 while os.path.exists(X_LOCK_FILE_TEMPLATE % display): |
179 display += 1 | 180 display += 1 |
180 return display | 181 return display |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
246 display = self.get_unused_display_number() | 247 display = self.get_unused_display_number() |
247 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, | 248 ret_code = subprocess.call("xauth add :%d . `mcookie`" % display, |
248 shell=True) | 249 shell=True) |
249 if ret_code != 0: | 250 if ret_code != 0: |
250 raise Exception("xauth failed with code %d" % ret_code) | 251 raise Exception("xauth failed with code %d" % ret_code) |
251 | 252 |
252 max_width = max([width for width, height in self.sizes]) | 253 max_width = max([width for width, height in self.sizes]) |
253 max_height = max([height for width, height in self.sizes]) | 254 max_height = max([height for width, height in self.sizes]) |
254 | 255 |
255 try: | 256 try: |
256 xvfb = locate_executable("Xvfb-randr") | 257 # TODO(jamiewalch): This script expects to be installed alongside |
| 258 # Xvfb-randr, but that's no longer the case. Fix this once we have |
| 259 # a Xvfb-randr package that installs somewhere sensible. |
| 260 xvfb = "/usr/bin/Xvfb-randr" |
| 261 if not os.path.exists(xvfb): |
| 262 xvfb = locate_executable("Xvfb-randr") |
| 263 self.server_supports_exact_resize = True |
257 except Exception: | 264 except Exception: |
258 xvfb = "Xvfb" | 265 xvfb = "Xvfb" |
| 266 self.server_supports_exact_resize = False |
259 | 267 |
260 logging.info("Starting %s on display :%d" % (xvfb, display)) | 268 logging.info("Starting %s on display :%d" % (xvfb, display)) |
261 screen_option = "%dx%dx24" % (max_width, max_height) | 269 screen_option = "%dx%dx24" % (max_width, max_height) |
262 self.x_proc = subprocess.Popen([xvfb, ":%d" % display, | 270 self.x_proc = subprocess.Popen([xvfb, ":%d" % display, |
263 "-noreset", | 271 "-noreset", |
264 "-auth", X_AUTH_FILE, | 272 "-auth", X_AUTH_FILE, |
265 "-nolisten", "tcp", | 273 "-nolisten", "tcp", |
266 "-screen", "0", screen_option | 274 "-screen", "0", screen_option |
267 ] + extra_x_args) | 275 ] + extra_x_args) |
268 if not self.x_proc.pid: | 276 if not self.x_proc.pid: |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
340 self._init_child_env() | 348 self._init_child_env() |
341 self._setup_pulseaudio() | 349 self._setup_pulseaudio() |
342 self._launch_x_server(x_args) | 350 self._launch_x_server(x_args) |
343 self._launch_x_session() | 351 self._launch_x_session() |
344 | 352 |
345 def launch_host(self, host_config): | 353 def launch_host(self, host_config): |
346 # Start remoting host | 354 # Start remoting host |
347 args = [locate_executable(HOST_BINARY_NAME), "--host-config=/dev/stdin"] | 355 args = [locate_executable(HOST_BINARY_NAME), "--host-config=/dev/stdin"] |
348 if self.pulseaudio_pipe: | 356 if self.pulseaudio_pipe: |
349 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) | 357 args.append("--audio-pipe-name=%s" % self.pulseaudio_pipe) |
| 358 if self.server_supports_exact_resize: |
| 359 args.append("--server-supports-exact-resize") |
350 self.host_proc = subprocess.Popen(args, env=self.child_env, | 360 self.host_proc = subprocess.Popen(args, env=self.child_env, |
351 stdin=subprocess.PIPE) | 361 stdin=subprocess.PIPE) |
352 logging.info(args) | 362 logging.info(args) |
353 if not self.host_proc.pid: | 363 if not self.host_proc.pid: |
354 raise Exception("Could not start Chrome Remote Desktop host") | 364 raise Exception("Could not start Chrome Remote Desktop host") |
355 self.host_proc.stdin.write(json.dumps(host_config.data)) | 365 self.host_proc.stdin.write(json.dumps(host_config.data)) |
356 self.host_proc.stdin.close() | 366 self.host_proc.stdin.close() |
357 | 367 |
358 | 368 |
359 class PidFile: | 369 class PidFile: |
(...skipping 234 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
594 # Exit cleanly so the atexit handler, cleanup(), gets called. | 604 # Exit cleanly so the atexit handler, cleanup(), gets called. |
595 raise SystemExit | 605 raise SystemExit |
596 | 606 |
597 | 607 |
598 def relaunch_self(): | 608 def relaunch_self(): |
599 cleanup() | 609 cleanup() |
600 os.execvp(sys.argv[0], sys.argv) | 610 os.execvp(sys.argv[0], sys.argv) |
601 | 611 |
602 | 612 |
603 def main(): | 613 def main(): |
604 DEFAULT_SIZE = "1280x800" | 614 DEFAULT_SIZE = "2560x1600" |
605 EPILOG = """This script is not intended for use by end-users. To configure | 615 EPILOG = """This script is not intended for use by end-users. To configure |
606 Chrome Remote Desktop, please install the app from the Chrome | 616 Chrome Remote Desktop, please install the app from the Chrome |
607 Web Store: https://chrome.google.com/remotedesktop""" | 617 Web Store: https://chrome.google.com/remotedesktop""" |
608 parser = optparse.OptionParser( | 618 parser = optparse.OptionParser( |
609 usage="Usage: %prog [options] [ -- [ X server options ] ]", | 619 usage="Usage: %prog [options] [ -- [ X server options ] ]", |
610 epilog=EPILOG) | 620 epilog=EPILOG) |
611 parser.add_option("-s", "--size", dest="size", action="append", | 621 parser.add_option("-s", "--size", dest="size", action="append", |
612 help="Dimensions of virtual desktop (default: %s). " | 622 help="Dimensions of virtual desktop (default: %s). " |
613 "This can be specified multiple times to make multiple " | 623 "This can be specified multiple times to make multiple " |
614 "screen resolutions available (if the Xvfb server " | 624 "screen resolutions available (if the Xvfb server " |
(...skipping 232 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
847 return 0 | 857 return 0 |
848 elif os.WEXITSTATUS(status) == 5: | 858 elif os.WEXITSTATUS(status) == 5: |
849 logging.info("Host domain is blocked by policy - exiting.") | 859 logging.info("Host domain is blocked by policy - exiting.") |
850 os.remove(host.config_file) | 860 os.remove(host.config_file) |
851 return 0 | 861 return 0 |
852 # Nothing to do for Mac-only status 6 (login screen unsupported) | 862 # Nothing to do for Mac-only status 6 (login screen unsupported) |
853 | 863 |
854 if __name__ == "__main__": | 864 if __name__ == "__main__": |
855 logging.basicConfig(level=logging.DEBUG) | 865 logging.basicConfig(level=logging.DEBUG) |
856 sys.exit(main()) | 866 sys.exit(main()) |
OLD | NEW |