blob: 41f3ce1d7f181f4927579284aad27a0e5594b197 [file] [log] [blame]
// Copyright 2015 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/console/debug_hub.h"
#include <memory>
#include <set>
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/json/json_writer.h"
#include "base/path_service.h"
#include "base/values.h"
#include "cobalt/base/c_val.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/debug/console/command_manager.h"
#include "cobalt/debug/json_object.h"
namespace cobalt {
namespace debug {
namespace console {
namespace {
constexpr char kContentDir[] = "debug_console";
} // namespace
DebugHub::DebugHub(
const GetHudModeCallback& get_hud_mode_callback,
const CreateDebugClientCallback& create_debug_client_callback)
: c_val_(new dom::CValView()),
get_hud_mode_callback_(get_hud_mode_callback),
create_debug_client_callback_(create_debug_client_callback),
on_event_(new DebuggerEventTarget()) {}
DebugHub::~DebugHub() {}
debug::console::DebugConsoleMode DebugHub::GetDebugConsoleMode() const {
return get_hud_mode_callback_.Run();
}
void DebugHub::Attach(const AttachCallbackArg& callback) {
last_error_ = base::nullopt;
debug_client_ = create_debug_client_callback_.Run(this);
// |debug_client_| may be NULL if the WebModule is not available at this time.
if (!debug_client_) {
DLOG(WARNING) << "Debug dispatcher unavailable.";
last_error_ = "Debug dispatcher unavailable.";
}
AttachCallbackArg::Reference callback_reference(this, callback);
callback_reference.value().Run();
}
void DebugHub::Detach(const AttachCallbackArg& callback) {
last_error_ = base::nullopt;
debug_client_.reset();
AttachCallbackArg::Reference callback_reference(this, callback);
callback_reference.value().Run();
}
std::string DebugHub::ReadDebugContentText(const std::string& filename) {
std::string result;
base::FilePath file_path;
base::PathService::Get(paths::DIR_COBALT_WEB_ROOT, &file_path);
file_path = file_path.AppendASCII(kContentDir);
file_path = file_path.AppendASCII(filename);
std::string text;
if (!base::ReadFileToString(file_path, &text)) {
DLOG(WARNING) << "Cannot read file: " << file_path.value();
}
return text;
}
void DebugHub::SendCommand(const std::string& method,
const std::string& json_params,
const ResponseCallbackArg& callback) {
last_error_ = base::nullopt;
if (!debug_client_ || !debug_client_->IsAttached()) {
std::unique_ptr<base::DictionaryValue> response(new base::DictionaryValue);
response->SetString("error.message", "Debugger is not connected.");
std::string json_response;
auto* response_as_value = static_cast<const base::Value*>(response.get());
base::JSONWriter::Write(*response_as_value, &json_response);
ResponseCallbackArg::Reference callback_ref(this, callback);
callback_ref.value().Run(json_response);
return;
}
scoped_refptr<ResponseCallbackInfo> callback_info(
new ResponseCallbackInfo(this, callback));
debug_client_->SendCommand(
method, json_params,
base::Bind(&DebugHub::OnCommandResponse, this, callback_info));
}
const script::Sequence<ConsoleCommand> DebugHub::console_commands() const {
script::Sequence<ConsoleCommand> result;
ConsoleCommandManager* command_manager = ConsoleCommandManager::GetInstance();
DCHECK(command_manager);
if (command_manager) {
std::set<std::string> commands = command_manager->GetRegisteredCommands();
for (std::set<std::string>::const_iterator it = commands.begin();
it != commands.end(); ++it) {
ConsoleCommand console_command;
console_command.set_command(*it);
console_command.set_short_help(command_manager->GetShortHelp(*it));
console_command.set_long_help(command_manager->GetLongHelp(*it));
result.push_back(console_command);
}
}
return result;
}
void DebugHub::SendConsoleCommand(const std::string& command,
const std::string& message) {
ConsoleCommandManager* console_command_manager =
ConsoleCommandManager::GetInstance();
DCHECK(console_command_manager);
console_command_manager->HandleCommand(command, message);
}
void DebugHub::TraceMembers(script::Tracer* tracer) {
tracer->Trace(on_event_);
}
void DebugHub::OnCommandResponse(
const scoped_refptr<ResponseCallbackInfo>& callback_info,
const base::Optional<std::string>& response) const {
// Run the script callback on the message loop the command was sent from.
callback_info->task_runner->PostTask(
FROM_HERE, base::Bind(&DebugHub::RunResponseCallback, this, callback_info,
response));
}
void DebugHub::OnDebugClientEvent(const std::string& method,
const std::string& params) {
// Pass to the onEvent handler. The handler will notify the JavaScript
// listener on the message loop the listener was registered on.
on_event_->DispatchEvent(method, params);
}
void DebugHub::OnDebugClientDetach(const std::string& reason) {
DLOG(INFO) << "Debugger detached: " + reason;
const std::string method = "Inspector.detached";
JSONObject params(new base::DictionaryValue());
params->SetString("reason", reason);
on_event_->DispatchEvent(method, JSONStringify(params));
}
void DebugHub::RunResponseCallback(
const scoped_refptr<ResponseCallbackInfo>& callback_info,
base::Optional<std::string> response) const {
DCHECK_EQ(base::MessageLoop::current()->task_runner(),
callback_info->task_runner);
callback_info->callback.value().Run(std::move(response));
}
} // namespace console
} // namespace debug
} // namespace cobalt