Commit 32fdf2ad authored by eseckler's avatar eseckler Committed by Commit bot

[headless] Expose DevToolsTarget via HeadlessBrowser + add tracing test.

BUG=546953

Review-Url: https://codereview.chromium.org/2840993003
Cr-Commit-Position: refs/heads/master@{#468229}
parent 321e6752
...@@ -13,11 +13,13 @@ ...@@ -13,11 +13,13 @@
#include "base/threading/thread_task_runner_handle.h" #include "base/threading/thread_task_runner_handle.h"
#include "content/public/app/content_main.h" #include "content/public/app/content_main.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h" #include "content/public/common/content_switches.h"
#include "headless/app/headless_shell_switches.h" #include "headless/app/headless_shell_switches.h"
#include "headless/lib/browser/headless_browser_context_impl.h" #include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_main_parts.h" #include "headless/lib/browser/headless_browser_main_parts.h"
#include "headless/lib/browser/headless_devtools_client_impl.h"
#include "headless/lib/browser/headless_web_contents_impl.h" #include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/lib/headless_content_main_delegate.h" #include "headless/lib/headless_content_main_delegate.h"
#include "net/http/http_util.h" #include "net/http/http_util.h"
...@@ -32,6 +34,10 @@ ...@@ -32,6 +34,10 @@
#include "sandbox/win/src/sandbox_types.h" #include "sandbox/win/src/sandbox_types.h"
#endif #endif
namespace content {
class DevToolsAgentHost;
}
namespace headless { namespace headless {
namespace { namespace {
...@@ -67,6 +73,7 @@ HeadlessBrowserImpl::HeadlessBrowserImpl( ...@@ -67,6 +73,7 @@ HeadlessBrowserImpl::HeadlessBrowserImpl(
options_(std::move(options)), options_(std::move(options)),
browser_main_parts_(nullptr), browser_main_parts_(nullptr),
default_browser_context_(nullptr), default_browser_context_(nullptr),
agent_host_(nullptr),
weak_ptr_factory_(this) {} weak_ptr_factory_(this) {}
HeadlessBrowserImpl::~HeadlessBrowserImpl() {} HeadlessBrowserImpl::~HeadlessBrowserImpl() {}
...@@ -133,6 +140,10 @@ void HeadlessBrowserImpl::set_browser_main_parts( ...@@ -133,6 +140,10 @@ void HeadlessBrowserImpl::set_browser_main_parts(
} }
void HeadlessBrowserImpl::RunOnStartCallback() { void HeadlessBrowserImpl::RunOnStartCallback() {
// We don't support the tethering domain on this agent host.
agent_host_ = content::DevToolsAgentHost::CreateForBrowser(
nullptr, content::DevToolsAgentHost::CreateServerSocketCallback());
PlatformCreateWindow(); PlatformCreateWindow();
on_start_callback_.Run(this); on_start_callback_.Run(this);
on_start_callback_ = base::Callback<void(HeadlessBrowser*)>(); on_start_callback_ = base::Callback<void(HeadlessBrowser*)>();
...@@ -200,6 +211,32 @@ HeadlessBrowserContext* HeadlessBrowserImpl::GetBrowserContextForId( ...@@ -200,6 +211,32 @@ HeadlessBrowserContext* HeadlessBrowserImpl::GetBrowserContextForId(
return find_it->second.get(); return find_it->second.get();
} }
HeadlessDevToolsTarget* HeadlessBrowserImpl::GetDevToolsTarget() {
return agent_host_ ? this : nullptr;
}
bool HeadlessBrowserImpl::AttachClient(HeadlessDevToolsClient* client) {
DCHECK(agent_host_);
return HeadlessDevToolsClientImpl::From(client)->AttachToHost(
agent_host_.get());
}
void HeadlessBrowserImpl::ForceAttachClient(HeadlessDevToolsClient* client) {
DCHECK(agent_host_);
HeadlessDevToolsClientImpl::From(client)->ForceAttachToHost(
agent_host_.get());
}
void HeadlessBrowserImpl::DetachClient(HeadlessDevToolsClient* client) {
DCHECK(agent_host_);
HeadlessDevToolsClientImpl::From(client)->DetachFromHost(agent_host_.get());
}
bool HeadlessBrowserImpl::IsAttached() {
DCHECK(agent_host_);
return agent_host_->IsAttached();
}
void RunChildProcessIfNeeded(int argc, const char** argv) { void RunChildProcessIfNeeded(int argc, const char** argv) {
base::CommandLine::Init(argc, argv); base::CommandLine::Init(argc, argv);
const base::CommandLine& command_line( const base::CommandLine& command_line(
......
...@@ -24,7 +24,8 @@ class HeadlessBrowserContextImpl; ...@@ -24,7 +24,8 @@ class HeadlessBrowserContextImpl;
class HeadlessBrowserMainParts; class HeadlessBrowserMainParts;
// Exported for tests. // Exported for tests.
class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser { class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser,
public HeadlessDevToolsTarget {
public: public:
HeadlessBrowserImpl( HeadlessBrowserImpl(
const base::Callback<void(HeadlessBrowser*)>& on_start_callback, const base::Callback<void(HeadlessBrowser*)>& on_start_callback,
...@@ -49,6 +50,13 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser { ...@@ -49,6 +50,13 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser {
void SetDefaultBrowserContext( void SetDefaultBrowserContext(
HeadlessBrowserContext* browser_context) override; HeadlessBrowserContext* browser_context) override;
HeadlessBrowserContext* GetDefaultBrowserContext() override; HeadlessBrowserContext* GetDefaultBrowserContext() override;
HeadlessDevToolsTarget* GetDevToolsTarget() override;
// HeadlessDevToolsTarget implementation:
bool AttachClient(HeadlessDevToolsClient* client) override;
void ForceAttachClient(HeadlessDevToolsClient* client) override;
void DetachClient(HeadlessDevToolsClient* client) override;
bool IsAttached() override;
void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts); void set_browser_main_parts(HeadlessBrowserMainParts* browser_main_parts);
HeadlessBrowserMainParts* browser_main_parts() const; HeadlessBrowserMainParts* browser_main_parts() const;
...@@ -82,6 +90,8 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser { ...@@ -82,6 +90,8 @@ class HEADLESS_EXPORT HeadlessBrowserImpl : public HeadlessBrowser {
browser_contexts_; browser_contexts_;
HeadlessBrowserContext* default_browser_context_; // Not owned. HeadlessBrowserContext* default_browser_context_; // Not owned.
scoped_refptr<content::DevToolsAgentHost> agent_host_;
base::WeakPtrFactory<HeadlessBrowserImpl> weak_ptr_factory_; base::WeakPtrFactory<HeadlessBrowserImpl> weak_ptr_factory_;
private: private:
......
...@@ -21,6 +21,7 @@ ...@@ -21,6 +21,7 @@
#include "headless/public/devtools/domains/inspector.h" #include "headless/public/devtools/domains/inspector.h"
#include "headless/public/devtools/domains/network.h" #include "headless/public/devtools/domains/network.h"
#include "headless/public/devtools/domains/page.h" #include "headless/public/devtools/domains/page.h"
#include "headless/public/devtools/domains/tracing.h"
#include "headless/public/headless_browser.h" #include "headless/public/headless_browser.h"
#include "headless/public/headless_devtools_client.h" #include "headless/public/headless_devtools_client.h"
#include "headless/public/headless_devtools_target.h" #include "headless/public/headless_devtools_target.h"
...@@ -829,4 +830,76 @@ IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithNetLog, WriteNetLog) { ...@@ -829,4 +830,76 @@ IN_PROC_BROWSER_TEST_F(HeadlessBrowserTestWithNetLog, WriteNetLog) {
EXPECT_GE(net_log_data.find("hello.html"), 0u); EXPECT_GE(net_log_data.find("hello.html"), 0u);
} }
namespace {
class TraceHelper : public headless::tracing::ExperimentalObserver {
public:
TraceHelper(HeadlessBrowserTest* browser_test, HeadlessDevToolsTarget* target)
: browser_test_(browser_test),
target_(target),
client_(HeadlessDevToolsClient::Create()),
tracing_data_(base::MakeUnique<base::ListValue>()) {
EXPECT_FALSE(target_->IsAttached());
target_->AttachClient(client_.get());
EXPECT_TRUE(target_->IsAttached());
client_->GetTracing()->GetExperimental()->AddObserver(this);
client_->GetTracing()->GetExperimental()->Start(
tracing::StartParams::Builder().Build(),
base::Bind(&TraceHelper::OnTracingStarted, base::Unretained(this)));
}
~TraceHelper() override {
target_->DetachClient(client_.get());
EXPECT_FALSE(target_->IsAttached());
}
std::unique_ptr<base::ListValue> TakeTracingData() {
return std::move(tracing_data_);
}
private:
void OnTracingStarted(std::unique_ptr<headless::tracing::StartResult>) {
// We don't need the callback from End, but the OnTracingComplete event.
client_->GetTracing()->GetExperimental()->End(
headless::tracing::EndParams::Builder().Build());
}
// headless::tracing::ExperimentalObserver implementation:
void OnDataCollected(
const headless::tracing::DataCollectedParams& params) override {
for (const auto& value : *params.GetValue()) {
tracing_data_->Append(value->CreateDeepCopy());
}
}
void OnTracingComplete(
const headless::tracing::TracingCompleteParams& params) override {
browser_test_->FinishAsynchronousTest();
}
HeadlessBrowserTest* browser_test_; // Not owned.
HeadlessDevToolsTarget* target_; // Not owned.
std::unique_ptr<HeadlessDevToolsClient> client_;
std::unique_ptr<base::ListValue> tracing_data_;
DISALLOW_COPY_AND_ASSIGN(TraceHelper);
};
} // namespace
IN_PROC_BROWSER_TEST_F(HeadlessBrowserTest, TraceUsingBrowserDevToolsTarget) {
HeadlessDevToolsTarget* target = browser()->GetDevToolsTarget();
EXPECT_NE(nullptr, target);
TraceHelper helper(this, target);
RunAsynchronousTest();
std::unique_ptr<base::ListValue> tracing_data = helper.TakeTracingData();
EXPECT_TRUE(tracing_data);
EXPECT_LT(0u, tracing_data->GetSize());
}
} // namespace headless } // namespace headless
...@@ -46,6 +46,12 @@ class HEADLESS_EXPORT HeadlessBrowser { ...@@ -46,6 +46,12 @@ class HEADLESS_EXPORT HeadlessBrowser {
virtual std::vector<HeadlessBrowserContext*> GetAllBrowserContexts() = 0; virtual std::vector<HeadlessBrowserContext*> GetAllBrowserContexts() = 0;
// Return a DevTools target corresponding to this browser. Note that this
// method only returns a valid target after browser has been initialized on
// the main thread. The target only supports the domains available on the
// browser endpoint excluding the Tethering domain.
virtual HeadlessDevToolsTarget* GetDevToolsTarget() = 0;
// Returns the HeadlessWebContents associated with the // Returns the HeadlessWebContents associated with the
// |devtools_agent_host_id| if any. Otherwise returns null. // |devtools_agent_host_id| if any. Otherwise returns null.
virtual HeadlessWebContents* GetWebContentsForDevToolsAgentHostId( virtual HeadlessWebContents* GetWebContentsForDevToolsAgentHostId(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment