chore: enable debugger api specs (#14475)

This commit is contained in:
Robo 2018-09-06 20:14:22 +05:30 committed by Samuel Attard
parent 9bf1fb323b
commit 35a1849e31
3 changed files with 51 additions and 27 deletions

View file

@ -6,16 +6,13 @@
#include <string> #include <string>
#include "atom/browser/atom_browser_main_parts.h"
#include "atom/common/native_mate_converters/callback.h" #include "atom/common/native_mate_converters/callback.h"
#include "atom/common/native_mate_converters/value_converter.h" #include "atom/common/native_mate_converters/value_converter.h"
#include "base/json/json_reader.h" #include "base/json/json_reader.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "base/memory/ptr_util.h"
#include "content/public/browser/devtools_agent_host.h" #include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "native_mate/dictionary.h" #include "native_mate/dictionary.h"
#include "native_mate/object_template_builder.h"
#include "atom/common/node_includes.h" #include "atom/common/node_includes.h"
@ -26,20 +23,22 @@ namespace atom {
namespace api { namespace api {
Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents) Debugger::Debugger(v8::Isolate* isolate, content::WebContents* web_contents)
: web_contents_(web_contents) { : content::WebContentsObserver(web_contents), web_contents_(web_contents) {
Init(isolate); Init(isolate);
} }
Debugger::~Debugger() {} Debugger::~Debugger() {}
void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host) { void Debugger::AgentHostClosed(DevToolsAgentHost* agent_host) {
std::string detach_reason = "target closed"; DCHECK(agent_host == agent_host_);
Emit("detach", detach_reason); agent_host_ = nullptr;
ClearPendingRequests();
Emit("detach", "target closed");
} }
void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host, void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
const std::string& message) { const std::string& message) {
DCHECK(agent_host == agent_host_.get()); DCHECK(agent_host == agent_host_);
v8::Locker locker(isolate()); v8::Locker locker(isolate());
v8::HandleScope handle_scope(isolate()); v8::HandleScope handle_scope(isolate());
@ -77,42 +76,52 @@ void Debugger::DispatchProtocolMessage(DevToolsAgentHost* agent_host,
} }
} }
void Debugger::RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
content::RenderFrameHost* new_rfh) {
if (agent_host_) {
agent_host_->DisconnectWebContents();
auto* web_contents = content::WebContents::FromRenderFrameHost(new_rfh);
agent_host_->ConnectWebContents(web_contents);
}
}
void Debugger::Attach(mate::Arguments* args) { void Debugger::Attach(mate::Arguments* args) {
std::string protocol_version; std::string protocol_version;
args->GetNext(&protocol_version); args->GetNext(&protocol_version);
if (agent_host_) {
args->ThrowError("Debugger is already attached to the target");
return;
}
if (!protocol_version.empty() && if (!protocol_version.empty() &&
!DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) { !DevToolsAgentHost::IsSupportedProtocolVersion(protocol_version)) {
args->ThrowError("Requested protocol version is not supported"); args->ThrowError("Requested protocol version is not supported");
return; return;
} }
agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_); agent_host_ = DevToolsAgentHost::GetOrCreateFor(web_contents_);
if (!agent_host_.get()) { if (!agent_host_) {
args->ThrowError("No target available"); args->ThrowError("No target available");
return; return;
} }
if (agent_host_->IsAttached()) {
args->ThrowError("Another debugger is already attached to this target");
return;
}
agent_host_->AttachClient(this); agent_host_->AttachClient(this);
} }
bool Debugger::IsAttached() { bool Debugger::IsAttached() {
return agent_host_.get() ? agent_host_->IsAttached() : false; return agent_host_ && agent_host_->IsAttached();
} }
void Debugger::Detach() { void Debugger::Detach() {
if (!agent_host_.get()) if (!agent_host_)
return; return;
agent_host_->DetachClient(this); agent_host_->DetachClient(this);
AgentHostClosed(agent_host_.get()); AgentHostClosed(agent_host_.get());
agent_host_ = nullptr;
} }
void Debugger::SendCommand(mate::Arguments* args) { void Debugger::SendCommand(mate::Arguments* args) {
if (!agent_host_.get()) if (!agent_host_)
return; return;
std::string method; std::string method;
@ -139,6 +148,16 @@ void Debugger::SendCommand(mate::Arguments* args) {
agent_host_->DispatchProtocolMessage(this, json_args); agent_host_->DispatchProtocolMessage(this, json_args);
} }
void Debugger::ClearPendingRequests() {
if (pending_requests_.empty())
return;
base::Value error(base::Value::Type::DICTIONARY);
base::Value error_msg("target closed while handling command");
error.SetKey("message", std::move(error_msg));
for (const auto& it : pending_requests_)
it.second.Run(error, base::Value());
}
// static // static
mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate, mate::Handle<Debugger> Debugger::Create(v8::Isolate* isolate,
content::WebContents* web_contents) { content::WebContents* web_contents) {

View file

@ -12,6 +12,7 @@
#include "base/callback.h" #include "base/callback.h"
#include "base/values.h" #include "base/values.h"
#include "content/public/browser/devtools_agent_host_client.h" #include "content/public/browser/devtools_agent_host_client.h"
#include "content/public/browser/web_contents_observer.h"
#include "native_mate/handle.h" #include "native_mate/handle.h"
namespace content { namespace content {
@ -28,11 +29,11 @@ namespace atom {
namespace api { namespace api {
class Debugger : public mate::TrackableObject<Debugger>, class Debugger : public mate::TrackableObject<Debugger>,
public content::DevToolsAgentHostClient { public content::DevToolsAgentHostClient,
public content::WebContentsObserver {
public: public:
using SendCommandCallback = using SendCommandCallback =
base::Callback<void(const base::DictionaryValue&, base::Callback<void(const base::Value&, const base::Value&)>;
const base::DictionaryValue&)>;
static mate::Handle<Debugger> Create(v8::Isolate* isolate, static mate::Handle<Debugger> Create(v8::Isolate* isolate,
content::WebContents* web_contents); content::WebContents* web_contents);
@ -50,6 +51,10 @@ class Debugger : public mate::TrackableObject<Debugger>,
void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host, void DispatchProtocolMessage(content::DevToolsAgentHost* agent_host,
const std::string& message) override; const std::string& message) override;
// content::WebContentsObserver:
void RenderFrameHostChanged(content::RenderFrameHost* old_rfh,
content::RenderFrameHost* new_rfh) override;
private: private:
using PendingRequestMap = std::map<int, SendCommandCallback>; using PendingRequestMap = std::map<int, SendCommandCallback>;
@ -57,6 +62,7 @@ class Debugger : public mate::TrackableObject<Debugger>,
bool IsAttached(); bool IsAttached();
void Detach(); void Detach();
void SendCommand(mate::Arguments* args); void SendCommand(mate::Arguments* args);
void ClearPendingRequests();
content::WebContents* web_contents_; // Weak Reference. content::WebContents* web_contents_; // Weak Reference.
scoped_refptr<content::DevToolsAgentHost> agent_host_; scoped_refptr<content::DevToolsAgentHost> agent_host_;

View file

@ -3,7 +3,7 @@ const dirtyChai = require('dirty-chai')
const http = require('http') const http = require('http')
const path = require('path') const path = require('path')
const {closeWindow} = require('./window-helpers') const {closeWindow} = require('./window-helpers')
const BrowserWindow = require('electron').remote.BrowserWindow const {BrowserWindow} = require('electron').remote
const {expect} = chai const {expect} = chai
chai.use(dirtyChai) chai.use(dirtyChai)
@ -23,15 +23,16 @@ describe('debugger module', () => {
afterEach(() => closeWindow(w).then(() => { w = null })) afterEach(() => closeWindow(w).then(() => { w = null }))
describe('debugger.attach', () => { describe('debugger.attach', () => {
it('fails when devtools is already open', done => { it('succeeds when devtools is already open', done => {
w.webContents.on('did-finish-load', () => { w.webContents.on('did-finish-load', () => {
w.webContents.openDevTools() w.webContents.openDevTools()
try { try {
w.webContents.debugger.attach() w.webContents.debugger.attach()
} catch (err) { } catch (err) {
expect(w.webContents.debugger.isAttached()).to.be.true() done(`unexpected error : ${err}`)
done()
} }
expect(w.webContents.debugger.isAttached()).to.be.true()
done()
}) })
w.webContents.loadFile(path.join(fixtures, 'pages', 'a.html')) w.webContents.loadFile(path.join(fixtures, 'pages', 'a.html'))
}) })
@ -144,8 +145,7 @@ describe('debugger module', () => {
}) })
}) })
// TODO(alexeykuzmin): [Ch66] Times out. Fix it and enable back. it('handles valid unicode characters in message', (done) => {
xit('handles valid unicode characters in message', (done) => {
try { try {
w.webContents.debugger.attach() w.webContents.debugger.attach()
} catch (err) { } catch (err) {
@ -174,8 +174,7 @@ describe('debugger module', () => {
}) })
}) })
// TODO(alexeykuzmin): [Ch66] Times out. Fix it and enable back. it('does not crash for invalid unicode characters in message', (done) => {
xit('does not crash for invalid unicode characters in message', (done) => {
try { try {
w.webContents.debugger.attach() w.webContents.debugger.attach()
} catch (err) { } catch (err) {