16
17
# with this program. If not, see <http://www.gnu.org/licenses/>.
17
18
"""Main implementation on windows."""
20
# pylint: disable=F0401
21
from _winreg import HKEY_LOCAL_MACHINE, OpenKey, QueryValueEx
21
23
from functools import wraps
23
25
from twisted.internet import defer, reactor
24
26
from twisted.internet.threads import deferToThread
25
from twisted.spread.pb import Referenceable, Root, PBClientFactory
27
# pylint: disable=F0401
28
from win32con import NameSamCompatible
29
from win32api import GetUserNameEx
30
from _winreg import OpenKey, HKEY_LOCAL_MACHINE, QueryValueEx
31
# pylint: enable=F0401
27
from twisted.spread.pb import (
33
34
from ubuntu_sso import NO_OP
34
35
from ubuntu_sso.account import Account
36
37
from ubuntu_sso.logger import setup_logging
37
38
from ubuntu_sso.main import (CredentialsManagementRoot, SSOLoginRoot,
38
39
SSOCredentialsRoot, except_to_errdict)
40
from ubuntu_sso.utils.tcpactivation import ActivationConfig, ActivationClient
41
42
logger = setup_logging("ubuntu_sso.main.windows")
42
43
NAMED_PIPE_URL = '\\\\.\\pipe\\ubuntu_sso\\%s'
43
U1_REG_PATH = r'Software\\Ubuntu One'
44
U1_REG_PATH = r'Software\Ubuntu One'
44
45
SSO_INSTALL_PATH = 'SSOInstallPath'
46
LOCALHOST = "127.0.0.1"
47
SSO_DEFAULT_PB_PORT = 50001
48
SSO_SERVICE_NAME = "ubuntu-sso-client"
51
def get_sso_pb_hostport():
52
"""Get the host and port on which the SSO pb is running."""
53
return LOCALHOST, SSO_DEFAULT_PB_PORT
47
56
def remote_handler(handler):
51
60
return lambda: None
63
def get_activation_cmdline(service_name):
64
"""Get the command line to activate an executable."""
65
key = OpenKey(HKEY_LOCAL_MACHINE, U1_REG_PATH)
66
# pylint: disable=W0612
67
value, registry_type = QueryValueEx(key, "path-" + service_name)
71
def get_activation_config():
72
"""Get the configuration to activate the sso service."""
73
_, port = get_sso_pb_hostport()
74
service_name = SSO_SERVICE_NAME
75
cmdline = get_activation_cmdline(service_name)
76
return ActivationConfig(service_name, cmdline, port)
54
79
def blocking(f, app_name, result_cb, error_cb):
55
80
"""Run f in a thread; return or throw an exception thru the callbacks."""
56
81
d = deferToThread(f)
106
131
def emit_signal(self, signal_name, *args, **kwargs):
107
132
"""Emit the given signal to the clients."""
108
133
for current_client in self.clients:
109
d = current_client.callRemote(signal_name, *args, **kwargs)
110
d.addErrback(self._emit_failure)
135
d = current_client.callRemote(signal_name, *args, **kwargs)
136
d.addErrback(self._emit_failure)
137
except DeadReferenceError:
138
self.remote_unregister_to_signals(current_client)
113
141
class SSOLogin(Referenceable, SignalBroadcaster):
312
340
def login_or_register_to_get_credentials(self, app_name,
313
341
terms_and_conditions_url,
314
help_text, window_id):
342
help_text, window_id,
343
ui_module='ubuntu_sso.qt.gui'):
315
344
"""Get credentials if found else prompt GUI to login or register.
317
346
'app_name' will be displayed in the GUI.
328
357
self.emit_credentials_found,
329
358
self._process_error,
330
359
self.emit_authorization_denied,
331
ui_module='ubuntu_sso.qt.gui')
333
362
def login_to_get_credentials(self, app_name, help_text, window_id):
334
363
"""Get credentials if found else prompt GUI just to login
911
940
self.cred_management = CredentialsManagementClient(cred_management)
912
941
defer.returnValue(self)
943
@defer.inlineCallbacks
914
944
def connect(self):
915
945
"""Connect to the sso service."""
916
# pylint: disable=W0702
918
pipe = NAMED_PIPE_URL % GetUserNameEx(NameSamCompatible)
919
# got the pipe, lets try and connect to it and get the diff
920
# remote objects for the wrappers
921
self.factory = PBClientFactory()
922
# the reactor does have a connectTCP method
923
# pylint: disable=E1101
924
self.client = reactor.connectPipe(pipe, self.factory)
925
# pylint: enable=E1101
926
d = self.factory.getRootObject()
927
d.addCallback(self._request_remote_objects)
930
logger.info('The ubuntu sso process is not running!')
931
# try to start the sso process and for that we need to know
932
# its location which should have been stored in the registry
933
key = OpenKey(HKEY_LOCAL_MACHINE, U1_REG_PATH)
934
path = QueryValueEx(key, SSO_INSTALL_PATH)[0]
935
subprocess.Popen([path, ])
936
# try to connect again
938
# pylint: disable=W0702
946
ac = ActivationClient(get_activation_config())
947
port = yield ac.get_active_port()
948
# got the port, lets try and connect to it and get the diff
949
# remote objects for the wrappers
950
self.factory = PBClientFactory()
951
# the reactor does have a connectTCP method
952
# pylint: disable=E1101
953
self.client = reactor.connectTCP(LOCALHOST, port, self.factory)
954
# pylint: enable=E1101
955
root = yield self.factory.getRootObject()
956
client = yield self._request_remote_objects(root)
957
defer.returnValue(client)
940
959
def disconnect(self):
941
960
"""Disconnect from the process."""