| Index: tools/android/loading/log_requests.py
|
| diff --git a/tools/android/loading/log_requests.py b/tools/android/loading/log_requests.py
|
| deleted file mode 100755
|
| index ee5f0915289d579a65a6beebdc799c06dc124025..0000000000000000000000000000000000000000
|
| --- a/tools/android/loading/log_requests.py
|
| +++ /dev/null
|
| @@ -1,237 +0,0 @@
|
| -#! /usr/bin/python
|
| -# Copyright 2015 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.
|
| -
|
| -"""Loads a URL on an Android device, logging all the requests made to do it
|
| -to a JSON file using DevTools.
|
| -"""
|
| -
|
| -import contextlib
|
| -import httplib
|
| -import json
|
| -import logging
|
| -import optparse
|
| -import os
|
| -import sys
|
| -
|
| -_SRC_DIR = os.path.abspath(os.path.join(
|
| - os.path.dirname(__file__), '..', '..', '..'))
|
| -
|
| -sys.path.append(os.path.join(_SRC_DIR, 'third_party', 'catapult', 'devil'))
|
| -from devil.android import device_utils
|
| -
|
| -sys.path.append(os.path.join(_SRC_DIR, 'build', 'android'))
|
| -import devil_chromium
|
| -
|
| -sys.path.append(os.path.join(_SRC_DIR, 'tools', 'telemetry'))
|
| -from telemetry.internal.backends.chrome_inspector import inspector_websocket
|
| -from telemetry.internal.backends.chrome_inspector import websocket
|
| -
|
| -sys.path.append(os.path.join(_SRC_DIR, 'tools', 'chrome_proxy'))
|
| -from common import inspector_network
|
| -
|
| -import device_setup
|
| -
|
| -
|
| -class AndroidRequestsLogger(object):
|
| - """Logs all the requests made to load a page on a device."""
|
| -
|
| - def __init__(self, device):
|
| - """If device is None, we connect to a local chrome session."""
|
| - self.device = device
|
| - self._please_stop = False
|
| - self._main_frame_id = None
|
| - self._tracing_data = []
|
| -
|
| - def _PageDataReceived(self, msg):
|
| - """Called when a Page event is received.
|
| -
|
| - Records the main frame, and stops the recording once it has finished
|
| - loading.
|
| -
|
| - Args:
|
| - msg: (dict) Message sent by DevTools.
|
| - """
|
| - if 'params' not in msg:
|
| - return
|
| - params = msg['params']
|
| - method = msg.get('method', None)
|
| - if method == 'Page.frameStartedLoading' and self._main_frame_id is None:
|
| - self._main_frame_id = params['frameId']
|
| - elif (method == 'Page.frameStoppedLoading'
|
| - and params['frameId'] == self._main_frame_id):
|
| - self._please_stop = True
|
| -
|
| - def _TracingDataReceived(self, msg):
|
| - self._tracing_data.append(msg)
|
| -
|
| - def _LogPageLoadInternal(self, url, clear_cache):
|
| - """Returns the collection of requests made to load a given URL.
|
| -
|
| - Assumes that DevTools is available on http://localhost:DEVTOOLS_PORT.
|
| -
|
| - Args:
|
| - url: URL to load.
|
| - clear_cache: Whether to clear the HTTP cache.
|
| -
|
| - Returns:
|
| - [inspector_network.InspectorNetworkResponseData, ...]
|
| - """
|
| - self._main_frame_id = None
|
| - self._please_stop = False
|
| - r = httplib.HTTPConnection(
|
| - device_setup.DEVTOOLS_HOSTNAME, device_setup.DEVTOOLS_PORT)
|
| - r.request('GET', '/json')
|
| - response = r.getresponse()
|
| - if response.status != 200:
|
| - logging.error('Cannot connect to the remote target.')
|
| - return None
|
| - json_response = json.loads(response.read())
|
| - r.close()
|
| - websocket_url = json_response[0]['webSocketDebuggerUrl']
|
| - ws = inspector_websocket.InspectorWebsocket()
|
| - ws.Connect(websocket_url)
|
| - inspector = inspector_network.InspectorNetwork(ws)
|
| - if clear_cache:
|
| - inspector.ClearCache()
|
| - ws.SyncRequest({'method': 'Page.enable'})
|
| - ws.RegisterDomain('Page', self._PageDataReceived)
|
| - inspector.StartMonitoringNetwork()
|
| - ws.SendAndIgnoreResponse({'method': 'Page.navigate',
|
| - 'params': {'url': url}})
|
| - while not self._please_stop:
|
| - try:
|
| - ws.DispatchNotifications()
|
| - except websocket.WebSocketTimeoutException as e:
|
| - logging.warning('Exception: ' + str(e))
|
| - break
|
| - if not self._please_stop:
|
| - logging.warning('Finished with timeout instead of page load')
|
| - inspector.StopMonitoringNetwork()
|
| - return inspector.GetResponseData()
|
| -
|
| - def _LogTracingInternal(self, url):
|
| - self._main_frame_id = None
|
| - self._please_stop = False
|
| - r = httplib.HTTPConnection('localhost', device_setup.DEVTOOLS_PORT)
|
| - r.request('GET', '/json')
|
| - response = r.getresponse()
|
| - if response.status != 200:
|
| - logging.error('Cannot connect to the remote target.')
|
| - return None
|
| - json_response = json.loads(response.read())
|
| - r.close()
|
| - websocket_url = json_response[0]['webSocketDebuggerUrl']
|
| - ws = inspector_websocket.InspectorWebsocket()
|
| - ws.Connect(websocket_url)
|
| - ws.RegisterDomain('Tracing', self._TracingDataReceived)
|
| - logging.warning('Tracing.start: ' +
|
| - str(ws.SyncRequest({'method': 'Tracing.start',
|
| - 'options': 'zork'})))
|
| - ws.SendAndIgnoreResponse({'method': 'Page.navigate',
|
| - 'params': {'url': url}})
|
| - while not self._please_stop:
|
| - try:
|
| - ws.DispatchNotifications()
|
| - except websocket.WebSocketTimeoutException:
|
| - break
|
| - if not self._please_stop:
|
| - logging.warning('Finished with timeout instead of page load')
|
| - return {'events': self._tracing_data,
|
| - 'end': ws.SyncRequest({'method': 'Tracing.end'})}
|
| -
|
| -
|
| - def LogPageLoad(self, url, clear_cache, package):
|
| - """Returns the collection of requests made to load a given URL on a device.
|
| -
|
| - Args:
|
| - url: (str) URL to load on the device.
|
| - clear_cache: (bool) Whether to clear the HTTP cache.
|
| -
|
| - Returns:
|
| - See _LogPageLoadInternal().
|
| - """
|
| - return device_setup.SetUpAndExecute(
|
| - self.device, package,
|
| - lambda: self._LogPageLoadInternal(url, clear_cache))
|
| -
|
| - def LogTracing(self, url):
|
| - """Log tracing events from a load of the given URL.
|
| -
|
| - TODO(mattcary): This doesn't work. It would be best to log tracing
|
| - simultaneously with network requests, but as that wasn't working the tracing
|
| - logging was broken out separately. It still doesn't work...
|
| - """
|
| - return device_setup.SetUpAndExecute(
|
| - self.device, 'chrome', lambda: self._LogTracingInternal(url))
|
| -
|
| -
|
| -def _ResponseDataToJson(data):
|
| - """Converts a list of inspector_network.InspectorNetworkResponseData to JSON.
|
| -
|
| - Args:
|
| - data: as returned by _LogPageLoad()
|
| -
|
| - Returns:
|
| - A JSON file with the following format:
|
| - [request1, request2, ...], and a request is:
|
| - {'status': str, 'headers': dict, 'request_headers': dict,
|
| - 'timestamp': double, 'timing': dict, 'url': str,
|
| - 'served_from_cache': bool, 'initiator': str})
|
| - """
|
| - result = []
|
| - for r in data:
|
| - result.append({'status': r.status,
|
| - 'headers': r.headers,
|
| - 'request_headers': r.request_headers,
|
| - 'timestamp': r.timestamp,
|
| - 'timing': r.timing,
|
| - 'url': r.url,
|
| - 'served_from_cache': r.served_from_cache,
|
| - 'initiator': r.initiator})
|
| - return json.dumps(result)
|
| -
|
| -
|
| -def _CreateOptionParser():
|
| - """Returns the option parser for this tool."""
|
| - parser = optparse.OptionParser(description='Starts a browser on an Android '
|
| - 'device, gathers the requests made to load a '
|
| - 'page and dumps it to a JSON file.')
|
| - parser.add_option('--url', help='URL to load.',
|
| - default='https://www.google.com', metavar='URL')
|
| - parser.add_option('--output', help='Output file.', default='result.json')
|
| - parser.add_option('--no-clear-cache', help=('Do not clear the HTTP cache '
|
| - 'before loading the URL.'),
|
| - default=True, action='store_false', dest='clear_cache')
|
| - parser.add_option('--package', help='Package info for chrome build. '
|
| - 'See build/android/pylib/constants.',
|
| - default='chrome')
|
| - parser.add_option('--local', action='store_true', default=False,
|
| - help='Connect to local chrome session rather than android.')
|
| - return parser
|
| -
|
| -
|
| -def main():
|
| - logging.basicConfig(level=logging.WARNING)
|
| - parser = _CreateOptionParser()
|
| - options, _ = parser.parse_args()
|
| -
|
| - devil_chromium.Initialize()
|
| -
|
| - if options.local:
|
| - device = None
|
| - else:
|
| - devices = device_utils.DeviceUtils.HealthyDevices()
|
| - device = devices[0]
|
| -
|
| - request_logger = AndroidRequestsLogger(device)
|
| - response_data = request_logger.LogPageLoad(
|
| - options.url, options.clear_cache, options.package)
|
| - json_data = _ResponseDataToJson(response_data)
|
| - with open(options.output, 'w') as f:
|
| - f.write(json_data)
|
| -
|
| -
|
| -if __name__ == '__main__':
|
| - main()
|
|
|