// Copyright (c) 2012 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.

#include "content/browser/devtools/devtools_tracing_handler.h"

#include "base/bind.h"
#include "base/callback.h"
#include "base/file_util.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/location.h"
#include "base/memory/ref_counted_memory.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/values.h"
#include "content/browser/devtools/devtools_http_handler_impl.h"
#include "content/browser/devtools/devtools_protocol_constants.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/tracing_controller.h"

namespace content {

namespace {

const char kRecordUntilFull[]   = "record-until-full";
const char kRecordContinuously[] = "record-continuously";
const char kEnableSampling[] = "enable-sampling";

void ReadFile(
    const base::FilePath& path,
    const base::Callback<void(const scoped_refptr<base::RefCountedString>&)>
        callback) {
  std::string trace_data;
  if (!base::ReadFileToString(path, &trace_data))
    LOG(ERROR) << "Failed to read file: " << path.value();
  base::DeleteFile(path, false);
  BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
      base::Bind(callback, make_scoped_refptr(
          base::RefCountedString::TakeString(&trace_data))));
}

}  // namespace

DevToolsTracingHandler::DevToolsTracingHandler()
    : weak_factory_(this) {
  RegisterCommandHandler(devtools::Tracing::start::kName,
                         base::Bind(&DevToolsTracingHandler::OnStart,
                                    base::Unretained(this)));
  RegisterCommandHandler(devtools::Tracing::end::kName,
                         base::Bind(&DevToolsTracingHandler::OnEnd,
                                    base::Unretained(this)));
}

DevToolsTracingHandler::~DevToolsTracingHandler() {
}

void DevToolsTracingHandler::BeginReadingRecordingResult(
    const base::FilePath& path) {
  BrowserThread::PostTask(
      BrowserThread::FILE, FROM_HERE,
      base::Bind(&ReadFile, path,
                 base::Bind(&DevToolsTracingHandler::ReadRecordingResult,
                            weak_factory_.GetWeakPtr())));
}

void DevToolsTracingHandler::ReadRecordingResult(
    const scoped_refptr<base::RefCountedString>& trace_data) {
  if (trace_data->data().size()) {
    scoped_ptr<base::Value> trace_value(base::JSONReader::Read(
        trace_data->data()));
    base::DictionaryValue* dictionary = NULL;
    bool ok = trace_value->GetAsDictionary(&dictionary);
    DCHECK(ok);
    base::ListValue* list = NULL;
    ok = dictionary->GetList("traceEvents", &list);
    DCHECK(ok);
    std::string buffer;
    for (size_t i = 0; i < list->GetSize(); ++i) {
      std::string item;
      base::Value* item_value;
      list->Get(i, &item_value);
      base::JSONWriter::Write(item_value, &item);
      if (buffer.size())
        buffer.append(",");
      buffer.append(item);
      if (i % 1000 == 0) {
        OnTraceDataCollected(buffer);
        buffer.clear();
      }
    }
    if (buffer.size())
      OnTraceDataCollected(buffer);
  }

  SendNotification(devtools::Tracing::tracingComplete::kName, NULL);
}

void DevToolsTracingHandler::OnTraceDataCollected(
    const std::string& trace_fragment) {
  // Hand-craft protocol notification message so we can substitute JSON
  // that we already got as string as a bare object, not a quoted string.
  std::string message = base::StringPrintf(
      "{ \"method\": \"%s\", \"params\": { \"%s\": [ %s ] } }",
      devtools::Tracing::dataCollected::kName,
      devtools::Tracing::dataCollected::kParamValue,
      trace_fragment.c_str());
  SendRawMessage(message);
}

TracingController::Options DevToolsTracingHandler::TraceOptionsFromString(
    const std::string& options) {
  std::vector<std::string> split;
  std::vector<std::string>::iterator iter;
  int ret = 0;

  base::SplitString(options, ',', &split);
  for (iter = split.begin(); iter != split.end(); ++iter) {
    if (*iter == kRecordUntilFull) {
      ret &= ~TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kRecordContinuously) {
      ret |= TracingController::RECORD_CONTINUOUSLY;
    } else if (*iter == kEnableSampling) {
      ret |= TracingController::ENABLE_SAMPLING;
    }
  }
  return static_cast<TracingController::Options>(ret);
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnStart(
    scoped_refptr<DevToolsProtocol::Command> command) {
  std::string categories;
  base::DictionaryValue* params = command->params();
  if (params)
    params->GetString(devtools::Tracing::start::kParamCategories, &categories);

  TracingController::Options options = TracingController::DEFAULT_OPTIONS;
  if (params && params->HasKey(devtools::Tracing::start::kParamOptions)) {
    std::string options_param;
    params->GetString(devtools::Tracing::start::kParamOptions, &options_param);
    options = TraceOptionsFromString(options_param);
  }

  TracingController::GetInstance()->EnableRecording(
      categories, options,
      base::Bind(&DevToolsTracingHandler::OnTracingStarted,
                 weak_factory_.GetWeakPtr(),
                 command));
  return command->AsyncResponsePromise();
}

void DevToolsTracingHandler::OnTracingStarted(
    scoped_refptr<DevToolsProtocol::Command> command) {
  SendAsyncResponse(command->SuccessResponse(NULL));
}

scoped_refptr<DevToolsProtocol::Response>
DevToolsTracingHandler::OnEnd(
    scoped_refptr<DevToolsProtocol::Command> command) {
  TracingController::GetInstance()->DisableRecording(
      base::FilePath(),
      base::Bind(&DevToolsTracingHandler::BeginReadingRecordingResult,
                 weak_factory_.GetWeakPtr()));
  return command->SuccessResponse(NULL);
}

}  // namespace content
