Home | History | Annotate | Download | only in tools
      1 #!/usr/bin/env python
      2 # Copyright 2013 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 # Interactive test script for the Chromoting host native messaging component.
      7 
      8 import json
      9 import readline
     10 import struct
     11 import subprocess
     12 import sys
     13 
     14 
     15 def PrintMenuAndGetBuilder(messages):
     16   print
     17   for i in range(0, len(messages)):
     18     print '%d: %s' % (i + 1, messages[i][0])
     19   print 'Q: Quit'
     20   while True:
     21     choice = raw_input('Enter choice: ')
     22     if choice.lower() == 'q':
     23       return None
     24     choice = int(choice)
     25     if choice >= 1 and choice <= len(messages):
     26       return messages[choice - 1][1]
     27 
     28 
     29 # Message builder methods.
     30 def BuildHello():
     31   return {'type': 'hello'}
     32 
     33 
     34 def BuildClearAllPairedClients():
     35   return {'type': 'clearPairedClients'}
     36 
     37 
     38 def BuildDeletePairedClient():
     39   client_id = raw_input('Enter client id: ')
     40   return {'type': 'deletePairedClient',
     41           'clientId': client_id}
     42 
     43 
     44 def BuildGetHostName():
     45   return {'type': 'getHostName'}
     46 
     47 
     48 def BuildGetPinHash():
     49   host_id = raw_input('Enter host id: ')
     50   pin = raw_input('Enter PIN: ')
     51   return {'type': 'getPinHash',
     52           'hostId': host_id,
     53           'pin': pin}
     54 
     55 
     56 def BuildGenerateKeyPair():
     57   return {'type': 'generateKeyPair'}
     58 
     59 
     60 def BuildUpdateDaemonConfig():
     61   config_json = raw_input('Enter config JSON: ')
     62   return {'type': 'updateDaemonConfig',
     63           'config': config_json}
     64 
     65 
     66 def BuildGetDaemonConfig():
     67   return {'type': 'getDaemonConfig'}
     68 
     69 
     70 def BuildGetPairedClients():
     71   return {'type': 'getPairedClients'}
     72 
     73 
     74 def BuildGetUsageStatsConsent():
     75   return {'type': 'getUsageStatsConsent'}
     76 
     77 
     78 def BuildStartDaemon():
     79   while True:
     80     consent = raw_input('Report usage stats [y/n]? ')
     81     if consent.lower() == 'y':
     82       consent = True
     83     elif consent.lower() == 'n':
     84       consent = False
     85     else:
     86       continue
     87     break
     88   config_json = raw_input('Enter config JSON: ')
     89   return {'type': 'startDaemon',
     90           'consent': consent,
     91           'config': config_json}
     92 
     93 
     94 def BuildStopDaemon():
     95   return {'type': 'stopDaemon'}
     96 
     97 
     98 def BuildGetDaemonState():
     99   return {'type': 'getDaemonState'}
    100 
    101 
    102 def main():
    103   if len(sys.argv) != 2:
    104     print 'Usage: ' + sys.argv[0] + ' <path to native messaging host>'
    105     sys.exit(1)
    106 
    107   native_messaging_host = sys.argv[1]
    108 
    109   child = subprocess.Popen(native_messaging_host, stdin=subprocess.PIPE,
    110                            stdout=subprocess.PIPE, close_fds=True)
    111 
    112   message_id = 0
    113   while True:
    114     messages = [
    115       ('Hello', BuildHello),
    116       ('Clear all paired clients', BuildClearAllPairedClients),
    117       ('Delete paired client', BuildDeletePairedClient),
    118       ('Get host name', BuildGetHostName),
    119       ('Get PIN hash', BuildGetPinHash),
    120       ('Generate key pair', BuildGenerateKeyPair),
    121       ('Update daemon config', BuildUpdateDaemonConfig),
    122       ('Get daemon config', BuildGetDaemonConfig),
    123       ('Get paired clients', BuildGetPairedClients),
    124       ('Get usage stats consent', BuildGetUsageStatsConsent),
    125       ('Start daemon', BuildStartDaemon),
    126       ('Stop daemon', BuildStopDaemon),
    127       ('Get daemon state', BuildGetDaemonState)
    128     ]
    129     builder = PrintMenuAndGetBuilder(messages)
    130     if not builder:
    131       break
    132     message_dict = builder()
    133     message_dict['id'] = message_id
    134     message = json.dumps(message_dict)
    135     message_id += 1
    136     print 'Message: ' + message
    137     child.stdin.write(struct.pack('I', len(message)))
    138     child.stdin.write(message)
    139     child.stdin.flush()
    140 
    141     reply_length_bytes = child.stdout.read(4)
    142     if len(reply_length_bytes) < 4:
    143       print 'Invalid message length'
    144       break
    145     reply_length = struct.unpack('i', reply_length_bytes)[0]
    146     reply = child.stdout.read(reply_length).decode('utf-8')
    147     print 'Reply: ' + reply
    148     if len(reply) != reply_length:
    149       print 'Invalid reply length'
    150       break
    151 
    152 if __name__ == '__main__':
    153   main()
    154