1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import json 6import logging 7import socket 8import traceback 9 10from telemetry.internal.backends.chrome_inspector import inspector_websocket 11from telemetry.internal.backends.chrome_inspector import websocket 12 13 14class MemoryTimeoutException(Exception): 15 pass 16 17 18class MemoryUnrecoverableException(Exception): 19 pass 20 21 22class MemoryUnexpectedResponseException(Exception): 23 pass 24 25 26class MemoryBackend(object): 27 28 def __init__(self, inspector_socket): 29 self._inspector_websocket = inspector_socket 30 31 def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30): 32 """Enable/disable suppressing memory pressure notifications. 33 34 Args: 35 suppressed: If true, memory pressure notifications will be suppressed. 36 timeout: The timeout in seconds. 37 38 Raises: 39 MemoryTimeoutException: If more than |timeout| seconds has passed 40 since the last time any data is received. 41 MemoryUnrecoverableException: If there is a websocket error. 42 MemoryUnexpectedResponseException: If the response contains an error 43 or does not contain the expected result. 44 """ 45 self._SendMemoryRequest('setPressureNotificationsSuppressed', 46 {'suppressed': suppressed}, timeout) 47 48 def SimulateMemoryPressureNotification(self, pressure_level, timeout=30): 49 """Simulate a memory pressure notification. 50 51 Args: 52 pressure level: The memory pressure level of the notification ('moderate' 53 or 'critical'). 54 timeout: The timeout in seconds. 55 56 Raises: 57 MemoryTimeoutException: If more than |timeout| seconds has passed 58 since the last time any data is received. 59 MemoryUnrecoverableException: If there is a websocket error. 60 MemoryUnexpectedResponseException: If the response contains an error 61 or does not contain the expected result. 62 """ 63 self._SendMemoryRequest('simulatePressureNotification', 64 {'level': pressure_level}, timeout) 65 66 def _SendMemoryRequest(self, command, params, timeout): 67 method = 'Memory.%s' % command 68 request = { 69 'method': method, 70 'params': params 71 } 72 try: 73 response = self._inspector_websocket.SyncRequest(request, timeout) 74 except websocket.WebSocketTimeoutException: 75 raise MemoryTimeoutException( 76 'Exception raised while sending a %s request:\n%s' % 77 (method, traceback.format_exc())) 78 except (socket.error, websocket.WebSocketException, 79 inspector_websocket.WebSocketDisconnected): 80 raise MemoryUnrecoverableException( 81 'Exception raised while sending a %s request:\n%s' % 82 (method, traceback.format_exc())) 83 84 if 'error' in response: 85 code = response['error']['code'] 86 if code == inspector_websocket.InspectorWebsocket.METHOD_NOT_FOUND_CODE: 87 logging.warning( 88 '%s DevTools method not supported by the browser' % method) 89 else: 90 raise MemoryUnexpectedResponseException( 91 'Inspector returned unexpected response for %s:\n%s' % 92 (method, json.dumps(response, indent=2))) 93 94 def Close(self): 95 self._inspector_websocket = None 96