Index: headless/app/headless_shell.cc |
diff --git a/headless/app/headless_shell.cc b/headless/app/headless_shell.cc |
index 942fb9bbad7084131d5f94af51c8bdb28cc6e313..f103c3fc172f62af7e8ad796b48447b3b046de3a 100644 |
--- a/headless/app/headless_shell.cc |
+++ b/headless/app/headless_shell.cc |
@@ -29,6 +29,7 @@ |
#include "headless/public/headless_web_contents.h" |
#include "headless/public/util/deterministic_dispatcher.h" |
#include "headless/public/util/deterministic_http_protocol_handler.h" |
+#include "headless/public/util/navigation_request.h" |
#include "net/base/file_stream.h" |
#include "net/base/io_buffer.h" |
#include "net/base/ip_address.h" |
@@ -36,6 +37,8 @@ |
#include "ui/gfx/geometry/size.h" |
namespace headless { |
+class HeadlessShell; |
+ |
namespace { |
// Address where to listen to incoming DevTools connections. |
const char kDevToolsHttpServerAddress[] = "127.0.0.1"; |
@@ -54,11 +57,37 @@ bool ParseWindowSize(std::string window_size, gfx::Size* parsed_window_size) { |
} |
} // namespace |
+// Used in deterministic mode to make sure navigations and resource requests |
+// complete in the order requested. |
+class SimpleNavigationRequest : public NavigationRequest { |
Sami
2017/02/09 14:05:11
s/Simple/Shell/? Not sure what a complex navigatio
alex clarke (OOO till 29th)
2017/02/09 15:08:32
Done.
|
+ public: |
+ SimpleNavigationRequest(base::WeakPtr<HeadlessShell> headless_shell, |
+ const page::NavigationRequestedParams& params) |
+ : headless_shell_(headless_shell), |
+ navigation_id_(params.GetNavigationId()) {} |
+ |
+ ~SimpleNavigationRequest() override {} |
+ |
+ void StartProcessing(base::Closure done_callback) override; |
+ |
+ // Note the navigation likely isn't done when this is called, however we |
+ // expect it will have been committed and the initial resource load requested. |
+ static void ProcessNavigationResult( |
+ base::Closure done_callback, |
+ std::unique_ptr<page::ProcessNavigationResult>) { |
+ done_callback.Run(); |
+ } |
+ |
+ private: |
+ base::WeakPtr<HeadlessShell> headless_shell_; |
+ int navigation_id_; |
+}; |
+ |
// An application which implements a simple headless browser. |
class HeadlessShell : public HeadlessWebContents::Observer, |
emulation::ExperimentalObserver, |
inspector::ExperimentalObserver, |
- page::Observer { |
+ page::ExperimentalObserver { |
public: |
HeadlessShell() |
: browser_(nullptr), |
@@ -126,7 +155,7 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
if (!RemoteDebuggingEnabled()) { |
devtools_client_->GetEmulation()->GetExperimental()->RemoveObserver(this); |
devtools_client_->GetInspector()->GetExperimental()->RemoveObserver(this); |
- devtools_client_->GetPage()->RemoveObserver(this); |
+ devtools_client_->GetPage()->GetExperimental()->RemoveObserver(this); |
if (web_contents_->GetDevToolsTarget()) { |
web_contents_->GetDevToolsTarget()->DetachClient( |
devtools_client_.get()); |
@@ -142,7 +171,7 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
void DevToolsTargetReady() override { |
web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get()); |
devtools_client_->GetInspector()->GetExperimental()->AddObserver(this); |
- devtools_client_->GetPage()->AddObserver(this); |
+ devtools_client_->GetPage()->GetExperimental()->AddObserver(this); |
devtools_client_->GetPage()->Enable(); |
// Check if the document had already finished loading by the time we |
// attached. |
@@ -150,6 +179,14 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
devtools_client_->GetEmulation()->GetExperimental()->AddObserver(this); |
if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
+ switches::kDeterministicFetch)) { |
+ devtools_client_->GetPage()->GetExperimental()->SetControlNavigations( |
+ headless::page::SetControlNavigationsParams::Builder() |
+ .SetEnabled(true) |
+ .Build()); |
+ } |
+ |
+ if (base::CommandLine::ForCurrentProcess()->HasSwitch( |
switches::kVirtualTimeBudget)) { |
std::string budget_ms_ascii = |
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII( |
@@ -235,6 +272,13 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
OnPageReady(); |
} |
+ void OnNavigationRequested( |
+ const headless::page::NavigationRequestedParams& params) override { |
+ deterministic_dispatcher_->NavigationRequested( |
+ base::MakeUnique<SimpleNavigationRequest>(weak_factory_.GetWeakPtr(), |
+ params)); |
+ } |
+ |
void OnPageReady() { |
if (processed_page_ready_) |
return; |
@@ -386,6 +430,10 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
return command_line.HasSwitch(switches::kRemoteDebuggingPort); |
} |
+ HeadlessDevToolsClient* devtools_client() const { |
+ return devtools_client_.get(); |
+ } |
+ |
private: |
GURL url_; |
HeadlessBrowser* browser_; // Not owned. |
@@ -400,6 +448,23 @@ class HeadlessShell : public HeadlessWebContents::Observer, |
DISALLOW_COPY_AND_ASSIGN(HeadlessShell); |
}; |
+void SimpleNavigationRequest::StartProcessing(base::Closure done_callback) { |
+ if (!headless_shell_) |
+ return; |
+ |
+ // Allow the navigation to proceed. |
+ headless_shell_->devtools_client() |
+ ->GetPage() |
+ ->GetExperimental() |
+ ->ProcessNavigation( |
+ headless::page::ProcessNavigationParams::Builder() |
+ .SetNavigationId(navigation_id_) |
+ .SetResponse(headless::page::NavigationResponse::PROCEED) |
+ .Build(), |
+ base::Bind(&SimpleNavigationRequest::ProcessNavigationResult, |
+ done_callback)); |
+} |
+ |
bool ValidateCommandLine(const base::CommandLine& command_line) { |
if (!command_line.HasSwitch(switches::kRemoteDebuggingPort)) { |
if (command_line.GetArgs().size() <= 1) |