blob: d7f05c6284b8234f4230449a62851695786b5264 [file] [log] [blame]
# Copyright 2016 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.
"""Device and network emulation utilities via devtools."""
import json
# Copied from
# WebKit/Source/devtools/front_end/network/NetworkConditionsSelector.js
# Units:
# download/upload: byte/s
# latency: ms
NETWORK_CONDITIONS = {
'GPRS': {
'download': 50 * 1024 / 8, 'upload': 20 * 1024 / 8, 'latency': 500},
'Regular2G': {
'download': 250 * 1024 / 8, 'upload': 50 * 1024 / 8, 'latency': 300},
'Good2G': {
'download': 450 * 1024 / 8, 'upload': 150 * 1024 / 8, 'latency': 150},
'Regular3G': {
'download': 750 * 1024 / 8, 'upload': 250 * 1024 / 8, 'latency': 100},
'Good3G': {
'download': 1.5 * 1024 * 1024 / 8, 'upload': 750 * 1024 / 8,
'latency': 40},
'Regular4G': {
'download': 4 * 1024 * 1024 / 8, 'upload': 3 * 1024 * 1024 / 8,
'latency': 20},
'DSL': {
'download': 2 * 1024 * 1024 / 8, 'upload': 1 * 1024 * 1024 / 8,
'latency': 5},
'WiFi': {
'download': 30 * 1024 * 1024 / 8, 'upload': 15 * 1024 * 1024 / 8,
'latency': 2}
}
def LoadEmulatedDevices(registry):
"""Loads a list of emulated devices from the DevTools JSON registry.
See, for example, third_party/WebKit/Source/devtools/front_end
/emulated_devices/module.json.
Args:
registry: A file-like object for the device registry (should be JSON).
Returns:
{'device_name': device}
"""
json_dict = json.load(registry)
devices = {}
for device in json_dict['extensions']:
device = device['device']
devices[device['title']] = device
return devices
def SetUpDeviceEmulationAndReturnMetadata(connection, device):
"""Configures an instance of Chrome for device emulation.
Args:
connection: (DevToolsConnection)
device: (dict) An entry from LoadEmulatedDevices().
Returns:
A dict containing the device emulation metadata.
"""
res = connection.SyncRequest('Emulation.canEmulate')
assert res['result'], 'Cannot set device emulation.'
data = _GetDeviceEmulationMetadata(device)
connection.SyncRequestNoResponse(
'Emulation.setDeviceMetricsOverride',
{'width': data['width'],
'height': data['height'],
'deviceScaleFactor': data['deviceScaleFactor'],
'mobile': data['mobile'],
'fitWindow': True})
connection.SyncRequestNoResponse('Network.setUserAgentOverride',
{'userAgent': data['userAgent']})
return data
def SetUpNetworkEmulation(connection, latency, download, upload):
"""Configures an instance of Chrome for network emulation.
See NETWORK_CONDITIONS for example (or valid?) emulation options.
Args:
connection: (DevToolsConnection)
latency: (float) Latency in ms.
download: (float) Download speed (Bytes / s).
upload: (float) Upload speed (Bytes / s).
"""
res = connection.SyncRequest('Network.canEmulateNetworkConditions')
assert res['result'], 'Cannot set network emulation.'
connection.SyncRequestNoResponse(
'Network.emulateNetworkConditions',
{'offline': False, 'latency': latency, 'downloadThroughput': download,
'uploadThroughput': upload})
def BandwidthToString(bandwidth):
"""Converts a bandwidth to string.
Args:
bandwidth: The bandwidth to convert in byte/s. Must be a multiple of 1024/8.
Returns:
A string compatible with wpr --{up,down} command line flags.
"""
assert bandwidth % (1024/8) == 0
bandwidth_kbps = (int(bandwidth) * 8) / 1024
if bandwidth_kbps % 1024:
return '{}Kbit/s'.format(bandwidth_kbps)
return '{}Mbit/s'.format(bandwidth_kbps / 1024)
def _GetDeviceEmulationMetadata(device):
"""Returns the metadata associated with a given device."""
return {'width': device['screen']['vertical']['width'],
'height': device['screen']['vertical']['height'],
'deviceScaleFactor': device['screen']['device-pixel-ratio'],
'mobile': 'mobile' in device['capabilities'],
'userAgent': device['user-agent']}