// Copyright 2016 The Cobalt Authors. All Rights Reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

#include "cobalt/debug/debug_script_runner.h"

#include "base/bind.h"
#include "base/file_path.h"
#include "base/file_util.h"
#include "base/path_service.h"
#include "base/stringprintf.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/script/source_code.h"

namespace cobalt {
namespace debug {

namespace {
const char kContentDir[] = "cobalt/debug/backend";
const char kObjectIdentifier[] = "devtoolsBackend";
}  // namespace

DebugScriptRunner::DebugScriptRunner(
    script::GlobalEnvironment* global_environment,
    const dom::CspDelegate* csp_delegate,
    const OnEventCallback& on_event_callback)
    : global_environment_(global_environment),
      csp_delegate_(csp_delegate),
      on_event_callback_(on_event_callback) {
  // Bind this object to the global object so it can persist state and be
  // accessed from any of the debug components.
  global_environment_->Bind(kObjectIdentifier, make_scoped_refptr(this));
}

base::optional<std::string> DebugScriptRunner::CreateRemoteObject(
    const script::ValueHandleHolder* object, const std::string& params) {
  // Callback function should have been set by runtime.js.
  DCHECK(create_remote_object_callback_);

  CreateRemoteObjectCallback::ReturnValue result =
      create_remote_object_callback_->value().Run(object, params);
  if (result.exception) {
    DLOG(WARNING) << "Exception creating remote object.";
    return base::nullopt;
  } else {
    return result.result;
  }
}

bool DebugScriptRunner::RunCommand(const std::string& method,
                                   const std::string& json_params,
                                   std::string* json_result) {
  // If either the domain or the method are undefined in JavaScript, return
  // an empty string to indicate it's unimplemented. Otherwise go ahead and
  // run the method, letting it fail if there's any exception.
  std::string domain(method, 0, method.find('.'));
  std::string script = base::StringPrintf(
      "(typeof %s.%s === 'undefined' || typeof %s.%s === 'undefined')"
      "    ? '' : %s.%s(%s);",
      kObjectIdentifier, domain.c_str(), kObjectIdentifier, method.c_str(),
      kObjectIdentifier, method.c_str(), json_params.c_str());
  return EvaluateScript(script, json_result);
}

bool DebugScriptRunner::RunScriptFile(const std::string& filename) {
  std::string result;
  bool success = EvaluateScriptFile(filename, &result);
  if (!success) {
    DLOG(WARNING) << "Failed to run script file " << filename << ": " << result;
  }
  return success;
}

bool DebugScriptRunner::EvaluateScript(const std::string& js_code,
                                       std::string* result) {
  DCHECK(global_environment_);
  DCHECK(result);
  scoped_refptr<script::SourceCode> source_code =
      script::SourceCode::CreateSourceCode(js_code, GetInlineSourceLocation());

  ForceEnableEval();
  bool succeeded = global_environment_->EvaluateScript(source_code, result);
  SetEvalAllowedFromCsp();
  return succeeded;
}

bool DebugScriptRunner::EvaluateScriptFile(const std::string& filename,
                                           std::string* result) {
  DCHECK(result);

  FilePath file_path;
  PathService::Get(paths::DIR_COBALT_WEB_ROOT, &file_path);
  file_path = file_path.AppendASCII(kContentDir);
  file_path = file_path.AppendASCII(filename);

  std::string script;
  if (!file_util::ReadFileToString(file_path, &script)) {
    DLOG(WARNING) << "Cannot read file: " << file_path.value();
    return false;
  }

  return EvaluateScript(script, result);
}

void DebugScriptRunner::SendEvent(const std::string& method,
                                  const base::optional<std::string>& params) {
  on_event_callback_.Run(method, params);
}

void DebugScriptRunner::ForceEnableEval() {
  global_environment_->EnableEval();
  global_environment_->SetReportEvalCallback(base::Closure());
}

void DebugScriptRunner::SetEvalAllowedFromCsp() {
  std::string eval_disabled_message;
  bool allow_eval = csp_delegate_->AllowEval(&eval_disabled_message);
  if (allow_eval) {
    global_environment_->EnableEval();
  } else {
    global_environment_->DisableEval(eval_disabled_message);
  }

  global_environment_->SetReportEvalCallback(base::Bind(
      &dom::CspDelegate::ReportEval, base::Unretained(csp_delegate_)));
}

const DebugScriptRunner::CreateRemoteObjectCallbackHolder*
DebugScriptRunner::create_remote_object_callback() {
  if (create_remote_object_callback_) {
    return &(create_remote_object_callback_->referenced_value());
  } else {
    return NULL;
  }
}

void DebugScriptRunner::set_create_remote_object_callback(
    const CreateRemoteObjectCallbackHolder& callback) {
  create_remote_object_callback_.emplace(this, callback);
}

}  // namespace debug
}  // namespace cobalt
