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
3 # found in the LICENSE file.
11 from telemetry
.internal
.platform
import profiler
12 from telemetry
.internal
.platform
.profiler
import android_prebuilt_profiler_helper
14 _TCP_DUMP_BASE_OPTS
= ['-i', 'any', '-p', '-s', '0', '-w']
17 class _TCPDumpProfilerAndroid(object):
18 """An internal class to collect TCP dumps on android.
20 This profiler uses pre-built binaries from AOSP.
21 See more details in prebuilt/android/README.txt.
24 _DEVICE_DUMP_FILE
= '/sdcard/tcpdump_profiles/capture.pcap'
26 def __init__(self
, device
, output_path
):
28 self
._output
_path
= output_path
29 self
._device
.RunShellCommand(
30 ['mkdir', '-p', os
.path
.dirname(self
._DEVICE
_DUMP
_FILE
)],
32 self
._proc
= subprocess
.Popen(
33 [self
._device
.adb
.GetAdbPath(),
34 '-s', self
._device
.adb
.GetDeviceSerial(),
35 'shell', android_prebuilt_profiler_helper
.GetDevicePath('tcpdump')] +
37 [self
._DEVICE
_DUMP
_FILE
])
39 def CollectProfile(self
):
40 tcpdump_pid
= self
._device
.GetPids('tcpdump')
41 if not tcpdump_pid
or not 'tcpdump' in tcpdump_pid
:
42 raise Exception('Unable to find TCPDump. Check your device is rooted '
43 'and tcpdump is installed at ' +
44 android_prebuilt_profiler_helper
.GetDevicePath('tcpdump'))
45 if len(tcpdump_pid
['tcpdump']) > 1:
47 'At most one instance of process tcpdump expected but found pids: '
49 tcpdump_pid
= int(tcpdump_pid
['tcpdump'][0])
50 self
._device
.RunShellCommand(
51 ['kill', '-term', str(tcpdump_pid
)], check_return
=True)
52 self
._proc
.terminate()
53 host_dump
= os
.path
.join(self
._output
_path
,
54 os
.path
.basename(self
._DEVICE
_DUMP
_FILE
))
55 self
._device
.PullFile(self
._DEVICE
_DUMP
_FILE
, host_dump
)
56 print 'TCP dump available at: %s ' % host_dump
57 print 'Use Wireshark to open it.'
61 class _TCPDumpProfilerLinux(object):
62 """An internal class to collect TCP dumps on linux desktop."""
64 _DUMP_FILE
= 'capture.pcap'
66 def __init__(self
, output_path
):
67 if not os
.path
.exists(output_path
):
68 os
.makedirs(output_path
)
69 self
._dump
_file
= os
.path
.join(output_path
, self
._DUMP
_FILE
)
70 self
._tmp
_output
_file
= tempfile
.NamedTemporaryFile('w', 0)
72 self
._proc
= subprocess
.Popen(
73 ['tcpdump'] + _TCP_DUMP_BASE_OPTS
+ [self
._dump
_file
],
74 stdout
=self
._tmp
_output
_file
, stderr
=subprocess
.STDOUT
)
76 raise Exception('Unable to execute TCPDump, please check your '
77 'installation. ' + str(e
))
79 def CollectProfile(self
):
80 self
._proc
.send_signal(signal
.SIGINT
)
81 exit_code
= self
._proc
.wait()
85 'tcpdump failed with exit code %d. Output:\n%s' %
86 (exit_code
, self
._GetStdOut
()))
88 self
._tmp
_output
_file
.close()
89 print 'TCP dump available at: ', self
._dump
_file
90 print 'Use Wireshark to open it.'
91 return self
._dump
_file
94 self
._tmp
_output
_file
.flush()
96 with
open(self
._tmp
_output
_file
.name
) as f
:
102 class TCPDumpProfiler(profiler
.Profiler
):
103 """A Factory to instantiate the platform-specific profiler."""
104 def __init__(self
, browser_backend
, platform_backend
, output_path
, state
):
105 super(TCPDumpProfiler
, self
).__init
__(
106 browser_backend
, platform_backend
, output_path
, state
)
107 if platform_backend
.GetOSName() == 'android':
108 android_prebuilt_profiler_helper
.InstallOnDevice(
109 browser_backend
.device
, 'tcpdump')
110 self
._platform
_profiler
= _TCPDumpProfilerAndroid(
111 browser_backend
.device
, output_path
)
113 self
._platform
_profiler
= _TCPDumpProfilerLinux(output_path
)
120 def is_supported(cls
, browser_type
):
121 if browser_type
.startswith('cros'):
123 if sys
.platform
.startswith('linux'):
125 return browser_type
.startswith('android')
127 def CollectProfile(self
):
128 return self
._platform
_profiler
.CollectProfile()