Publish Vulpes Preview 15 sources for desktop, Android and Tundra
Share Gaia assets and adapters, keep private profiles and development documents local, and update both public READMEs.
This commit is contained in:
parent
93e3a48004
commit
b38dea0597
25901 changed files with 9982925 additions and 369 deletions
70
tools/marionette_client.py
Normal file
70
tools/marionette_client.py
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
"""Small client for the Marionette protocol shipped with current Firefox."""
|
||||
|
||||
import json
|
||||
import socket
|
||||
import time
|
||||
|
||||
|
||||
class Client:
|
||||
def __init__(self, port=2856):
|
||||
deadline = time.monotonic() + 30
|
||||
while True:
|
||||
try:
|
||||
self.socket = socket.create_connection(("127.0.0.1", port), timeout=20)
|
||||
break
|
||||
except ConnectionRefusedError:
|
||||
if time.monotonic() >= deadline:
|
||||
raise
|
||||
time.sleep(0.2)
|
||||
self.sequence = 0
|
||||
self.quit_requested = False
|
||||
self.receive()
|
||||
self.call("WebDriver:NewSession", {"capabilities": {}})
|
||||
self.call("Marionette:SetContext", {"value": "chrome"})
|
||||
|
||||
def receive(self):
|
||||
length = bytearray()
|
||||
while not length.endswith(b":"):
|
||||
chunk = self.socket.recv(1)
|
||||
if not chunk:
|
||||
raise ConnectionError("Marionette disconnected")
|
||||
length += chunk
|
||||
remaining = int(length[:-1])
|
||||
payload = bytearray()
|
||||
while len(payload) < remaining:
|
||||
chunk = self.socket.recv(remaining - len(payload))
|
||||
if not chunk:
|
||||
raise ConnectionError("Marionette disconnected")
|
||||
payload += chunk
|
||||
return json.loads(payload)
|
||||
|
||||
def call(self, command, arguments=None):
|
||||
self.sequence += 1
|
||||
payload = json.dumps([0, self.sequence, command, arguments or {}]).encode()
|
||||
self.socket.sendall(str(len(payload)).encode() + b":" + payload)
|
||||
response = self.receive()
|
||||
if response[2]:
|
||||
raise RuntimeError(response[2])
|
||||
if command == "Marionette:Quit":
|
||||
self.quit_requested = True
|
||||
return response[3]
|
||||
|
||||
def execute(self, script):
|
||||
result = self.call(
|
||||
"WebDriver:ExecuteScript",
|
||||
{"script": script, "args": [], "newSandbox": True, "sandbox": "system"},
|
||||
)
|
||||
return result.get("value", result)
|
||||
|
||||
def close(self):
|
||||
try:
|
||||
if not self.quit_requested:
|
||||
self.call("WebDriver:DeleteSession")
|
||||
finally:
|
||||
self.socket.close()
|
||||
|
||||
def __enter__(self):
|
||||
return self
|
||||
|
||||
def __exit__(self, *args):
|
||||
self.close()
|
||||
Loading…
Reference in a new issue