| // 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 |