# Copyright 2014 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import logging
import re
import socket
import sys

from telemetry.core import exceptions
from telemetry import decorators
from telemetry.internal.backends import browser_backend
from telemetry.internal.backends.chrome_inspector import devtools_http
from telemetry.internal.backends.chrome_inspector import inspector_backend
from telemetry.internal.backends.chrome_inspector import inspector_websocket
from telemetry.internal.backends.chrome_inspector import memory_backend
from telemetry.internal.backends.chrome_inspector import tracing_backend
from telemetry.internal.backends.chrome_inspector import websocket
from telemetry.internal.platform.tracing_agent import chrome_tracing_agent
from telemetry.internal.platform.tracing_agent import (
    chrome_tracing_devtools_manager)
from telemetry.timeline import trace_data as trace_data_module


BROWSER_INSPECTOR_WEBSOCKET_URL = 'ws://127.0.0.1:%i/devtools/browser'


class TabNotFoundError(exceptions.Error):
  pass


def IsDevToolsAgentAvailable(port, app_backend):
  """Returns True if a DevTools agent is available on the given port."""
  if (isinstance(app_backend, browser_backend.BrowserBackend) and
      app_backend.supports_tracing):
    inspector_websocket_instance = inspector_websocket.InspectorWebsocket()
    try:
      if not _IsInspectorWebsocketAvailable(inspector_websocket_instance, port):
        return False
    finally:
      inspector_websocket_instance.Disconnect()

  devtools_http_instance = devtools_http.DevToolsHttp(port)
  try:
    return _IsDevToolsAgentAvailable(devtools_http_instance)
  finally:
    devtools_http_instance.Disconnect()


def _IsInspectorWebsocketAvailable(inspector_websocket_instance, port):
  try:
    inspector_websocket_instance.Connect(BROWSER_INSPECTOR_WEBSOCKET_URL % port)
  except websocket.WebSocketException:
    return False
  except socket.error:
    return False
  except Exception as e:
    sys.stderr.write('Unidentified exception while checking if wesocket is'
                     'available on port %i. Exception message: %s\n' %
                     (port, e.message))
    return False
  else:
    return True


# TODO(nednguyen): Find a more reliable way to check whether the devtool agent
# is still alive.
def _IsDevToolsAgentAvailable(devtools_http_instance):
  try:
    devtools_http_instance.Request('')
  except devtools_http.DevToolsClientConnectionError:
    return False
  else:
    return True


