aboutsummaryrefslogtreecommitdiff
path: root/catapult/telemetry/telemetry/internal/backends/chrome/ios_browser_backend.py
blob: fac37cb2e7fab7568f9a413f0ce583feef1fa333 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
# Copyright 2014 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 contextlib
import json
import logging
import re
import urllib2

from telemetry.internal.backends.chrome import chrome_browser_backend
from telemetry.internal.backends.chrome import system_info_backend

import py_utils


class IosBrowserBackend(chrome_browser_backend.ChromeBrowserBackend):
  _DEBUGGER_URL_BUILDER = 'ws://localhost:%i/devtools/page/%i'
  _DEBUGGER_URL_REGEX = r'ws://localhost:(\d+)/devtools/page/(\d+)'
  _DEVICE_LIST_URL = 'http://localhost:9221/json'

  def __init__(self, ios_platform_backend, browser_options):
    browser_options.output_profile_path = '.'
    super(IosBrowserBackend, self).__init__(
        ios_platform_backend,
        supports_tab_control=False,
        supports_extensions=False,
        browser_options=browser_options)
    self._webviews = []
    self._port = None
    self._page = None
    self._system_info_backend = None
    self.UpdateRunningBrowsersInfo()

  def UpdateRunningBrowsersInfo(self):
    """ Refresh to match current state of the running browser.
    """
    device_urls = self.GetDeviceUrls()
    urls = self.GetWebSocketDebuggerUrls(device_urls)
    for url in urls:
      m = re.match(self._DEBUGGER_URL_REGEX, url)
      if m:
        self._webviews.append([int(m.group(1)), int(m.group(2))])
      else:
        logging.error('Unexpected url format: %s' % url)

    # TODO(baxley): For now, grab first item from |_webviews|. Ideally, we'd
    # prefer to have the currently displayed tab, or something similar.
    if self._webviews:
      self._port = self._webviews[0][0]
      self._page = self._webviews[0][1]

  def GetDeviceUrls(self):
    device_urls = []
    try:
      with contextlib.closing(
          urllib2.urlopen(self._DEVICE_LIST_URL)) as device_list:
        json_urls = device_list.read()
        device_urls = json.loads(json_urls)
        if not device_urls:
          logging.debug('No iOS devices found. Will not try searching for iOS '
                        'browsers.')
          return []
    except urllib2.URLError as e:
      logging.debug('Error communicating with iOS device.')
      logging.debug(str(e))
      return []
    return device_urls

  def GetWebSocketDebuggerUrls(self, device_urls):
    """ Get a list of the websocket debugger URLs to communicate with
        all running UIWebViews.
    """
    data = []
    # Loop through all devices.
    for d in device_urls:
      def GetData():
        try:
          with contextlib.closing(
              # pylint: disable=cell-var-from-loop
              urllib2.urlopen('http://%s/json' % d['url'])) as f:
            json_result = f.read()
            data = json.loads(json_result)
            return data
        except urllib2.URLError as e:
          logging.debug('Error communicating with iOS device.')
          logging.debug(e)
          return False
      try:
        # Retry a few times since it can take a few seconds for this API to be
        # ready, if ios_webkit_debug_proxy is just launched.
        data = py_utils.WaitFor(GetData, 5)
      except py_utils.TimeoutException as e:
        logging.debug('Timeout retrieving data from iOS device')
        logging.debug(e)
        return []

    # Find all running UIWebViews.
    debug_urls = []
    for j in data:
      debug_urls.append(j['webSocketDebuggerUrl'])

    return debug_urls

  def GetSystemInfo(self):
    if self._system_info_backend is None:
      self._system_info_backend = system_info_backend.SystemInfoBackend(
          self._port, self._page)
    return self._system_info_backend.GetSystemInfo()

  def IsBrowserRunning(self):
    return bool(self._webviews)

  #TODO(baxley): The following were stubbed out to get the sunspider benchmark
  # running. These should be implemented.
  @property
  def browser_directory(self):
    logging.warn('Not implemented')
    return None

  @property
  def profile_directory(self):
    logging.warn('Not implemented')
    return None

  def Start(self):
    logging.warn('Not implemented')

  def extension_backend(self):
    logging.warn('Not implemented')
    return None

  def GetBrowserStartupArgs(self):
    logging.warn('Not implemented')
    return None

  def HasBrowserFinishedLaunching(self):
    logging.warn('Not implemented')
    return False

  def GetStandardOutput(self):
    raise NotImplementedError()

  def GetStackTrace(self):
    raise NotImplementedError()

  def GetMostRecentMinidumpPath(self):
    return None

  def GetAllMinidumpPaths(self):
    return None

  def GetAllUnsymbolizedMinidumpPaths(self):
    return None

  def SymbolizeMinidump(self, minidump_path):
    return None