Index: tools/chrome_remote_control/chrome_remote_control/tab.py |
diff --git a/tools/chrome_remote_control/chrome_remote_control/tab.py b/tools/chrome_remote_control/chrome_remote_control/tab.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..1c85ecde589c88f8374781cdf452e256476f5d4a |
--- /dev/null |
+++ b/tools/chrome_remote_control/chrome_remote_control/tab.py |
@@ -0,0 +1,102 @@ |
+# Copyright (c) 2012 The Chromium Authors. All rights reserved. |
+# Use of this source code is governed by a BSD-style license that can be |
+# found in the LICENSE file. |
+ |
+import json |
+import time |
+import websocket |
+import socket |
+ |
+class EvaluateException(Exception): |
+ pass |
+ |
+class Tab(object): |
+ def __init__(self, browser, descriptor): |
+ self._browser = browser |
+ self._descriptor = descriptor |
+ self._socket = websocket.create_connection( |
+ descriptor["webSocketDebuggerUrl"]); |
+ self._socket.settimeout(0.5) |
+ self._next_request_id = 0 |
+ |
+ def __enter__(self): |
+ return self |
+ |
+ def __exit__(self, *args): |
+ if self._socket: |
+ self.Close() |
+ |
+ def Close(self): |
+ self._socket.close() |
+ self._socket = None |
+ self._browser = None |
+ |
+ def _SyncRequest(self, req): |
+ req["id"] = self._next_request_id |
+ self._next_request_id += 1 |
+ self._socket.send(json.dumps(req)) |
+ while True: |
+ try: |
+ data = self._socket.recv() |
+ except socket.error: |
+ req["id"] = self._next_request_id |
+ self._next_request_id += 1 |
+ self._socket.send(json.dumps(req)) |
+ continue |
+ res = json.loads(data) |
+ if "method" in res: |
+ continue |
+ |
+ if res["id"] != req["id"]: |
+ continue |
+ return res |
+ |
+ def RuntimeEvaluate(self, expr): |
+ request = { |
+ "method": "Runtime.evaluate", |
+ "params": { |
+ "expression": expr, |
+ "returnByValue": True |
+ } |
+ } |
+ res = self._SyncRequest(request) |
+ if res["result"]["wasThrown"]: |
+ # TODO(nduca): propagate stacks from javascript up to the python |
+ # exception. |
+ raise EvaluateException(res["result"]["result"]["description"]) |
+ if res["result"]["result"]["type"] == 'undefined': |
+ return None |
+ return res["result"]["result"]["value"] |
+ |
+ def BeginToLoadURL(self, url): |
+ # In order to tell when the document has actually changed, |
+ # we go to about:blank first and wait. When that has happened, we |
+ # to go the new URL and detect the document being non-about:blank as |
+ # indication that the new document is loading. |
+ self.RuntimeEvaluate("document.location = 'about:blank';") |
+ while True: |
+ hr = self.RuntimeEvaluate("document.location.href") |
+ if hr == "about:blank": |
+ break |
+ time.sleep(0.01) |
+ |
+ self.RuntimeEvaluate("document.location = '%s';" % url) |
+ while True: |
+ hr = self.RuntimeEvaluate("document.location.href") |
+ if hr != "about:blank": |
+ break |
+ time.sleep(0.01) |
+ |
+ def WaitForDocumentReadyStateToBeComplete(self): |
+ while True: |
+ rs = self.RuntimeEvaluate("document.readyState") |
+ if rs == 'complete': |
+ break |
+ time.sleep(0.01) |
+ |
+ def WaitForDocumentReadyStateToBeInteractiveOrBetter(self): |
+ while True: |
+ rs = self.RuntimeEvaluate("document.readyState") |
+ if rs == 'complete' or rs == 'interactive': |
+ break |
+ time.sleep(0.01) |