Skip to content

Commit

Permalink
Add boxdump debug command
Browse files Browse the repository at this point in the history
  • Loading branch information
jellefoks committed Jan 24, 2024
1 parent 6dd5f99 commit eed136a
Show file tree
Hide file tree
Showing 36 changed files with 235 additions and 106 deletions.
27 changes: 27 additions & 0 deletions cobalt/browser/browser_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,17 @@ const char kFuzzerToggleCommandLongHelp[] =
"activated or not. While activated, input will constantly and randomly be "
"generated and passed directly into the main web module.";

#if defined(ENABLE_DEBUGGER)
// Command to reload the current URL.
const char kBoxDumpCommand[] = "boxdump";

// Help strings for the navigate command.
const char kBoxDumpCommandShortHelp[] = "Makes a box dump.";
const char kBoxDumpCommandLongHelp[] =
"Creates a box dump of the most recent box tree and writes it "
"to disk. Logs the filename of the boxdump to the console when done.";
#endif

const char kScreenshotCommand[] = "screenshot";
const char kScreenshotCommandShortHelp[] = "Takes a screenshot.";
const char kScreenshotCommandLongHelp[] =
Expand Down Expand Up @@ -263,6 +274,12 @@ BrowserModule::BrowserModule(const GURL& url,
kFuzzerToggleCommand,
base::Bind(&BrowserModule::OnFuzzerToggle, base::Unretained(this)),
kFuzzerToggleCommandShortHelp, kFuzzerToggleCommandLongHelp)),
#if defined(ENABLE_DEBUGGER)
ALLOW_THIS_IN_INITIALIZER_LIST(boxdump_command_handler_(
kBoxDumpCommand,
base::Bind(&BrowserModule::OnBoxDumpMessage, base::Unretained(this)),
kBoxDumpCommandShortHelp, kBoxDumpCommandLongHelp)),
#endif // defined(ENABLE_DEBUGGER)
ALLOW_THIS_IN_INITIALIZER_LIST(screenshot_command_handler_(
kScreenshotCommand,
base::Bind(&OnScreenshotMessage, base::Unretained(this)),
Expand Down Expand Up @@ -2222,5 +2239,15 @@ void BrowserModule::ValidateCacheBackendSettings() {
network_module_->url_request_context()->ValidateCachePersistentSettings();
}

#if defined(ENABLE_DEBUGGER)
std::string BrowserModule::OnBoxDumpMessage(const std::string& message) {
std::string response = "No MainWebModule.";
if (web_module_) {
response = web_module_->OnBoxDumpMessage(message);
}
return response;
}
#endif

} // namespace browser
} // namespace cobalt
9 changes: 9 additions & 0 deletions cobalt/browser/browser_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,6 +243,10 @@ class BrowserModule {
// Pass the deeplink timestamp from Starboard.
void SetDeepLinkTimestamp(int64_t timestamp);

#if defined(ENABLE_DEBUGGER)
std::string OnBoxDumpMessage(const std::string& message);
#endif // ENABLE_DEBUGGER

private:
// Called when the WebModule's Window.onload event is fired.
void OnLoad();
Expand Down Expand Up @@ -646,6 +650,11 @@ class BrowserModule {
// Command handler object for toggling the input fuzzer on/off.
debug::console::ConsoleCommandManager::CommandHandler
fuzzer_toggle_command_handler_;
#if defined(ENABLE_DEBUGGER)
// Command handler object for boxdump command from the debug console.
debug::console::ConsoleCommandManager::CommandHandler
boxdump_command_handler_;
#endif

// Command handler object for screenshot command from the debug console.
debug::console::ConsoleCommandManager::CommandHandler
Expand Down
52 changes: 49 additions & 3 deletions cobalt/browser/web_module.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,16 +21,19 @@
#include "base/bind.h"
#include "base/callback.h"
#include "base/command_line.h"
#include "base/files/file_util.h"
#include "base/logging.h"
#include "base/memory/weak_ptr.h"
#include "base/message_loop/message_loop.h"
#include "base/optional.h"
#include "base/path_service.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "cobalt/base/c_val.h"
#include "cobalt/base/cobalt_paths.h"
#include "cobalt/base/debugger_hooks.h"
#include "cobalt/base/language.h"
#include "cobalt/base/tokens.h"
Expand All @@ -43,6 +46,7 @@
#include "cobalt/css_parser/parser.h"
#include "cobalt/dom/element.h"
#include "cobalt/dom/global_stats.h"
#include "cobalt/dom/html_html_element.h"
#include "cobalt/dom/html_script_element.h"
#include "cobalt/dom/input_event.h"
#include "cobalt/dom/input_event_init.h"
Expand All @@ -59,6 +63,7 @@
#include "cobalt/dom/wheel_event.h"
#include "cobalt/dom/window.h"
#include "cobalt/dom_parser/parser.h"
#include "cobalt/layout/container_box.h"
#include "cobalt/layout/topmost_event_target.h"
#include "cobalt/loader/image/animated_image_tracker.h"
#include "cobalt/loader/loader_factory.h"
Expand All @@ -85,7 +90,7 @@
namespace cobalt {
namespace browser {

using cobalt::cssom::ViewportSize;
using cssom::ViewportSize;

namespace {

Expand Down Expand Up @@ -282,6 +287,10 @@ class WebModule::Impl {
void SetUnloadEventTimingInfo(base::TimeTicks start_time,
base::TimeTicks end_time);

#if defined(ENABLE_DEBUGGER)
std::string OnBoxDumpMessage(const std::string& message);
#endif // ENABLE_DEBUGGER

private:
class DocumentLoadedObserver;

Expand Down Expand Up @@ -464,8 +473,7 @@ class WebModule::Impl {

bool should_retain_remote_typeface_cache_on_freeze_;

scoped_refptr<cobalt::dom::captions::SystemCaptionSettings>
system_caption_settings_;
scoped_refptr<dom::captions::SystemCaptionSettings> system_caption_settings_;

// This event is used to interrupt the loader when JavaScript is loaded
// synchronously. It is manually reset so that events like Freeze can be
Expand Down Expand Up @@ -1699,5 +1707,43 @@ void WebModule::SetUnloadEventTimingInfo(base::TimeTicks start_time,
impl_->SetUnloadEventTimingInfo(start_time, end_time);
}

#if defined(ENABLE_DEBUGGER)
std::string WebModule::OnBoxDumpMessage(const std::string& message) {
if (message_loop()->task_runner()->BelongsToCurrentThread()) {
return impl_->OnBoxDumpMessage(message);
} else {
std::string response;
message_loop()->task_runner()->PostBlockingTask(
FROM_HERE, base::Bind(
[](WebModule::Impl* impl, const std::string& message,
std::string* response) {
*response = impl->OnBoxDumpMessage(message);
},
base::Unretained(impl_.get()), message, &response));
return response;
}
}

std::string WebModule::Impl::OnBoxDumpMessage(const std::string& message) {
DCHECK(window_);
std::string boxdump;
dom::HTMLElement* html_element = window_->document()->html();
if (html_element->layout_boxes() &&
html_element->layout_boxes()->type() ==
dom::LayoutBoxes::kLayoutLayoutBoxes) {
layout::LayoutBoxes* layout_boxes =
base::polymorphic_downcast<layout::LayoutBoxes*>(
html_element->layout_boxes());
if (!layout_boxes->boxes().empty()) {
std::ostringstream out("", std::ios_base::ate);
layout_boxes->boxes()[0]->GetContainingBlock()->DumpWithIndent(&out, 0);
boxdump = out.str();
}
}
return boxdump;
}

#endif // ENABLE_DEBUGGER

} // namespace browser
} // namespace cobalt
4 changes: 4 additions & 0 deletions cobalt/browser/web_module.h
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,10 @@ class WebModule : public base::MessageLoop::DestructionObserver,
void SetUnloadEventTimingInfo(base::TimeTicks start_time,
base::TimeTicks end_time);

#if defined(ENABLE_DEBUGGER)
std::string OnBoxDumpMessage(const std::string& message);
#endif // ENABLE_DEBUGGER

private:
// Data required to construct a WebModule, initialized in the constructor and
// passed to |InitializeTaskInThread|.
Expand Down
7 changes: 5 additions & 2 deletions cobalt/debug/backend/cobalt_agent.cc
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,16 @@ void CobaltAgent::SendConsoleCommand(Command command) {
if (params) {
std::string console_command;
if (params->GetString("command", &console_command)) {
JSONObject response(new base::DictionaryValue());
std::string message;
params->GetString("message", &message);
console::ConsoleCommandManager* console_command_manager =
console::ConsoleCommandManager::GetInstance();
DCHECK(console_command_manager);
console_command_manager->HandleCommand(console_command, message);
command.SendResponse();
std::string response_string =
console_command_manager->HandleCommand(console_command, message);
response->SetString("result", std::move(response_string));
command.SendResponse(response);
return;
}
}
Expand Down
34 changes: 28 additions & 6 deletions cobalt/debug/console/command_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,10 +29,23 @@ ConsoleCommandManager* ConsoleCommandManager::GetInstance() {

ConsoleCommandManager::CommandHandler::CommandHandler(
const std::string& command,
const ConsoleCommandManager::CommandCallback& callback,
const ConsoleCommandManager::VoidCommandCallback& callback,
const std::string& short_help, const std::string& long_help)
: command_(command),
callback_(callback),
void_callback_(callback),
short_help_(short_help),
long_help_(long_help) {
ConsoleCommandManager* manager = ConsoleCommandManager::GetInstance();
DCHECK(manager);
manager->RegisterCommandHandler(this);
}

ConsoleCommandManager::CommandHandler::CommandHandler(
const std::string& command,
const ConsoleCommandManager::StringCommandCallback& callback,
const std::string& short_help, const std::string& long_help)
: command_(command),
string_callback_(callback),
short_help_(short_help),
long_help_(long_help) {
ConsoleCommandManager* manager = ConsoleCommandManager::GetInstance();
Expand All @@ -56,16 +69,25 @@ bool ConsoleCommandManager::CommandHandler::IsOnEnableOrTrue(
}


void ConsoleCommandManager::HandleCommand(const std::string& command,
const std::string& message) const {
std::string ConsoleCommandManager::HandleCommand(
const std::string& command, const std::string& message) const {
DCHECK_GT(command.length(), size_t(0));
base::AutoLock auto_lock(lock_);
CommandHandlerMap::const_iterator iter = command_command_map_.find(command);
std::string response;
if (iter != command_command_map_.end()) {
iter->second->callback().Run(message);
const CommandHandler* handler = iter->second;
if (!handler->void_callback().is_null()) {
handler->void_callback().Run(message);
response = "Command dispatched.";
} else if (!handler->string_callback().is_null()) {
response = handler->string_callback().Run(message);
}
} else {
DLOG(WARNING) << "No handler registered for command: " << command;
response = "No handler registered for command";
}
DLOG(INFO) << "Console Command " << command << " response: \n" << response;
return response;
}

std::set<std::string> ConsoleCommandManager::GetRegisteredCommands() const {
Expand Down
22 changes: 16 additions & 6 deletions cobalt/debug/console/command_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,17 +47,26 @@ namespace console {
class ConsoleCommandManager {
public:
// Type for a callback to handle a command.
typedef base::Callback<void(const std::string& message)> CommandCallback;
typedef base::Callback<void(const std::string& message)> VoidCommandCallback;
typedef base::Callback<std::string(const std::string& message)>
StringCommandCallback;

// Command handler that registers itself with this object.
class CommandHandler {
public:
CommandHandler(const std::string& command, const CommandCallback& callback,
CommandHandler(const std::string& command,
const VoidCommandCallback& callback,
const std::string& short_help, const std::string& long_help);
CommandHandler(const std::string& command,
const StringCommandCallback& callback,
const std::string& short_help, const std::string& long_help);
~CommandHandler();

const std::string& command() const { return command_; }
const CommandCallback& callback() const { return callback_; }
const VoidCommandCallback& void_callback() const { return void_callback_; }
const StringCommandCallback& string_callback() const {
return string_callback_;
}
const std::string& short_help() const { return short_help_; }
const std::string& long_help() const { return long_help_; }

Expand All @@ -66,7 +75,8 @@ class ConsoleCommandManager {

private:
std::string command_;
CommandCallback callback_;
VoidCommandCallback void_callback_;
StringCommandCallback string_callback_;
std::string short_help_;
std::string long_help_;
};
Expand All @@ -78,8 +88,8 @@ class ConsoleCommandManager {

// Handles a command by posting the message to the handler registered for
// the specified command, if any.
void HandleCommand(const std::string& command,
const std::string& message) const;
std::string HandleCommand(const std::string& command,
const std::string& message) const;

// Returns a set of all the currently registered commands.
std::set<std::string> GetRegisteredCommands() const;
Expand Down
6 changes: 3 additions & 3 deletions cobalt/debug/console/debug_hub.cc
Original file line number Diff line number Diff line change
Expand Up @@ -127,12 +127,12 @@ const script::Sequence<ConsoleCommand> DebugHub::console_commands() const {
return result;
}

void DebugHub::SendConsoleCommand(const std::string& command,
const std::string& message) {
std::string 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);
return console_command_manager->HandleCommand(command, message);
}

void DebugHub::TraceMembers(script::Tracer* tracer) {
Expand Down
4 changes: 2 additions & 2 deletions cobalt/debug/console/debug_hub.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,8 +101,8 @@ class DebugHub : public script::Wrappable, public DebugClient::Delegate {
// Sends a console command to be handled in the context of the debug WebModule
// by a registered handler. This lets the JavaScript debug console trigger
// actions in the app.
void SendConsoleCommand(const std::string& command,
const std::string& message);
std::string SendConsoleCommand(const std::string& command,
const std::string& message);

DEFINE_WRAPPABLE_TYPE(DebugHub);
void TraceMembers(script::Tracer* tracer) override;
Expand Down
2 changes: 1 addition & 1 deletion cobalt/debug/console/debug_hub.idl
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@

// Provides list of custom commands for the debug console.
readonly attribute sequence<ConsoleCommand> consoleCommands;
void sendConsoleCommand(DOMString command, DOMString message);
DOMString sendConsoleCommand(DOMString command, DOMString message);
};

callback AttachCallback = void();
Expand Down
4 changes: 0 additions & 4 deletions cobalt/layout/BUILD.gn
Original file line number Diff line number Diff line change
Expand Up @@ -96,10 +96,6 @@ static_library("layout") {
"white_space_processing.h",
]

if (is_debug) {
defines = [ "COBALT_BOX_DUMP_ENABLED" ]
}

configs -= [ "//starboard/build/config:size" ]
configs += [ "//starboard/build/config:speed" ]

Expand Down
4 changes: 2 additions & 2 deletions cobalt/layout/anonymous_block_box.cc
Original file line number Diff line number Diff line change
Expand Up @@ -129,13 +129,13 @@ void AnonymousBlockBox::AddInlineLevelChild(
PushBackDirectChild(child_box);
}

#ifdef COBALT_BOX_DUMP_ENABLED
#ifdef ENABLE_DEBUGGER

void AnonymousBlockBox::DumpClassName(std::ostream* stream) const {
*stream << "AnonymousBlockBox ";
}

#endif // COBALT_BOX_DUMP_ENABLED
#endif // ENABLE_DEBUGGER

std::unique_ptr<FormattingContext>
AnonymousBlockBox::UpdateRectOfInFlowChildBoxes(
Expand Down
4 changes: 2 additions & 2 deletions cobalt/layout/anonymous_block_box.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,9 @@ class AnonymousBlockBox : public BlockContainerBox {

protected:
// From |Box|.
#ifdef COBALT_BOX_DUMP_ENABLED
#ifdef ENABLE_DEBUGGER
void DumpClassName(std::ostream* stream) const override;
#endif // COBALT_BOX_DUMP_ENABLED
#endif // ENABLE_DEBUGGER

// From |BlockContainerBox|.
std::unique_ptr<FormattingContext> UpdateRectOfInFlowChildBoxes(
Expand Down
Loading

0 comments on commit eed136a

Please sign in to comment.