0

[DevTools] Add Target.createTarget() window state to headless shell

https://crrev.com/c/6167447 added window state support to Chrome's
Target.createTarget(). This CL adds it to headless shell/

Change-Id: I5604b6a99bfab7e1ce0412f31750c3c9e0b92b12
Cq-Include-Trybots: luci.chromium.try:mac12-tests,mac13-tests,mac14-tests
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6168459
Auto-Submit: Peter Kvitek <kvitekp@chromium.org>
Reviewed-by: Andrey Kosyakov <caseq@chromium.org>
Commit-Queue: Peter Kvitek <kvitekp@chromium.org>
Cr-Commit-Position: refs/heads/main@{#1406909}
This commit is contained in:
Peter Kvitek
2025-01-15 12:36:49 -08:00
committed by Chromium LUCI CQ
parent 09e49a1a48
commit 913cade5f8
7 changed files with 77 additions and 8 deletions

@ -371,7 +371,8 @@ std::unique_ptr<HeadlessWebContentsImpl> HeadlessWebContentsImpl::Create(
headless_web_contents->begin_frame_control_enabled_ =
builder->enable_begin_frame_control_ ||
headless_web_contents->browser()->options()->enable_begin_frame_control;
headless_web_contents->InitializeWindow(builder->window_bounds_);
headless_web_contents->InitializeWindow(builder->window_bounds_,
builder->window_state_);
if (!headless_web_contents->OpenURL(builder->initial_url_))
return nullptr;
return headless_web_contents;
@ -388,19 +389,20 @@ HeadlessWebContentsImpl::CreateForChildContents(
// Child contents have their own root window and inherit the BeginFrameControl
// setting.
child->begin_frame_control_enabled_ = parent->begin_frame_control_enabled_;
child->InitializeWindow(child->web_contents_->GetContainerBounds());
child->InitializeWindow(child->web_contents_->GetContainerBounds(),
/*window_state=*/"normal");
return child;
}
void HeadlessWebContentsImpl::InitializeWindow(
const gfx::Rect& initial_bounds) {
const gfx::Rect& bounds,
const std::string& window_state) {
static int window_id = 1;
window_id_ = window_id++;
window_state_ = "normal";
browser()->PlatformInitializeWebContents(this);
SetBounds(initial_bounds);
SetBounds(bounds);
SetWindowState(window_state);
}
void HeadlessWebContentsImpl::SetWindowState(const std::string& state) {
@ -409,7 +411,7 @@ void HeadlessWebContentsImpl::SetWindowState(const std::string& state) {
} else if (state == "minimized") {
web_contents_->WasHidden();
} else {
NOTREACHED();
NOTREACHED() << "Unknown window state: " << state;
}
window_state_ = state;
}
@ -545,6 +547,12 @@ HeadlessWebContents::Builder& HeadlessWebContents::Builder::SetWindowBounds(
return *this;
}
HeadlessWebContents::Builder& HeadlessWebContents::Builder::SetWindowState(
std::string_view window_state) {
window_state_ = window_state;
return *this;
}
HeadlessWebContents::Builder&
HeadlessWebContents::Builder::SetEnableBeginFrameControl(
bool enable_begin_frame_control) {

@ -92,7 +92,8 @@ class HEADLESS_EXPORT HeadlessWebContentsImpl : public HeadlessWebContents {
explicit HeadlessWebContentsImpl(
std::unique_ptr<content::WebContents> web_contents);
void InitializeWindow(const gfx::Rect& initial_bounds);
void InitializeWindow(const gfx::Rect& bounds,
const std::string& window_state);
uint64_t begin_frame_sequence_number_ =
viz::BeginFrameArgs::kStartingFrameNumber;

@ -4,6 +4,9 @@
#include "headless/lib/browser/protocol/target_handler.h"
#include <ranges>
#include <string_view>
#include "build/build_config.h"
#include "headless/lib/browser/headless_browser_context_impl.h"
#include "headless/lib/browser/headless_browser_impl.h"
@ -46,6 +49,20 @@ Response TargetHandler::CreateTarget(
}
#endif
if (window_state) {
static std::string_view kWindowStates[] = {
protocol::Target::WindowStateEnum::Normal,
protocol::Target::WindowStateEnum::Minimized,
protocol::Target::WindowStateEnum::Maximized,
protocol::Target::WindowStateEnum::Fullscreen,
};
if (std::ranges::find(kWindowStates, *window_state) ==
std::end(kWindowStates)) {
return protocol::Response::ServerError("Invalid target window state: " +
*window_state);
}
}
HeadlessBrowserContext* context;
if (context_id.has_value()) {
context = browser_->GetBrowserContextForId(context_id.value());
@ -73,6 +90,8 @@ Response TargetHandler::CreateTarget(
left.value_or(0), top.value_or(0),
width.value_or(browser_->options()->window_size.width()),
height.value_or(browser_->options()->window_size.height())))
.SetWindowState(
window_state.value_or(protocol::Target::WindowStateEnum::Normal))
.SetEnableBeginFrameControl(
enable_begin_frame_control.value_or(false))
.Build());

@ -5,6 +5,8 @@
#ifndef HEADLESS_PUBLIC_HEADLESS_WEB_CONTENTS_H_
#define HEADLESS_PUBLIC_HEADLESS_WEB_CONTENTS_H_
#include <string_view>
#include "base/memory/raw_ptr.h"
#include "base/process/kill.h"
#include "headless/public/headless_export.h"
@ -51,6 +53,9 @@ class HEADLESS_EXPORT HeadlessWebContents::Builder {
// options).
Builder& SetWindowBounds(const gfx::Rect& bounds);
// Specify the initial window state. Default is 'normal'.
Builder& SetWindowState(std::string_view window_state);
// Specify whether BeginFrames should be controlled via DevTools commands.
Builder& SetEnableBeginFrameControl(bool enable_begin_frame_control);
@ -70,6 +75,7 @@ class HEADLESS_EXPORT HeadlessWebContents::Builder {
GURL initial_url_ = GURL("about:blank");
gfx::Rect window_bounds_;
std::string window_state_ = "normal";
bool enable_begin_frame_control_ = false;
};

@ -0,0 +1,5 @@
Tests Target.createTarget() window state handling.
Expected: normal, actual: normal
Expected: maximized, actual: maximized
Expected: minimized, actual: minimized
Expected: fullscreen, actual: fullscreen

@ -0,0 +1,25 @@
// Copyright 2025 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
(async function(testRunner) {
const {session, dp} = await testRunner.startBlank(
`Tests Target.createTarget() window state handling.`);
async function tryCreateTarget(windowState) {
const {targetId} =
(await session.protocol.Target.createTarget(
{'url': 'about:blank', windowState, 'newWindow': true}))
.result;
const {bounds} = (await dp.Browser.getWindowForTarget({targetId})).result;
testRunner.log(`Expected: ${windowState}, actual: ${bounds.windowState}`);
}
await tryCreateTarget('normal');
await tryCreateTarget('maximized');
await tryCreateTarget('minimized');
await tryCreateTarget('fullscreen');
testRunner.completeTest();
})

@ -740,4 +740,9 @@ HEADLESS_PROTOCOL_TEST_WITH_COMMAND_LINE_EXTRAS(
"sanity/create-target-secondary-screen.js",
"--screen-info={label='#1'}{label='#2'}")
HEADLESS_PROTOCOL_TEST_WITH_COMMAND_LINE_EXTRAS(
CreateTargetWindowState,
"sanity/create-target-window-state.js",
"--screen-info={1600x1200}")
} // namespace headless