| OLD | NEW |
| 1 # Copyright 2013 The Chromium Authors. All rights reserved. | 1 # Copyright 2013 The Chromium Authors. All rights reserved. |
| 2 # Use of this source code is governed by a BSD-style license that can be | 2 # Use of this source code is governed by a BSD-style license that can be |
| 3 # found in the LICENSE file. | 3 # found in the LICENSE file. |
| 4 import json | 4 import json |
| 5 import logging | 5 import logging |
| 6 import socket | 6 import socket |
| 7 import sys | 7 import sys |
| 8 | 8 |
| 9 from telemetry.core import util | 9 from telemetry.core import util |
| 10 from telemetry.core import exceptions | 10 from telemetry.core import exceptions |
| 11 from telemetry.core.backends import png_bitmap | 11 from telemetry.core.backends import png_bitmap |
| 12 from telemetry.core.backends.chrome import inspector_console | 12 from telemetry.core.backends.chrome import inspector_console |
| 13 from telemetry.core.backends.chrome import inspector_memory | 13 from telemetry.core.backends.chrome import inspector_memory |
| 14 from telemetry.core.backends.chrome import inspector_network | 14 from telemetry.core.backends.chrome import inspector_network |
| 15 from telemetry.core.backends.chrome import inspector_page | 15 from telemetry.core.backends.chrome import inspector_page |
| 16 from telemetry.core.backends.chrome import inspector_runtime | 16 from telemetry.core.backends.chrome import inspector_runtime |
| 17 from telemetry.core.backends.chrome import inspector_timeline | 17 from telemetry.core.backends.chrome import inspector_timeline |
| 18 from telemetry.core.backends.chrome import websocket | 18 from telemetry.core.backends.chrome import websocket |
| 19 from telemetry.core.jsheap import model |
| 19 | 20 |
| 20 class InspectorException(Exception): | 21 class InspectorException(Exception): |
| 21 pass | 22 pass |
| 22 | 23 |
| 23 class InspectorBackend(object): | 24 class InspectorBackend(object): |
| 24 def __init__(self, browser, browser_backend, debugger_url): | 25 def __init__(self, browser, browser_backend, debugger_url): |
| 25 assert debugger_url | 26 assert debugger_url |
| 26 self._browser = browser | 27 self._browser = browser |
| 27 self._browser_backend = browser_backend | 28 self._browser_backend = browser_backend |
| 28 self._debugger_url = debugger_url | 29 self._debugger_url = debugger_url |
| (...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 287 raise util.TimeoutException( | 288 raise util.TimeoutException( |
| 288 'Timed out waiting for reply. This is unusual.') | 289 'Timed out waiting for reply. This is unusual.') |
| 289 raise exceptions.TabCrashException(sys.exc_info()[1]) | 290 raise exceptions.TabCrashException(sys.exc_info()[1]) |
| 290 | 291 |
| 291 res = json.loads(data) | 292 res = json.loads(data) |
| 292 logging.debug('got [%s]', data) | 293 logging.debug('got [%s]', data) |
| 293 if 'method' in res: | 294 if 'method' in res: |
| 294 self._HandleNotification(res) | 295 self._HandleNotification(res) |
| 295 continue | 296 continue |
| 296 | 297 |
| 297 if res['id'] != req['id']: | 298 if 'id' not in res or res['id'] != req['id']: |
| 298 logging.debug('Dropped reply: %s', json.dumps(res)) | 299 logging.debug('Dropped reply: %s', json.dumps(res)) |
| 299 continue | 300 continue |
| 300 return res | 301 return res |
| 301 | 302 |
| 302 def RegisterDomain(self, | 303 def RegisterDomain(self, |
| 303 domain_name, notification_handler, will_close_handler): | 304 domain_name, notification_handler, will_close_handler): |
| 304 """Registers a given domain for handling notification methods. | 305 """Registers a given domain for handling notification methods. |
| 305 | 306 |
| 306 For example, given inspector_backend: | 307 For example, given inspector_backend: |
| 307 def OnConsoleNotification(msg): | 308 def OnConsoleNotification(msg): |
| 308 if msg['method'] == 'Console.messageAdded': | 309 if msg['method'] == 'Console.messageAdded': |
| 309 print msg['params']['message'] | 310 print msg['params']['message'] |
| 310 return | 311 return |
| 311 def OnConsoleClose(self): | 312 def OnConsoleClose(self): |
| 312 pass | 313 pass |
| 313 inspector_backend.RegisterDomain('Console', | 314 inspector_backend.RegisterDomain('Console', |
| 314 OnConsoleNotification, OnConsoleClose) | 315 OnConsoleNotification, OnConsoleClose) |
| 315 """ | 316 """ |
| 316 assert domain_name not in self._domain_handlers | 317 assert domain_name not in self._domain_handlers |
| 317 self._domain_handlers[domain_name] = (notification_handler, | 318 self._domain_handlers[domain_name] = (notification_handler, |
| 318 will_close_handler) | 319 will_close_handler) |
| 319 | 320 |
| 320 def UnregisterDomain(self, domain_name): | 321 def UnregisterDomain(self, domain_name): |
| 321 """Unregisters a previously registered domain.""" | 322 """Unregisters a previously registered domain.""" |
| 322 assert domain_name in self._domain_handlers | 323 assert domain_name in self._domain_handlers |
| 323 self._domain_handlers.pop(domain_name) | 324 self._domain_handlers.pop(domain_name) |
| 324 | 325 |
| 325 def CollectGarbage(self): | 326 def CollectGarbage(self): |
| 326 self._page.CollectGarbage() | 327 self._page.CollectGarbage() |
| 328 |
| 329 def TakeJSHeapSnapshot(self, timeout=120): |
| 330 # This is a hack to make the nested function be able to modify the |
| 331 # variables. |
| 332 snapshot_uid = [0] |
| 333 snapshot = [[]] |
| 334 |
| 335 def OnNotification(res): |
| 336 if res['method'] == 'HeapProfiler.addProfileHeader': |
| 337 snapshot_uid[0] = res['params']['header']['uid'] |
| 338 elif res['method'] == 'HeapProfiler.addHeapSnapshotChunk': |
| 339 snapshot[0].append(res['params']['chunk']) |
| 340 elif res['method'] == 'HeapProfiler.finishHeapSnapshot': |
| 341 snapshot[0] = ''.join(snapshot[0]) |
| 342 |
| 343 def OnClose(): |
| 344 pass |
| 345 |
| 346 self.RegisterDomain('HeapProfiler', OnNotification, OnClose) |
| 347 |
| 348 self.SyncRequest({'method': 'Page.getResourceTree'}, timeout) |
| 349 self.SyncRequest({'method': 'Debugger.enable'}, timeout) |
| 350 self.SyncRequest({'method': 'HeapProfiler.clearProfiles'}, timeout) |
| 351 self.SyncRequest({'method': 'HeapProfiler.takeHeapSnapshot', |
| 352 'params': {'detailed': True}}, timeout) |
| 353 self.SyncRequest({'method': 'HeapProfiler.getHeapSnapshot', |
| 354 'params': {'uid': snapshot_uid[0]}}, timeout) |
| 355 |
| 356 self.UnregisterDomain('HeapProfiler') |
| 357 |
| 358 return model.JsHeapSnapshotModel(snapshot[0]) |
| OLD | NEW |