class DevToolsClientBackend(object):
  """An object that communicates with Chrome's devtools.

  This class owns a map of InspectorBackends. It is responsible for creating
  them and destroying them.
  """
  def __init__(self, devtools_port, remote_devtools_port, app_backend):
    """Creates a new DevToolsClientBackend.

    A DevTools agent must exist on the given devtools_port.

    Args:
      devtools_port: The port to use to connect to DevTools agent.
      remote_devtools_port: In some cases (e.g., app running on
          Android device, devtools_port is the forwarded port on the
          host platform. We also need to know the remote_devtools_port
          so that we can uniquely identify the DevTools agent.
      app_backend: For the app that contains the DevTools agent.
    """
    self._devtools_port = devtools_port
    self._remote_devtools_port = remote_devtools_port
    self._devtools_http = devtools_http.DevToolsHttp(devtools_port)
    self._browser_inspector_websocket = None
    self._tracing_backend = None
    self._memory_backend = None
    self._app_backend = app_backend
    self._devtools_context_map_backend = _DevToolsContextMapBackend(
        self._app_backend, self)

    if not self.supports_tracing:
      return
    chrome_tracing_devtools_manager.RegisterDevToolsClient(
        self, self._app_backend.platform_backend)

    # Telemetry has started Chrome tracing if there is trace config, so start
    # tracing on this newly created devtools client if needed.
    trace_config = (self._app_backend.platform_backend
                    .tracing_controller_backend.GetChromeTraceConfig())
    if not trace_config:
      self._CreateTracingBackendIfNeeded(is_tracing_running=False)
      return

    if self.support_startup_tracing:
      self._CreateTracingBackendIfNeeded(is_tracing_running=True)
      return

    self._CreateTracingBackendIfNeeded(is_tracing_running=False)
    self.StartChromeTracing(
        trace_config=trace_config,
        custom_categories=trace_config.tracing_category_filter.filter_string)

  @property
  def remote_port(self):
    return self._remote_devtools_port

  @property
  def supports_tracing(self):
    if not isinstance(self._app_backend, browser_backend.BrowserBackend):
      return False
    return self._app_backend.supports_tracing

  @property
  def supports_overriding_memory_pressure_notifications(self):
    if not isinstance(self._app_backend, browser_backend.BrowserBackend):
      return False
    return self._app_backend.supports_overriding_memory_pressure_notifications


  @property
  def is_tracing_running(self):
    if not self.supports_tracing:
      return False
    if not self._tracing_backend:
      return False
    return self._tracing_backend.is_tracing_running

  @property
  def support_startup_tracing(self):
    # Startup tracing with --trace-config-file flag was not supported until
    # Chromium branch number 2512 (see crrev.com/1309243004 and
    # crrev.com/1353583002).
    if not chrome_tracing_agent.ChromeTracingAgent.IsStartupTracingSupported(
        self._app_backend.platform_backend):
      return False
    # TODO(zhenw): Remove this once stable Chrome and reference browser have
    # passed 2512.
    return self.GetChromeBranchNumber() >= 2512

  def IsAlive(self):
    """Whether the DevTools server is available and connectable."""
    return (self._devtools_http and
        _IsDevToolsAgentAvailable(self._devtools_http))

  def Close(self):
    if self._tracing_backend:
      self._tracing_backend.Close()
      self._tracing_backend = None
    if self._memory_backend:
      self._memory_backend.Close()
      self._memory_backend = None

    if self._devtools_context_map_backend:
      self._devtools_context_map_backend.Clear()

    # Close the browser inspector socket last (in case the backend needs to
    # interact with it before closing).
    if self._browser_inspector_websocket:
      self._browser_inspector_websocket.Disconnect()
      self._browser_inspector_websocket = None

    assert self._devtools_http
    self._devtools_http.Disconnect()
    self._devtools_http = None


  @decorators.Cache
  def GetChromeBranchNumber(self):
    # Detect version information.
    resp = self._devtools_http.RequestJson('version')
    if 'Protocol-Version' in resp:
      if 'Browser' in resp:
        branch_number_match = re.search(r'Chrome/\d+\.\d+\.(\d+)\.\d+',
                                        resp['Browser'])
      else:
        branch_number_match = re.search(
            r'Chrome/\d+\.\d+\.(\d+)\.\d+ (Mobile )?Safari',
            resp['User-Agent'])

      if branch_number_match:
        branch_number = int(branch_number_match.group(1))
        if branch_number:
          return branch_number

    # Branch number can't be determined, so fail any branch number checks.
    return 0

  def _ListInspectableContexts(self):
    return self._devtools_http.RequestJson('')

  def RequestNewTab(self, timeout):
    """Creates a new tab.

    Returns:
      A JSON string as returned by DevTools. Example:
      {
        "description": "",
        "devtoolsFrontendUrl":
            "/devtools/inspector.html?ws=host:port/devtools/page/id-string",
        "id": "id-string",
        "title": "Page Title",
        "type": "page",
        "url": "url",
        "webSocketDebuggerUrl": "ws://host:port/devtools/page/id-string"
      }

    Raises:
      devtools_http.DevToolsClientConnectionError
    """
    return self._devtools_http.Request('new', timeout=timeout)

  def CloseTab(self, tab_id, timeout):
    """Closes the tab with the given id.

    Raises:
      devtools_http.DevToolsClientConnectionError
      TabNotFoundError
    """
    try:
      return self._devtools_http.Request('close/%s' % tab_id,
                                         timeout=timeout)
    except devtools_http.DevToolsClientUrlError:
      error = TabNotFoundError(
          'Unable to close tab, tab id not found: %s' % tab_id)
      raise error, None, sys.exc_info()[2]

  def ActivateTab(self, tab_id, timeout):
    """Activates the tab with the given id.

    Raises:
      devtools_http.DevToolsClientConnectionError
      TabNotFoundError
    """
    try:
      return self._devtools_http.Request('activate/%s' % tab_id,
                                         timeout=timeout)
    except devtools_http.DevToolsClientUrlError:
      error = TabNotFoundError(
          'Unable to activate tab, tab id not found: %s' % tab_id)
      raise error, None, sys.exc_info()[2]

  def GetUrl(self, tab_id):
    """Returns the URL of the tab with |tab_id|, as reported by devtools.

    Raises:
      devtools_http.DevToolsClientConnectionError
    """
    for c in self._ListInspectableContexts():
      if c['id'] == tab_id:
        return c['url']
    return None

  def IsInspectable(self, tab_id):
    """Whether the tab with |tab_id| is inspectable, as reported by devtools.

    Raises:
      devtools_http.DevToolsClientConnectionError
    """
    contexts = self._ListInspectableContexts()
    return tab_id in [c['id'] for c in contexts]

  def GetUpdatedInspectableContexts(self):
    """Returns an updated instance of _DevToolsContextMapBackend."""
    contexts = self._ListInspectableContexts()
    self._devtools_context_map_backend._Update(contexts)
    return self._devtools_context_map_backend

  def _CreateTracingBackendIfNeeded(self, is_tracing_running=False):
    assert self.supports_tracing
    if not self._tracing_backend:
      self._CreateAndConnectBrowserInspectorWebsocketIfNeeded()
      self._tracing_backend = tracing_backend.TracingBackend(
          self._browser_inspector_websocket, is_tracing_running)

  def _CreateMemoryBackendIfNeeded(self):
    assert self.supports_overriding_memory_pressure_notifications
    if not self._memory_backend:
      self._CreateAndConnectBrowserInspectorWebsocketIfNeeded()
      self._memory_backend = memory_backend.MemoryBackend(
          self._browser_inspector_websocket)

  def _CreateAndConnectBrowserInspectorWebsocketIfNeeded(self):
    if not self._browser_inspector_websocket:
      self._browser_inspector_websocket = (
          inspector_websocket.InspectorWebsocket())
      self._browser_inspector_websocket.Connect(
          BROWSER_INSPECTOR_WEBSOCKET_URL % self._devtools_port)

  def IsChromeTracingSupported(self):
    if not self.supports_tracing:
      return False
    self._CreateTracingBackendIfNeeded()
    return self._tracing_backend.IsTracingSupported()

  def StartChromeTracing(
      self, trace_config, custom_categories=None, timeout=10):
    """
    Args:
        trace_config: An tracing_config.TracingConfig instance.
        custom_categories: An optional string containing a list of
                         comma separated categories that will be traced
                         instead of the default category set.  Example: use
                         "webkit,cc,disabled-by-default-cc.debug" to trace only
                         those three event categories.
    """
    assert trace_config and trace_config.enable_chrome_trace
    self._CreateTracingBackendIfNeeded()
    return self._tracing_backend.StartTracing(
        trace_config, custom_categories, timeout)

  def StopChromeTracing(self, trace_data_builder, timeout=30):
    assert self.is_tracing_running
    try:
      context_map = self.GetUpdatedInspectableContexts()
      for context in context_map.contexts:
        if context['type'] not in ['iframe', 'page', 'webview']:
          continue
        context_id = context['id']
        backend = context_map.GetInspectorBackend(context_id)
        success = backend.EvaluateJavaScript(
            "console.time('" + backend.id + "');" +
            "console.timeEnd('" + backend.id + "');" +
            "console.time.toString().indexOf('[native code]') != -1;")
        if not success:
          raise Exception('Page stomped on console.time')
        trace_data_builder.AddEventsTo(
            trace_data_module.TAB_ID_PART, [backend.id])
    finally:
      self._tracing_backend.StopTracing(trace_data_builder, timeout)

  def DumpMemory(self, timeout=30):
    """Dumps memory.

    Returns:
      GUID of the generated dump if successful, None otherwise.

    Raises:
      TracingTimeoutException: If more than |timeout| seconds has passed
      since the last time any data is received.
      TracingUnrecoverableException: If there is a websocket error.
      TracingUnexpectedResponseException: If the response contains an error
      or does not contain the expected result.
    """
    self._CreateTracingBackendIfNeeded()
    return self._tracing_backend.DumpMemory(timeout)

  def SetMemoryPressureNotificationsSuppressed(self, suppressed, timeout=30):
    """Enable/disable suppressing memory pressure notifications.

    Args:
      suppressed: If true, memory pressure notifications will be suppressed.
      timeout: The timeout in seconds.

    Raises:
      MemoryTimeoutException: If more than |timeout| seconds has passed
      since the last time any data is received.
      MemoryUnrecoverableException: If there is a websocket error.
      MemoryUnexpectedResponseException: If the response contains an error
      or does not contain the expected result.
    """
    self._CreateMemoryBackendIfNeeded()
    return self._memory_backend.SetMemoryPressureNotificationsSuppressed(
        suppressed, timeout)

  def SimulateMemoryPressureNotification(self, pressure_level, timeout=30):
    """Simulate a memory pressure notification.

    Args:
      pressure level: The memory pressure level of the notification ('moderate'
      or 'critical').
      timeout: The timeout in seconds.

    Raises:
      MemoryTimeoutException: If more than |timeout| seconds has passed
      since the last time any data is received.
      MemoryUnrecoverableException: If there is a websocket error.
      MemoryUnexpectedResponseException: If the response contains an error
      or does not contain the expected result.
    """
    self._CreateMemoryBackendIfNeeded()
    return self._memory_backend.SimulateMemoryPressureNotification(
        pressure_level, timeout)


