OLD | NEW |
1 #!/usr/bin/python | 1 #!/usr/bin/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. |
11 | 11 |
12 import atexit | 12 import atexit |
13 import errno | 13 import errno |
14 import getpass | 14 import getpass |
15 import hashlib | 15 import hashlib |
16 import json | 16 import json |
17 import logging | 17 import logging |
18 import optparse | 18 import optparse |
19 import os | 19 import os |
20 import signal | 20 import signal |
21 import socket | 21 import socket |
22 import subprocess | 22 import subprocess |
23 import sys | 23 import sys |
24 import tempfile | 24 import tempfile |
25 import time | 25 import time |
26 import uuid | 26 import uuid |
27 | 27 |
28 # By default this script will try to determine the most appropriate X session | |
29 # command for the system. To use a specific session instead, set this variable | |
30 # to the executable filename, or a list containing the executable and any | |
31 # arguments, for example: | |
32 # XSESSION_COMMAND = "/usr/bin/gnome-session-fallback" | |
33 # XSESSION_COMMAND = ["/usr/bin/gnome-session", "--session=ubuntu-2d"] | |
34 XSESSION_COMMAND = None | |
35 | |
36 LOG_FILE_ENV_VAR = "CHROME_REMOTE_DESKTOP_LOG_FILE" | 28 LOG_FILE_ENV_VAR = "CHROME_REMOTE_DESKTOP_LOG_FILE" |
37 | 29 |
38 # This script has a sensible default for the initial and maximum desktop size, | 30 # This script has a sensible default for the initial and maximum desktop size, |
39 # which can be overridden either on the command-line, or via a comma-separated | 31 # which can be overridden either on the command-line, or via a comma-separated |
40 # list of sizes in this environment variable. | 32 # list of sizes in this environment variable. |
41 DEFAULT_SIZES_ENV_VAR = "CHROME_REMOTE_DESKTOP_DEFAULT_DESKTOP_SIZES" | 33 DEFAULT_SIZES_ENV_VAR = "CHROME_REMOTE_DESKTOP_DEFAULT_DESKTOP_SIZES" |
42 | 34 |
43 # By default, provide a relatively small size to handle the case where resize- | 35 # By default, provide a relatively small size to handle the case where resize- |
44 # to-client is disabled, and a much larger size to support clients with large | 36 # to-client is disabled, and a much larger size to support clients with large |
45 # or mulitple monitors. These defaults can be overridden in ~/.profile. | 37 # or mulitple monitors. These defaults can be overridden in ~/.profile. |
(...skipping 302 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
348 | 340 |
349 devnull.close() | 341 devnull.close() |
350 | 342 |
351 def _launch_x_session(self): | 343 def _launch_x_session(self): |
352 # Start desktop session | 344 # Start desktop session |
353 # The /dev/null input redirection is necessary to prevent the X session | 345 # The /dev/null input redirection is necessary to prevent the X session |
354 # reading from stdin. If this code runs as a shell background job in a | 346 # reading from stdin. If this code runs as a shell background job in a |
355 # terminal, any reading from stdin causes the job to be suspended. | 347 # terminal, any reading from stdin causes the job to be suspended. |
356 # Daemonization would solve this problem by separating the process from the | 348 # Daemonization would solve this problem by separating the process from the |
357 # controlling terminal. | 349 # controlling terminal. |
358 logging.info("Launching X session: %s" % XSESSION_COMMAND) | 350 xsession_command = choose_x_session() |
359 self.session_proc = subprocess.Popen(XSESSION_COMMAND, | 351 if xsession_command is None: |
| 352 raise Exception("Unable to choose suitable X session command.") |
| 353 |
| 354 logging.info("Launching X session: %s" % xsession_command) |
| 355 self.session_proc = subprocess.Popen(xsession_command, |
360 stdin=open(os.devnull, "r"), | 356 stdin=open(os.devnull, "r"), |
361 cwd=HOME_DIR, | 357 cwd=HOME_DIR, |
362 env=self.child_env) | 358 env=self.child_env) |
363 if not self.session_proc.pid: | 359 if not self.session_proc.pid: |
364 raise Exception("Could not start X session") | 360 raise Exception("Could not start X session") |
365 | 361 |
366 def launch_session(self, x_args): | 362 def launch_session(self, x_args): |
367 self._init_child_env() | 363 self._init_child_env() |
368 self._setup_pulseaudio() | 364 self._setup_pulseaudio() |
369 self._launch_x_server(x_args) | 365 self._launch_x_server(x_args) |
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
464 | 460 |
465 This is called on process termination. | 461 This is called on process termination. |
466 """ | 462 """ |
467 if self.created: | 463 if self.created: |
468 os.remove(self.filename) | 464 os.remove(self.filename) |
469 | 465 |
470 | 466 |
471 def choose_x_session(): | 467 def choose_x_session(): |
472 """Chooses the most appropriate X session command for this system. | 468 """Chooses the most appropriate X session command for this system. |
473 | 469 |
474 If XSESSION_COMMAND is already set, its value is returned directly. | |
475 Otherwise, a session is chosen for this system. | |
476 | |
477 Returns: | 470 Returns: |
478 A string containing the command to run, or a list of strings containing | 471 A string containing the command to run, or a list of strings containing |
479 the executable program and its arguments, which is suitable for passing as | 472 the executable program and its arguments, which is suitable for passing as |
480 the first parameter of subprocess.Popen(). If a suitable session cannot | 473 the first parameter of subprocess.Popen(). If a suitable session cannot |
481 be found, returns None. | 474 be found, returns None. |
482 """ | 475 """ |
483 if XSESSION_COMMAND is not None: | |
484 return XSESSION_COMMAND | |
485 | |
486 # If the session wrapper script (see below) is given a specific session as an | 476 # If the session wrapper script (see below) is given a specific session as an |
487 # argument (such as ubuntu-2d on Ubuntu 12.04), the wrapper will run that | 477 # argument (such as ubuntu-2d on Ubuntu 12.04), the wrapper will run that |
488 # session instead of looking for custom .xsession files in the home directory. | 478 # session instead of looking for custom .xsession files in the home directory. |
489 # So it's necessary to test for these files here. | 479 # So it's necessary to test for these files here. |
490 XSESSION_FILES = [ | 480 XSESSION_FILES = [ |
491 "~/.chrome-remote-desktop-session", | 481 "~/.chrome-remote-desktop-session", |
492 "~/.xsession", | 482 "~/.xsession", |
493 "~/.Xsession" ] | 483 "~/.Xsession" ] |
494 for startup_file in XSESSION_FILES: | 484 for startup_file in XSESSION_FILES: |
495 startup_file = os.path.expanduser(startup_file) | 485 startup_file = os.path.expanduser(startup_file) |
(...skipping 364 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
860 | 850 |
861 # Enforce minimum desktop size, as a sanity-check. The limit of 100 will | 851 # Enforce minimum desktop size, as a sanity-check. The limit of 100 will |
862 # detect typos of 2 instead of 3 digits. | 852 # detect typos of 2 instead of 3 digits. |
863 if width < 100 or height < 100: | 853 if width < 100 or height < 100: |
864 raise ValueError | 854 raise ValueError |
865 except ValueError: | 855 except ValueError: |
866 parser.error("Width and height should be 100 pixels or greater") | 856 parser.error("Width and height should be 100 pixels or greater") |
867 | 857 |
868 sizes.append((width, height)) | 858 sizes.append((width, height)) |
869 | 859 |
870 # Determine the command-line to run the user's preferred X environment. | |
871 global XSESSION_COMMAND | |
872 XSESSION_COMMAND = choose_x_session() | |
873 if XSESSION_COMMAND is None: | |
874 print >> sys.stderr, "Unable to choose suitable X session command." | |
875 return 1 | |
876 | |
877 if "--session=ubuntu-2d" in XSESSION_COMMAND: | |
878 print >> sys.stderr, ( | |
879 "The Unity 2D desktop session will be used.\n" | |
880 "If you encounter problems with this choice of desktop, please install\n" | |
881 "the gnome-session-fallback package, and restart this script.\n") | |
882 | |
883 # Register an exit handler to clean up session process and the PID file. | 860 # Register an exit handler to clean up session process and the PID file. |
884 atexit.register(cleanup) | 861 atexit.register(cleanup) |
885 | 862 |
886 # Load the initial host configuration. | 863 # Load the initial host configuration. |
887 host_config = Config(options.config) | 864 host_config = Config(options.config) |
888 if (not host_config.load()): | 865 if (not host_config.load()): |
889 print >> sys.stderr, "Failed to load " + config_filename | 866 print >> sys.stderr, "Failed to load " + config_filename |
890 return 1 | 867 return 1 |
891 | 868 |
892 # Register handler to re-load the configuration in response to signals. | 869 # Register handler to re-load the configuration in response to signals. |
(...skipping 157 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1050 host_config.clear_auth() | 1027 host_config.clear_auth() |
1051 host_config.clear_host_info() | 1028 host_config.clear_host_info() |
1052 host_config.save() | 1029 host_config.save() |
1053 return 0 | 1030 return 0 |
1054 | 1031 |
1055 | 1032 |
1056 if __name__ == "__main__": | 1033 if __name__ == "__main__": |
1057 logging.basicConfig(level=logging.DEBUG, | 1034 logging.basicConfig(level=logging.DEBUG, |
1058 format="%(asctime)s:%(levelname)s:%(message)s") | 1035 format="%(asctime)s:%(levelname)s:%(message)s") |
1059 sys.exit(main()) | 1036 sys.exit(main()) |
OLD | NEW |