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
5import weakref
6
7from telemetry.internal import forwarders
8from telemetry.internal.forwarders import do_nothing_forwarder
9from telemetry.internal.platform import network_controller_backend
10from telemetry.internal.platform import tracing_controller_backend
11
12
13# pylint: disable=unused-argument
14
15class PlatformBackend(object):
16
17  def __init__(self, device=None):
18    """ Initalize an instance of PlatformBackend from a device optionally.
19      Call sites need to use SupportsDevice before intialization to check
20      whether this platform backend supports the device.
21      If device is None, this constructor returns the host platform backend
22      which telemetry is running on.
23
24      Args:
25        device: an instance of telemetry.core.platform.device.Device.
26    """
27    if device and not self.SupportsDevice(device):
28      raise ValueError('Unsupported device: %s' % device.name)
29    self._platform = None
30    self._running_browser_backends = weakref.WeakSet()
31    self._network_controller_backend = None
32    self._tracing_controller_backend = None
33    self._forwarder_factory = None
34
35  def InitPlatformBackend(self):
36    self._network_controller_backend = (
37        network_controller_backend.NetworkControllerBackend(self))
38    self._tracing_controller_backend = (
39        tracing_controller_backend.TracingControllerBackend(self))
40
41  @classmethod
42  def IsPlatformBackendForHost(cls):
43    """ Returns whether this platform backend is the platform backend to be used
44    for the host device which telemetry is running on. """
45    return False
46
47  @classmethod
48  def SupportsDevice(cls, device):
49    """ Returns whether this platform backend supports intialization from the
50    device. """
51    return False
52
53  @classmethod
54  def CreatePlatformForDevice(cls, device, finder_options):
55    raise NotImplementedError
56
57  def SetPlatform(self, platform):
58    assert self._platform == None
59    self._platform = platform
60
61  @property
62  def platform(self):
63    return self._platform
64
65  @property
66  def is_host_platform(self):
67    return self._platform.is_host_platform
68
69  @property
70  def running_browser_backends(self):
71    return list(self._running_browser_backends)
72
73  @property
74  def network_controller_backend(self):
75    return self._network_controller_backend
76
77  @property
78  def tracing_controller_backend(self):
79    return self._tracing_controller_backend
80
81  @property
82  def forwarder_factory(self):
83    if not self._forwarder_factory:
84      self._forwarder_factory = do_nothing_forwarder.DoNothingForwarderFactory()
85    return self._forwarder_factory
86
87  def GetRemotePort(self, port):
88    return port
89
90  def DidCreateBrowser(self, browser, browser_backend):
91    browser_options = browser_backend.browser_options
92    self.SetFullPerformanceModeEnabled(browser_options.full_performance_mode)
93
94  def DidStartBrowser(self, browser, browser_backend):
95    assert browser not in self._running_browser_backends
96    self._running_browser_backends.add(browser_backend)
97
98  def WillCloseBrowser(self, browser, browser_backend):
99    is_last_browser = len(self._running_browser_backends) <= 1
100    if is_last_browser:
101      self.SetFullPerformanceModeEnabled(False)
102
103    self._running_browser_backends.discard(browser_backend)
104
105  def GetWprPortPairs(self):
106    """Return suitable port pairs to be used for web page replay."""
107    return forwarders.PortPairs(
108        http=forwarders.PortPair(0, 0),
109        https=forwarders.PortPair(0, 0),
110        dns=None)
111
112  def IsDisplayTracingSupported(self):
113    return False
114
115  def StartDisplayTracing(self):
116    """Start gathering a trace with frame timestamps close to physical
117    display."""
118    raise NotImplementedError()
119
120  def StopDisplayTracing(self):
121    """Stop gathering a trace with frame timestamps close to physical display.
122
123    Returns a raw tracing events that contains the timestamps of physical
124    display.
125    """
126    raise NotImplementedError()
127
128  def SetFullPerformanceModeEnabled(self, enabled):
129    pass
130
131  def CanMonitorThermalThrottling(self):
132    return False
133
134  def IsThermallyThrottled(self):
135    raise NotImplementedError()
136
137  def HasBeenThermallyThrottled(self):
138    raise NotImplementedError()
139
140  def GetSystemCommitCharge(self):
141    raise NotImplementedError()
142
143  def GetSystemTotalPhysicalMemory(self):
144    raise NotImplementedError()
145
146  def GetCpuStats(self, pid):
147    return {}
148
149  def GetCpuTimestamp(self):
150    return {}
151
152  def PurgeUnpinnedMemory(self):
153    pass
154
155  def GetMemoryStats(self, pid):
156    return {}
157
158  def GetChildPids(self, pid):
159    raise NotImplementedError()
160
161  def GetCommandLine(self, pid):
162    raise NotImplementedError()
163
164  def GetDeviceTypeName(self):
165    raise NotImplementedError()
166
167  def GetArchName(self):
168    raise NotImplementedError()
169
170  def GetOSName(self):
171    raise NotImplementedError()
172
173  def GetOSVersionName(self):
174    raise NotImplementedError()
175
176  def CanFlushIndividualFilesFromSystemCache(self):
177    raise NotImplementedError()
178
179  def FlushEntireSystemCache(self):
180    raise NotImplementedError()
181
182  def FlushSystemCacheForDirectory(self, directory):
183    raise NotImplementedError()
184
185  def FlushDnsCache(self):
186    pass
187
188  def LaunchApplication(
189      self, application, parameters=None, elevate_privilege=False):
190    raise NotImplementedError()
191
192  def IsApplicationRunning(self, application):
193    raise NotImplementedError()
194
195  def CanLaunchApplication(self, application):
196    return False
197
198  def InstallApplication(self, application):
199    raise NotImplementedError()
200
201  def CanCaptureVideo(self):
202    return False
203
204  def StartVideoCapture(self, min_bitrate_mbps):
205    raise NotImplementedError()
206
207  @property
208  def is_video_capture_running(self):
209    return False
210
211  def StopVideoCapture(self):
212    raise NotImplementedError()
213
214  def CanMonitorPower(self):
215    return False
216
217  def CanMeasurePerApplicationPower(self):
218    return False
219
220  def StartMonitoringPower(self, browser):
221    raise NotImplementedError()
222
223  def StopMonitoringPower(self):
224    raise NotImplementedError()
225
226  def CanMonitorNetworkData(self):
227    return False
228
229  def GetNetworkData(self, browser):
230    raise NotImplementedError()
231
232  def ReadMsr(self, msr_number, start=0, length=64):
233    """Read a CPU model-specific register (MSR).
234
235    Which MSRs are available depends on the CPU model.
236    On systems with multiple CPUs, this function may run on any CPU.
237
238    Args:
239      msr_number: The number of the register to read.
240      start: The least significant bit to read, zero-indexed.
241          (Said another way, the number of bits to right-shift the MSR value.)
242      length: The number of bits to read. MSRs are 64 bits, even on 32-bit CPUs.
243    """
244    raise NotImplementedError()
245
246  @property
247  def supports_test_ca(self):
248    """Indicates whether the platform supports installing test CA."""
249    return False
250
251  def InstallTestCa(self, ca_cert_path):
252    """Install a test CA on the platform."""
253    raise NotImplementedError()
254
255  def RemoveTestCa(self):
256    """Remove a previously installed test CA from the platform."""
257    raise NotImplementedError()
258
259  def CanTakeScreenshot(self):
260    return False
261
262  def TakeScreenshot(self, file_path):
263    raise NotImplementedError
264
265  def IsCooperativeShutdownSupported(self):
266    """Indicates whether CooperativelyShutdown, below, is supported.
267    It is not necessary to implement it on all platforms."""
268    return False
269
270  def CooperativelyShutdown(self, proc, app_name):
271    """Cooperatively shut down the given process from subprocess.Popen.
272
273    Currently this is only implemented on Windows. See
274    crbug.com/424024 for background on why it was added.
275
276    Args:
277      proc: a process object returned from subprocess.Popen.
278      app_name: on Windows, is the prefix of the application's window
279          class name that should be searched for. This helps ensure
280          that only the application's windows are closed.
281
282    Returns True if it is believed the attempt succeeded.
283    """
284    raise NotImplementedError()
285
286  def PathExists(self, path, timeout=None, retries=None):
287    """Tests whether the given path exists on the target platform.
288    Args:
289      path: path in request.
290      timeout: timeout.
291      retries: num of retries.
292    Return:
293      Whether the path exists on the target platform.
294    """
295    raise NotImplementedError()
296