class _DevToolsContextMapBackend(object):
  def __init__(self, app_backend, devtools_client):
    self._app_backend = app_backend
    self._devtools_client = devtools_client
    self._contexts = None
    self._inspector_backends_dict = {}

  @property
  def contexts(self):
    """The most up to date contexts data.

    Returned in the order returned by devtools agent."""
    return self._contexts

  def GetContextInfo(self, context_id):
    for context in self._contexts:
      if context['id'] == context_id:
        return context
    raise KeyError('Cannot find a context with id=%s' % context_id)

  def GetInspectorBackend(self, context_id):
    """Gets an InspectorBackend instance for the given context_id.

    This lazily creates InspectorBackend for the context_id if it does
    not exist yet. Otherwise, it will return the cached instance."""
    if context_id in self._inspector_backends_dict:
      return self._inspector_backends_dict[context_id]

    for context in self._contexts:
      if context['id'] == context_id:
        new_backend = inspector_backend.InspectorBackend(
            self._app_backend.app, self._devtools_client, context)
        self._inspector_backends_dict[context_id] = new_backend
        return new_backend

    raise KeyError('Cannot find a context with id=%s' % context_id)

  def _Update(self, contexts):
    # Remove InspectorBackend that is not in the current inspectable
    # contexts list.
    context_ids = [context['id'] for context in contexts]
    for context_id in self._inspector_backends_dict.keys():
      if context_id not in context_ids:
        backend = self._inspector_backends_dict[context_id]
        backend.Disconnect()
        del self._inspector_backends_dict[context_id]

    valid_contexts = []
    for context in contexts:
      # If the context does not have webSocketDebuggerUrl, skip it.
      # If an InspectorBackend is already created for the tab,
      # webSocketDebuggerUrl will be missing, and this is expected.
      context_id = context['id']
      if context_id not in self._inspector_backends_dict:
        if 'webSocketDebuggerUrl' not in context:
          logging.debug('webSocketDebuggerUrl missing, removing %s'
                        % context_id)
          continue
      valid_contexts.append(context)
    self._contexts = valid_contexts

  def Clear(self):
    for backend in self._inspector_backends_dict.values():
      backend.Disconnect()
    self._inspector_backends_dict = {}
    self._contexts = None
