blob: 924dd9780b1ddb8e9dec19854d410b6c4324f006 [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.
#ifndef COBALT_DEBUG_DEBUGGER_H_
#define COBALT_DEBUG_DEBUGGER_H_
#if defined(ENABLE_DEBUG_CONSOLE)
#include <string>
#include "base/callback.h"
#include "base/memory/ref_counted.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop_proxy.h"
#include "base/optional.h"
#include "cobalt/debug/console_command.h"
#include "cobalt/debug/debug_client.h"
#include "cobalt/debug/debugger_event_target.h"
#include "cobalt/script/callback_function.h"
#include "cobalt/script/script_value.h"
#include "cobalt/script/value_handle.h"
#include "cobalt/script/wrappable.h"
namespace cobalt {
namespace debug {
// Custom interface to communicate with the debugger, modeled after
// chrome.debugger extension API.
// https://developer.chrome.com/extensions/debugger
class Debugger : public script::Wrappable, public DebugClient::Delegate {
public:
// JavaScript callback to be run when debugger at/detaches.
typedef script::CallbackFunction<void()> AttachCallback;
typedef script::ScriptValue<AttachCallback> AttachCallbackArg;
// JavaScript callback to receive the response after executing a command.
typedef script::CallbackFunction<void(base::optional<std::string>)>
ResponseCallback;
typedef script::ScriptValue<ResponseCallback> ResponseCallbackArg;
// Thread-safe ref-counted struct used to pass asynchronously executed
// response callbacks around. Stores the message loop the callback must be
// executed on as well as the callback itself.
struct ResponseCallbackInfo
: public base::RefCountedThreadSafe<ResponseCallbackInfo> {
ResponseCallbackInfo(Debugger* const debugger,
const ResponseCallbackArg& cb)
: callback(debugger, cb),
message_loop_proxy(base::MessageLoopProxy::current()) {}
ResponseCallbackArg::Reference callback;
scoped_refptr<base::MessageLoopProxy> message_loop_proxy;
friend class base::RefCountedThreadSafe<ResponseCallbackInfo>;
};
explicit Debugger(
const CreateDebugClientCallback& create_debug_client_callback);
~Debugger();
void Attach(const AttachCallbackArg& callback);
void Detach(const AttachCallbackArg& callback);
// Sends a devtools protocol command to be executed in the context of the main
// WebModule that is being debugged.
void SendCommand(const std::string& method, const std::string& json_params,
const ResponseCallbackArg& callback);
const base::optional<std::string>& last_error() const { return last_error_; }
const scoped_refptr<DebuggerEventTarget>& on_event() const {
return on_event_;
}
const script::Sequence<ConsoleCommand> console_commands() const;
// Sends a console command to be handled in the context of the debug WebModule
// by a registered hander. This lets the JavaScript debug console trigger
// actions in the app.
void SendConsoleCommand(const std::string& command,
const std::string& message);
DEFINE_WRAPPABLE_TYPE(Debugger);
void TraceMembers(script::Tracer* tracer) override;
protected:
// Called by the debug dispatcher with the response of a command on the
// message loop the command was sent from (the message loop of this object).
// Passes the response to the JavaScript callback registered with the command.
void OnCommandResponse(
const scoped_refptr<ResponseCallbackInfo>& callback_info,
const base::optional<std::string>& response) const;
// DebugClient::Delegate implementation.
void OnDebugClientEvent(
const std::string& method,
const base::optional<std::string>& json_params) override;
void OnDebugClientDetach(const std::string& reason) override;
private:
// Runs a script response callback with the specified response.
// Should be called from the same message loop as the script command that it
// is a response for.
void RunResponseCallback(
const scoped_refptr<ResponseCallbackInfo>& callback_info,
base::optional<std::string> response) const;
// Callback to be run to create a debug client.
CreateDebugClientCallback create_debug_client_callback_;
// Debug client that connects to the dispatcher.
scoped_ptr<DebugClient> debug_client_;
// This will be defined if there was an error since the last operation.
// TODO: Chrome implements similar functionality throughout the
// app using the chrome.runtime.lastError object. When we add support for
// Cobalt's equivalent to the runtime extension API, we may wish to consider
// using that and removing this attribute.
base::optional<std::string> last_error_;
// Handler for debugger events.
scoped_refptr<DebuggerEventTarget> on_event_;
};
} // namespace debug
} // namespace cobalt
#endif // ENABLE_DEBUG_CONSOLE
#endif // COBALT_DEBUG_DEBUGGER_H_