Commit 29548781 authored by Alex Clarke's avatar Alex Clarke Committed by Commit Bot

Add Browser.deterministicMode for Puppeteer

This optionally sets initial_virtual_time and beginFrameControl.

Change-Id: I6a0d6237137dbda57578a92b5abb4f160049ac20
Reviewed-on: https://chromium-review.googlesource.com/937402
Commit-Queue: Alex Clarke <alexclarke@chromium.org>
Reviewed-by: default avatarDmitry Gozman <dgozman@chromium.org>
Reviewed-by: default avatarEric Seckler <eseckler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#540804}
parent 7c9c1f82
...@@ -8,9 +8,11 @@ ...@@ -8,9 +8,11 @@
#include <utility> #include <utility>
#include "base/base64.h" #include "base/base64.h"
#include "base/base_switches.h"
#include "base/command_line.h" #include "base/command_line.h"
#include "base/json/json_writer.h" #include "base/json/json_writer.h"
#include "build/build_config.h" #include "build/build_config.h"
#include "cc/base/switches.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h" #include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/switches.h" #include "components/viz/common/switches.h"
#include "content/public/browser/browser_thread.h" #include "content/public/browser/browser_thread.h"
...@@ -18,10 +20,12 @@ ...@@ -18,10 +20,12 @@
#include "content/public/browser/devtools_frontend_host.h" #include "content/public/browser/devtools_frontend_host.h"
#include "content/public/browser/render_widget_host_view.h" #include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h" #include "content/public/browser/web_contents.h"
#include "content/public/common/content_switches.h"
#include "headless/grit/headless_lib_resources.h" #include "headless/grit/headless_lib_resources.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_impl.h" #include "headless/lib/browser/headless_browser_impl.h"
#include "headless/lib/browser/headless_web_contents_impl.h" #include "headless/lib/browser/headless_web_contents_impl.h"
#include "headless/public/devtools/domains/headless_experimental.h"
#include "headless/public/devtools/domains/target.h" #include "headless/public/devtools/domains/target.h"
#include "printing/units.h" #include "printing/units.h"
#include "third_party/skia/include/core/SkBitmap.h" #include "third_party/skia/include/core/SkBitmap.h"
...@@ -285,43 +289,48 @@ HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate( ...@@ -285,43 +289,48 @@ HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate(
: browser_(std::move(browser)) { : browser_(std::move(browser)) {
// TODO(eseckler): Use third_party/inspector_protocol to generate harnesses // TODO(eseckler): Use third_party/inspector_protocol to generate harnesses
// for commands, rather than binding commands here manually. // for commands, rather than binding commands here manually.
command_map_["Target.createTarget"] = base::Bind( command_map_["Target.createTarget"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this));
command_map_["Target.closeTarget"] = base::Bind( command_map_["Target.closeTarget"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this));
command_map_["Target.createBrowserContext"] = command_map_["Target.createBrowserContext"] = base::BindRepeating(
base::Bind(&HeadlessDevToolsManagerDelegate::CreateBrowserContext, &HeadlessDevToolsManagerDelegate::CreateBrowserContext,
base::Unretained(this)); base::Unretained(this));
command_map_["Target.disposeBrowserContext"] = command_map_["Target.disposeBrowserContext"] = base::BindRepeating(
base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext, &HeadlessDevToolsManagerDelegate::DisposeBrowserContext,
base::Unretained(this)); base::Unretained(this));
command_map_["Browser.close"] = base::Bind( command_map_["Browser.close"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::Close, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::Close, base::Unretained(this));
command_map_["Browser.getWindowForTarget"] = command_map_["Browser.getWindowForTarget"] =
base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowForTarget, base::BindRepeating(&HeadlessDevToolsManagerDelegate::GetWindowForTarget,
base::Unretained(this)); base::Unretained(this));
command_map_["Browser.getWindowBounds"] = command_map_["Browser.getWindowBounds"] =
base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowBounds, base::BindRepeating(&HeadlessDevToolsManagerDelegate::GetWindowBounds,
base::Unretained(this)); base::Unretained(this));
command_map_["Browser.setWindowBounds"] = command_map_["Browser.setWindowBounds"] =
base::Bind(&HeadlessDevToolsManagerDelegate::SetWindowBounds, base::BindRepeating(&HeadlessDevToolsManagerDelegate::SetWindowBounds,
base::Unretained(this)); base::Unretained(this));
command_map_["HeadlessExperimental.enable"] = command_map_["HeadlessExperimental.enterDeterministicMode"] =
base::Bind(&HeadlessDevToolsManagerDelegate::EnableHeadlessExperimental, base::BindRepeating(
base::Unretained(this)); &HeadlessDevToolsManagerDelegate::EnterDeterministicMode,
command_map_["HeadlessExperimental.disable"] = base::Unretained(this));
base::Bind(&HeadlessDevToolsManagerDelegate::DisableHeadlessExperimental, command_map_["HeadlessExperimental.enable"] = base::BindRepeating(
base::Unretained(this)); &HeadlessDevToolsManagerDelegate::EnableHeadlessExperimental,
base::Unretained(this));
command_map_["HeadlessExperimental.disable"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::DisableHeadlessExperimental,
base::Unretained(this));
unhandled_command_map_["Network.emulateNetworkConditions"] = unhandled_command_map_["Network.emulateNetworkConditions"] =
base::Bind(&HeadlessDevToolsManagerDelegate::EmulateNetworkConditions, base::BindRepeating(
base::Unretained(this)); &HeadlessDevToolsManagerDelegate::EmulateNetworkConditions,
unhandled_command_map_["Network.disable"] = base::Bind( base::Unretained(this));
unhandled_command_map_["Network.disable"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::NetworkDisable, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::NetworkDisable, base::Unretained(this));
async_command_map_["Page.printToPDF"] = base::Bind( async_command_map_["Page.printToPDF"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this));
async_command_map_["HeadlessExperimental.beginFrame"] = base::Bind( async_command_map_["HeadlessExperimental.beginFrame"] = base::BindRepeating(
&HeadlessDevToolsManagerDelegate::BeginFrame, base::Unretained(this)); &HeadlessDevToolsManagerDelegate::BeginFrame, base::Unretained(this));
} }
...@@ -462,7 +471,7 @@ void HeadlessDevToolsManagerDelegate::PrintToPDF( ...@@ -462,7 +471,7 @@ void HeadlessDevToolsManagerDelegate::PrintToPDF(
} }
HeadlessPrintManager::FromWebContents(web_contents) HeadlessPrintManager::FromWebContents(web_contents)
->GetPDFContents(rfh, settings, ->GetPDFContents(rfh, settings,
base::Bind(&PDFCreated, callback, command_id)); base::BindRepeating(&PDFCreated, callback, command_id));
#else #else
callback.Run(CreateErrorResponse(command_id, kErrorServerError, callback.Run(CreateErrorResponse(command_id, kErrorServerError,
"Printing is not enabled")); "Printing is not enabled"));
...@@ -583,6 +592,25 @@ HeadlessDevToolsManagerDelegate::CreateBrowserContext( ...@@ -583,6 +592,25 @@ HeadlessDevToolsManagerDelegate::CreateBrowserContext(
return CreateSuccessResponse(command_id, std::move(result)); return CreateSuccessResponse(command_id, std::move(result));
} }
std::unique_ptr<base::DictionaryValue>
HeadlessDevToolsManagerDelegate::EnterDeterministicMode(
content::DevToolsAgentHost* agent_host,
content::DevToolsAgentHostClient* client,
int command_id,
const base::DictionaryValue* params) {
if (const base::Value* initial_date = params->FindKey("initialDate")) {
browser_->options()->initial_virtual_time =
base::Time::FromDoubleT(initial_date->GetDouble());
} else {
browser_->options()->initial_virtual_time = base::nullopt;
}
std::unique_ptr<base::Value> result(
headless_experimental::EnterDeterministicModeResult::Builder()
.Build()
->Serialize());
return CreateSuccessResponse(command_id, std::move(result));
}
std::unique_ptr<base::DictionaryValue> std::unique_ptr<base::DictionaryValue>
HeadlessDevToolsManagerDelegate::DisposeBrowserContext( HeadlessDevToolsManagerDelegate::DisposeBrowserContext(
content::DevToolsAgentHost* agent_host, content::DevToolsAgentHost* agent_host,
...@@ -963,10 +991,11 @@ void HeadlessDevToolsManagerDelegate::BeginFrame( ...@@ -963,10 +991,11 @@ void HeadlessDevToolsManagerDelegate::BeginFrame(
"single BeginFrame should be active at the same time."; "single BeginFrame should be active at the same time.";
} }
headless_contents->BeginFrame(frame_timeticks, deadline, interval, headless_contents->BeginFrame(
no_display_updates, capture_screenshot, frame_timeticks, deadline, interval, no_display_updates,
base::Bind(&OnBeginFrameFinished, command_id, capture_screenshot,
callback, encoding, quality)); base::BindRepeating(&OnBeginFrameFinished, command_id, callback, encoding,
quality));
} }
} // namespace headless } // namespace headless
...@@ -118,6 +118,12 @@ class HeadlessDevToolsManagerDelegate ...@@ -118,6 +118,12 @@ class HeadlessDevToolsManagerDelegate
int command_id, int command_id,
const base::DictionaryValue* params); const base::DictionaryValue* params);
std::unique_ptr<base::DictionaryValue> EnterDeterministicMode(
content::DevToolsAgentHost* agent_host,
content::DevToolsAgentHostClient* client,
int command_id,
const base::DictionaryValue* params);
void SetNetworkConditions( void SetNetworkConditions(
std::vector<HeadlessBrowserContext*> browser_contexts, std::vector<HeadlessBrowserContext*> browser_contexts,
HeadlessNetworkConditions conditions); HeadlessNetworkConditions conditions);
......
...@@ -5343,6 +5343,18 @@ ...@@ -5343,6 +5343,18 @@
} }
] ]
}, },
{
"name": "enterDeterministicMode",
"description": "Puts the browser into deterministic mode. Only effective for subsequently created web contents.\nOnly supported in headless mode. Once set there's no way of leaving deterministic mode.",
"parameters": [
{
"name": "initialDate",
"description": "Number of seconds since the Epoch",
"optional": true,
"type": "number"
}
]
},
{ {
"name": "disable", "name": "disable",
"description": "Disables headless events for the target." "description": "Disables headless events for the target."
...@@ -12424,4 +12436,4 @@ ...@@ -12424,4 +12436,4 @@
] ]
} }
] ]
} }
\ No newline at end of file
...@@ -2441,6 +2441,13 @@ experimental domain HeadlessExperimental ...@@ -2441,6 +2441,13 @@ experimental domain HeadlessExperimental
# Base64-encoded image data of the screenshot, if one was requested and successfully taken. # Base64-encoded image data of the screenshot, if one was requested and successfully taken.
optional string screenshotData optional string screenshotData
# Puts the browser into deterministic mode. Only effective for subsequently created web contents.
# Only supported in headless mode. Once set there's no way of leaving deterministic mode.
command enterDeterministicMode
parameters
# Number of seconds since the Epoch
optional number initialDate
# Disables headless events for the target. # Disables headless events for the target.
command disable command disable
......
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