Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / tools / telemetry / telemetry / core / platform / profiler / tcpdump_profiler.py
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.
4
5 import os
6 import signal
7 import subprocess
8 import sys
9 import tempfile
10
11 from telemetry.core.platform import profiler
12 from telemetry.core.platform.profiler import android_prebuilt_profiler_helper
13
14 _TCP_DUMP_BASE_OPTS = ['-i', 'any', '-p', '-s', '0', '-w']
15
16
17 class _TCPDumpProfilerAndroid(object):
18   """An internal class to collect TCP dumps on android.
19
20   This profiler uses pre-built binaries from AOSP.
21   See more details in prebuilt/android/README.txt.
22   """
23
24   _DEVICE_DUMP_FILE = '/sdcard/tcpdump_profiles/capture.pcap'
25
26   def __init__(self, adb, output_path):
27     self._adb = adb
28     self._output_path = output_path
29     self._adb.RunShellCommand('mkdir -p ' +
30                               os.path.dirname(self._DEVICE_DUMP_FILE))
31     self._proc = subprocess.Popen(
32         ['adb', '-s', self._adb.device_serial(),
33          'shell', android_prebuilt_profiler_helper.GetDevicePath('tcpdump')] +
34          _TCP_DUMP_BASE_OPTS +
35          [self._DEVICE_DUMP_FILE])
36
37   def CollectProfile(self):
38     tcpdump_pid = self._adb.ExtractPid('tcpdump')
39     if not tcpdump_pid or not tcpdump_pid[0]:
40       raise Exception('Unable to find TCPDump. Check your device is rooted '
41           'and tcpdump is installed at ' +
42           android_prebuilt_profiler_helper.GetDevicePath('tcpdump'))
43     self._adb.RunShellCommand('kill -term ' + tcpdump_pid[0])
44     self._proc.terminate()
45     host_dump = os.path.join(self._output_path,
46                              os.path.basename(self._DEVICE_DUMP_FILE))
47     self._adb.device().old_interface.Adb().Pull(self._DEVICE_DUMP_FILE,
48                                                 host_dump)
49     print 'TCP dump available at: %s ' % host_dump
50     print 'Use Wireshark to open it.'
51     return host_dump
52
53
54 class _TCPDumpProfilerLinux(object):
55   """An internal class to collect TCP dumps on linux desktop."""
56
57   _DUMP_FILE = 'capture.pcap'
58
59   def __init__(self, output_path):
60     if not os.path.exists(output_path):
61       os.makedirs(output_path)
62     self._dump_file = os.path.join(output_path, self._DUMP_FILE)
63     self._tmp_output_file = tempfile.NamedTemporaryFile('w', 0)
64     try:
65       self._proc = subprocess.Popen(
66           ['tcpdump'] + _TCP_DUMP_BASE_OPTS + [self._dump_file],
67           stdout=self._tmp_output_file, stderr=subprocess.STDOUT)
68     except OSError as e:
69       raise Exception('Unable to execute TCPDump, please check your '
70           'installation. ' + str(e))
71
72   def CollectProfile(self):
73     self._proc.send_signal(signal.SIGINT)
74     exit_code = self._proc.wait()
75     try:
76       if exit_code:
77         raise Exception(
78             'tcpdump failed with exit code %d. Output:\n%s' %
79             (exit_code, self._GetStdOut()))
80     finally:
81       self._tmp_output_file.close()
82     print 'TCP dump available at: ', self._dump_file
83     print 'Use Wireshark to open it.'
84     return self._dump_file
85
86   def _GetStdOut(self):
87     self._tmp_output_file.flush()
88     try:
89       with open(self._tmp_output_file.name) as f:
90         return f.read()
91     except IOError:
92       return ''
93
94
95 class TCPDumpProfiler(profiler.Profiler):
96   """A Factory to instantiate the platform-specific profiler."""
97   def __init__(self, browser_backend, platform_backend, output_path, state):
98     super(TCPDumpProfiler, self).__init__(
99         browser_backend, platform_backend, output_path, state)
100     if platform_backend.GetOSName() == 'android':
101       android_prebuilt_profiler_helper.InstallOnDevice(
102           browser_backend.adb.device(), 'tcpdump')
103       self._platform_profiler = _TCPDumpProfilerAndroid(
104           browser_backend.adb, output_path)
105     else:
106       self._platform_profiler = _TCPDumpProfilerLinux(output_path)
107
108   @classmethod
109   def name(cls):
110     return 'tcpdump'
111
112   @classmethod
113   def is_supported(cls, browser_type):
114     if browser_type.startswith('cros'):
115       return False
116     if sys.platform.startswith('linux'):
117       return True
118     return browser_type.startswith('android')
119
120   def CollectProfile(self):
121     return self._platform_profiler.CollectProfile()