testing/marionette/transport/marionette_transport/transport.py

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 # This Source Code Form is subject to the terms of the Mozilla Public
     2 # License, v. 2.0. If a copy of the MPL was not distributed with this
     3 # file, You can obtain one at http://mozilla.org/MPL/2.0/.
     5 import errno
     6 import json
     7 import socket
    10 class MarionetteTransport(object):
    11     """ The Marionette socket client.  This speaks the same protocol
    12         as the remote debugger inside Gecko, in which messages are
    13         always preceded by the message length and a colon, e.g.,
    15         20:{'command': 'test'}
    16     """
    18     max_packet_length = 4096
    19     connection_lost_msg = "Connection to Marionette server is lost. Check gecko.log (desktop firefox) or logcat (b2g) for errors."
    21     def __init__(self, addr, port):
    22         self.addr = addr
    23         self.port = port
    24         self.sock = None
    25         self.traits = None
    26         self.applicationType = None
    27         self.actor = 'root'
    29     def _recv_n_bytes(self, n):
    30         """ Convenience method for receiving exactly n bytes from
    31             self.sock (assuming it's open and connected).
    32         """
    33         data = ''
    34         while len(data) < n:
    35             chunk = self.sock.recv(n - len(data))
    36             if chunk == '':
    37                 break
    38             data += chunk
    39         return data
    41     def receive(self):
    42         """ Receive the next complete response from the server, and return
    43             it as a dict.  Each response from the server is prepended by
    44             len(message) + ':'.
    45         """
    46         assert(self.sock)
    47         response = self.sock.recv(10)
    48         sep = response.find(':')
    49         length = response[0:sep]
    50         if length != '':
    51             response = response[sep + 1:]
    52             response += self._recv_n_bytes(int(length) + 1 + len(length) - 10)
    53             return json.loads(response)
    54         else:
    55             raise IOError(self.connection_lost_msg)
    57     def connect(self, timeout=360.0):
    58         """ Connect to the server and process the hello message we expect
    59             to receive in response.
    60         """
    61         self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    62         self.sock.settimeout(timeout)
    63         try:
    64             self.sock.connect((self.addr, self.port))
    65         except:
    66             # Unset self.sock so that the next attempt to send will cause
    67             # another connection attempt.
    68             self.sock = None
    69             raise
    70         hello = self.receive()
    71         self.traits = hello.get('traits')
    72         self.applicationType = hello.get('applicationType')
    74         # get the marionette actor id
    75         response = self.send({'to': 'root', 'name': 'getMarionetteID'})
    76         self.actor = response['id']
    78     def send(self, msg):
    79         """ Send a message on the socket, prepending it with len(msg) + ':'.
    80         """
    81         if not self.sock:
    82             self.connect()
    83         if 'to' not in msg:
    84             msg['to'] = self.actor
    85         data = json.dumps(msg)
    86         data = '%s:%s' % (len(data), data)
    88         for packet in [data[i:i + self.max_packet_length] for i in
    89                        range(0, len(data), self.max_packet_length)]:
    90             try: 
    91                 self.sock.send(packet)
    92             except IOError as e:
    93                 if e.errno == errno.EPIPE:
    94                     raise IOError("%s: %s" % (str(e)), self.connection_lost_msg)
    95                 else:
    96                     raise e
    98         response = self.receive()
    99         return response
   101     def close(self):
   102         """ Close the socket.
   103         """
   104         if self.sock:
   105             self.sock.close()
   106         self.sock = None

mercurial