Skip to content

Commit

Permalink
[DevTools] Capabilities on browser side.
Browse files Browse the repository at this point in the history
BUG=504412

Review URL: https://codereview.chromium.org/1208993002

Cr-Commit-Position: refs/heads/master@{#336772}
  • Loading branch information
dgozman authored and Commit bot committed Jun 30, 2015
1 parent cbb2d96 commit ec5a24b
Show file tree
Hide file tree
Showing 10 changed files with 158 additions and 25 deletions.
13 changes: 7 additions & 6 deletions content/browser/devtools/devtools_protocol_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,13 +55,13 @@ void DevToolsProtocolHandler::HandleMessage(const std::string& message) {
}

bool DevToolsProtocolHandler::HandleOptionalMessage(
const std::string& message, int* call_id) {
const std::string& message, int* call_id, std::string* method) {
scoped_ptr<base::DictionaryValue> command = ParseCommand(message);
if (!command)
return true;
if (PassCommandToDelegate(command.get()))
return true;
return HandleOptionalCommand(command.Pass(), call_id);
return HandleOptionalCommand(command.Pass(), call_id, method);
}

bool DevToolsProtocolHandler::PassCommandToDelegate(
Expand Down Expand Up @@ -134,13 +134,14 @@ void DevToolsProtocolHandler::HandleCommand(
}

bool DevToolsProtocolHandler::HandleOptionalCommand(
scoped_ptr<base::DictionaryValue> command, int* call_id) {
scoped_ptr<base::DictionaryValue> command,
int* call_id,
std::string* method) {
*call_id = DevToolsProtocolClient::kNoId;
std::string method;
command->GetInteger(kIdParam, call_id);
command->GetString(kMethodParam, &method);
command->GetString(kMethodParam, method);
DevToolsProtocolDispatcher::CommandHandler command_handler(
dispatcher_.FindCommandHandler(method));
dispatcher_.FindCommandHandler(*method));
if (!command_handler.is_null()) {
return command_handler.Run(
*call_id, TakeDictionary(command.get(), kParamsParam));
Expand Down
7 changes: 5 additions & 2 deletions content/browser/devtools/devtools_protocol_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ class DevToolsProtocolHandler {
virtual ~DevToolsProtocolHandler();

void HandleMessage(const std::string& message);
bool HandleOptionalMessage(const std::string& message, int* call_id);
bool HandleOptionalMessage(const std::string& message,
int* call_id,
std::string* method);

DevToolsProtocolDispatcher* dispatcher() { return &dispatcher_; }

Expand All @@ -30,7 +32,8 @@ class DevToolsProtocolHandler {
bool PassCommandToDelegate(base::DictionaryValue* command);
void HandleCommand(scoped_ptr<base::DictionaryValue> command);
bool HandleOptionalCommand(scoped_ptr<base::DictionaryValue> command,
int* call_id);
int* call_id,
std::string* method);

DevToolsAgentHost* agent_host_;
DevToolsProtocolClient client_;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ class DevToolsProtocolDispatcher;
template<>
base::Value* CreateValue(const std::string& param);
${capabilities}\
${types}\
} // namespace devtools
Expand Down Expand Up @@ -102,6 +104,30 @@ class DevToolsProtocolDispatcher {
#endif // CONTENT_BROWSER_DEVTOOLS_PROTOCOL_DEVTOOLS_PROTOCOL_DISPATCHER_H_
""")

tmpl_domain_capability = string.Template("""\
static const char ${capability}[];
""")

tmpl_domain_capabilities = string.Template("""\
namespace ${domain} {
struct Capabilities {
static const char ${Domain}[];
${capabilities}\
};
} // namespace ${domain}
""")

tmpl_domain_capability_impl = string.Template("""\
const char Capabilities::${capability}[] = "${Domain}.${capability_lower}";
""")

tmpl_domain_capabilities_impl = string.Template("""\
namespace ${domain} {
const char Capabilities::${Domain}[] = "${Domain}";
${capabilities}\
} // namespace ${domain}
""")

tmpl_typedef = string.Template("""\
namespace ${domain} {
typedef ${param_type} ${declared_name};
Expand Down Expand Up @@ -284,6 +310,8 @@ class Client : public DevToolsProtocolClient {
return new base::StringValue(param);
}
${capabilities}\
${types}\
} // namespace devtools
Expand Down Expand Up @@ -629,6 +657,8 @@ def ResolveType(json, mapping):
raise Exception("Unknown type at %s.%s %s" %
(mapping["Domain"], mapping["command"], mapping["proto_param"]))

capabilities = []
capabilities_impl = []
setters = []
fields = []

Expand All @@ -646,6 +676,25 @@ def ResolveType(json, mapping):
domain_empty = True
domain_needs_client = False

domain_capabilities = []
domain_capabilities_impl = []
if "capabilities" in json_domain:
for json_capability in json_domain["capabilities"]:
domain_capabilities.append(tmpl_domain_capability.substitute(
domain_map,
capability=Capitalize(json_capability["name"])))
domain_capabilities_impl.append(tmpl_domain_capability_impl.substitute(
domain_map,
capability=Capitalize(json_capability["name"]),
capability_lower=json_capability["name"]))

capabilities.append(tmpl_domain_capabilities.substitute(
domain_map,
capabilities="\n".join(domain_capabilities)))
capabilities_impl.append(tmpl_domain_capabilities_impl.substitute(
domain_map,
capabilities="\n".join(domain_capabilities_impl)))

if "commands" in json_domain:
for json_command in json_domain["commands"]:
if (not ("handlers" in json_command) or
Expand Down Expand Up @@ -784,6 +833,7 @@ def ResolveType(json, mapping):
output_cc_file = open(output_cc_path, "w")

output_h_file.write(template_h.substitute({},
capabilities = "\n".join(capabilities),
types = "\n".join(type_decls),
setters = "".join(setters),
methods = "".join(handler_methods),
Expand All @@ -796,5 +846,6 @@ def ResolveType(json, mapping):
includes = "".join(sorted(includes)),
fields_init = ",\n ".join(fields_init),
methods = "\n".join(handler_method_impls),
capabilities = "\n".join(capabilities_impl),
types = "\n".join(type_impls)))
output_cc_file.close()
16 changes: 11 additions & 5 deletions content/browser/devtools/protocol/emulation_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -112,16 +112,22 @@ Response EmulationHandler::SetTouchEmulationEnabled(
}

Response EmulationHandler::CanEmulate(bool* result) {
*result = IsDeviceEmulationAvailable();
return Response::OK();
}

bool EmulationHandler::IsDeviceEmulationAvailable() {
bool result;
#if defined(OS_ANDROID)
*result = false;
result = false;
#else
*result = true;
result = true;
if (WebContentsImpl* web_contents = GetWebContents())
*result &= !web_contents->GetVisibleURL().SchemeIs(kChromeDevToolsScheme);
result &= !web_contents->GetVisibleURL().SchemeIs(kChromeDevToolsScheme);
if (host_ && host_->GetRenderWidgetHost())
*result &= !host_->GetRenderWidgetHost()->auto_resize_enabled();
result &= !host_->GetRenderWidgetHost()->auto_resize_enabled();
#endif // defined(OS_ANDROID)
return Response::OK();
return result;
}

Response EmulationHandler::SetDeviceMetricsOverride(
Expand Down
1 change: 1 addition & 0 deletions content/browser/devtools/protocol/emulation_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class EmulationHandler : public page::PageHandler::ScreencastListener {

void SetRenderFrameHost(RenderFrameHostImpl* host);
void Detached();
bool IsDeviceEmulationAvailable();

Response SetGeolocationOverride(double* latitude,
double* longitude,
Expand Down
13 changes: 10 additions & 3 deletions content/browser/devtools/protocol/page_handler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -271,12 +271,19 @@ Response PageHandler::CaptureScreenshot(DevToolsCommandId command_id) {
}

Response PageHandler::CanScreencast(bool* result) {
*result = IsScreencastAvailable();
return Response::OK();
}

bool PageHandler::IsScreencastAvailable()
{
bool result;
#if defined(OS_ANDROID)
*result = true;
result = true;
#else
*result = false;
result = false;
#endif // defined(OS_ANDROID)
return Response::OK();
return result;
}

Response PageHandler::StartScreencast(const std::string* format,
Expand Down
1 change: 1 addition & 0 deletions content/browser/devtools/protocol/page_handler.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ class PageHandler : public NotificationObserver {
void DidDetachInterstitialPage();
void SetScreencastListener(ScreencastListener* listener);
bool screencast_enabled() const { return enabled_ && screencast_enabled_; }
bool IsScreencastAvailable();

Response Enable();
Response Disable();
Expand Down
73 changes: 65 additions & 8 deletions content/browser/devtools/render_frame_devtools_agent_host.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#include "content/browser/devtools/render_frame_devtools_agent_host.h"

#include "base/basictypes.h"
#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#include "base/lazy_instance.h"
#include "base/strings/utf_string_conversions.h"
#include "content/browser/child_process_security_policy_impl.h"
Expand Down Expand Up @@ -41,6 +43,10 @@ namespace content {
typedef std::vector<RenderFrameDevToolsAgentHost*> Instances;

namespace {

const char kGetCapabilitiesMethod[] = "Inspector.getCapabilities";
const char kCapabilitiesResultPath[] = "result.capabilities";

base::LazyInstance<Instances>::Leaky g_instances = LAZY_INSTANCE_INITIALIZER;

static RenderFrameDevToolsAgentHost* FindAgentHost(RenderFrameHost* host) {
Expand Down Expand Up @@ -102,7 +108,7 @@ class RenderFrameDevToolsAgentHost::FrameHostHolder {
bool attached_;
bool suspended_;
DevToolsMessageChunkProcessor chunk_processor_;
std::vector<std::string> pending_messages_;
std::vector<std::pair<std::string, int>> pending_messages_;
std::map<int, std::string> sent_messages_;
};

Expand Down Expand Up @@ -199,11 +205,12 @@ RenderFrameDevToolsAgentHost::FrameHostHolder::ProcessChunkedMessageFromAgent(

void RenderFrameDevToolsAgentHost::FrameHostHolder::SendMessageToClient(
const std::string& message) {
sent_messages_.erase(chunk_processor_.last_call_id());
int call_id = chunk_processor_.last_call_id();
sent_messages_.erase(call_id);
if (suspended_)
pending_messages_.push_back(message);
pending_messages_.push_back(std::make_pair(message, call_id));
else
agent_->SendMessageToClient(message);
agent_->OnMessageFromBackend(message, call_id);
}

void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {
Expand All @@ -212,9 +219,9 @@ void RenderFrameDevToolsAgentHost::FrameHostHolder::Suspend() {

void RenderFrameDevToolsAgentHost::FrameHostHolder::Resume() {
suspended_ = false;
for (const std::string& message : pending_messages_)
agent_->SendMessageToClient(message);
std::vector<std::string> empty;
for (const auto& pair : pending_messages_)
agent_->OnMessageFromBackend(pair.first, pair.second);
std::vector<std::pair<std::string, int>> empty;
pending_messages_.swap(empty);
}

Expand Down Expand Up @@ -310,27 +317,43 @@ RenderFrameDevToolsAgentHost::RenderFrameDevToolsAgentHost(
current_frame_crashed_(false) {
DevToolsProtocolDispatcher* dispatcher = protocol_handler_->dispatcher();
dispatcher->SetDOMHandler(dom_handler_.get());
capabilities_.push_back(devtools::dom::Capabilities::DOM);
dispatcher->SetInputHandler(input_handler_.get());
capabilities_.push_back(devtools::input::Capabilities::Input);
dispatcher->SetInspectorHandler(inspector_handler_.get());
capabilities_.push_back(devtools::inspector::Capabilities::Inspector);
dispatcher->SetNetworkHandler(network_handler_.get());
capabilities_.push_back(devtools::network::Capabilities::Network);
dispatcher->SetPowerHandler(power_handler_.get());
capabilities_.push_back(devtools::power::Capabilities::Power);
dispatcher->SetServiceWorkerHandler(service_worker_handler_.get());
capabilities_.push_back(
devtools::service_worker::Capabilities::ServiceWorker);
dispatcher->SetTracingHandler(tracing_handler_.get());
capabilities_.push_back(devtools::tracing::Capabilities::Tracing);

if (!host->GetParent()) {
security_handler_.reset(new devtools::security::SecurityHandler());
page_handler_.reset(new devtools::page::PageHandler());
emulation_handler_.reset(
new devtools::emulation::EmulationHandler(page_handler_.get()));
dispatcher->SetSecurityHandler(security_handler_.get());
capabilities_.push_back(devtools::security::Capabilities::Security);
dispatcher->SetPageHandler(page_handler_.get());
capabilities_.push_back(devtools::page::Capabilities::Page);
dispatcher->SetEmulationHandler(emulation_handler_.get());
capabilities_.push_back(devtools::emulation::Capabilities::Emulation);
}

SetPending(host);
CommitPending();
WebContentsObserver::Observe(WebContents::FromRenderFrameHost(host));

if (emulation_handler_ && emulation_handler_->IsDeviceEmulationAvailable())
capabilities_.push_back(devtools::emulation::Capabilities::DeviceMetrics);
if (page_handler_ && page_handler_->IsScreencastAvailable())
capabilities_.push_back(devtools::page::Capabilities::Screencast);

g_instances.Get().push_back(this);
AddRef(); // Balanced in RenderFrameHostDestroyed.
}
Expand Down Expand Up @@ -401,8 +424,11 @@ void RenderFrameDevToolsAgentHost::Detach() {
bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
const std::string& message) {
int call_id = 0;
if (protocol_handler_->HandleOptionalMessage(message, &call_id))
std::string method;
if (protocol_handler_->HandleOptionalMessage(message, &call_id, &method))
return true;
if (method == kGetCapabilitiesMethod)
get_capabilities_call_ids_.insert(call_id);

if (current_)
current_->DispatchProtocolMessage(call_id, message);
Expand All @@ -411,6 +437,37 @@ bool RenderFrameDevToolsAgentHost::DispatchProtocolMessage(
return true;
}

void RenderFrameDevToolsAgentHost::OnMessageFromBackend(
const std::string& message, int call_id) {
if (get_capabilities_call_ids_.find(call_id) !=
get_capabilities_call_ids_.end()) {
get_capabilities_call_ids_.erase(call_id);
SendMessageToClient(AppendCapabilities(message));
} else {
SendMessageToClient(message);
}
}

std::string RenderFrameDevToolsAgentHost::AppendCapabilities(
const std::string& message) {
scoped_ptr<base::Value> value = base::JSONReader::Read(message);
if (!value || !value->IsType(base::Value::TYPE_DICTIONARY))
return message;
scoped_ptr<base::DictionaryValue> dict =
make_scoped_ptr(static_cast<base::DictionaryValue*>(value.release()));
base::ListValue* list;
if (!dict->GetList(kCapabilitiesResultPath, &list))
return message;

for (const std::string& capabilitiy : capabilities_) {
scoped_ptr<base::StringValue> value(new base::StringValue(capabilitiy));
if (list->Find(*value) == list->end())
list->Append(value.Pass());
}
std::string result;
return base::JSONWriter::Write(*dict, &result) ? result : message;
}

void RenderFrameDevToolsAgentHost::InspectElement(int x, int y) {
if (current_)
current_->InspectElement(x, y);
Expand Down
5 changes: 5 additions & 0 deletions content/browser/devtools/render_frame_devtools_agent_host.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,9 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
void OnSwapCompositorFrame(const IPC::Message& message);
void DestroyOnRenderFrameGone();

void OnMessageFromBackend(const std::string& message, int call_id);
std::string AppendCapabilities(const std::string& message);

class FrameHostHolder;

scoped_ptr<FrameHostHolder> current_;
Expand All @@ -144,6 +147,8 @@ class CONTENT_EXPORT RenderFrameDevToolsAgentHost
#endif
scoped_ptr<DevToolsProtocolHandler> protocol_handler_;
bool current_frame_crashed_;
std::set<int> get_capabilities_call_ids_;
std::vector<std::string> capabilities_;

DISALLOW_COPY_AND_ASSIGN(RenderFrameDevToolsAgentHost);
};
Expand Down
Loading

0 comments on commit ec5a24b

Please sign in to comment.