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 |