Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(228)

Unified Diff: headless/lib/browser/headless_devtools_manager_delegate.cc

Issue 2896763002: Implement window management devtools commands for headless. (Closed)
Patch Set: nit Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: headless/lib/browser/headless_devtools_manager_delegate.cc
diff --git a/headless/lib/browser/headless_devtools_manager_delegate.cc b/headless/lib/browser/headless_devtools_manager_delegate.cc
index 77c7e54c02fdf90565c9929d7ff8609ed891df1f..f66e26d0748ae7778b14e4acb590e22b7c5a67ad 100644
--- a/headless/lib/browser/headless_devtools_manager_delegate.cc
+++ b/headless/lib/browser/headless_devtools_manager_delegate.cc
@@ -10,6 +10,7 @@
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/devtools_agent_host.h"
#include "content/public/browser/devtools_frontend_host.h"
+#include "content/public/browser/render_widget_host_view.h"
#include "content/public/browser/web_contents.h"
#include "headless/grit/headless_lib_resources.h"
#include "headless/lib/browser/headless_browser_context_impl.h"
@@ -68,6 +69,26 @@ std::unique_ptr<base::DictionaryValue> CreateInvalidParamResponse(
base::StringPrintf("Missing or invalid '%s' parameter", param.c_str()));
}
+gfx::Rect BoundsOnScreen(const HeadlessBrowserWindow* window,
+ const gfx::Size& screen_size) {
+ if (window->state() == "maximized" || window->state() == "fullscreen")
+ return gfx::Rect(screen_size);
+ return window->bounds();
+}
+
+std::unique_ptr<base::DictionaryValue> CreateBoundsDict(
+ const HeadlessBrowserWindow* window,
+ const gfx::Size& screen_size) {
+ auto bounds_object = base::MakeUnique<base::DictionaryValue>();
+ gfx::Rect bounds = BoundsOnScreen(window, screen_size);
+ bounds_object->SetInteger("left", bounds.x());
+ bounds_object->SetInteger("top", bounds.y());
+ bounds_object->SetInteger("width", bounds.width());
+ bounds_object->SetInteger("height", bounds.height());
+ bounds_object->SetString("windowState", window->state());
+ return bounds_object;
+}
+
#if BUILDFLAG(ENABLE_BASIC_PRINTING)
void PDFCreated(
const content::DevToolsManagerDelegate::CommandCallback& callback,
@@ -169,6 +190,15 @@ HeadlessDevToolsManagerDelegate::HeadlessDevToolsManagerDelegate(
command_map_["Target.disposeBrowserContext"] =
base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext,
base::Unretained(this));
+ command_map_["Browser.getWindowForTarget"] =
+ base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowForTarget,
+ base::Unretained(this));
+ command_map_["Browser.getWindowBounds"] =
+ base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowBounds,
+ base::Unretained(this));
+ command_map_["Browser.setWindowBounds"] =
+ base::Bind(&HeadlessDevToolsManagerDelegate::SetWindowBounds,
+ base::Unretained(this));
async_command_map_["Page.printToPDF"] = base::Bind(
&HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this));
@@ -193,6 +223,11 @@ base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand(
if (find_it == command_map_.end())
return nullptr;
+ // Only handle Browser domain commands from Browser DevToolsAgentHost.
Eric Seckler 2017/05/22 19:13:40 nit: Handle Browser domain commands only from ...
jzfeng 2017/05/24 05:05:39 Done.
+ if (method.find("Browser.") == 0 &&
+ agent_host->GetType() != content::DevToolsAgentHost::kTypeBrowser)
+ return nullptr;
+
const base::DictionaryValue* params = nullptr;
command->GetDictionary("params", &params);
auto cmd_result = find_it->second.Run(id, params);
@@ -226,11 +261,13 @@ bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand(
scoped_refptr<content::DevToolsAgentHost>
HeadlessDevToolsManagerDelegate::CreateNewTarget(const GURL& url) {
HeadlessBrowserContext* context = browser_->GetDefaultBrowserContext();
- HeadlessWebContentsImpl* web_contents_impl = HeadlessWebContentsImpl::From(
- context->CreateWebContentsBuilder()
- .SetInitialURL(url)
- .SetWindowSize(browser_->options()->window_size)
- .Build());
+ gfx::Rect bounds =
+ BoundsOnScreen(browser_->window(), browser_->options()->screen_size);
+ HeadlessWebContentsImpl* web_contents_impl =
+ HeadlessWebContentsImpl::From(context->CreateWebContentsBuilder()
+ .SetInitialURL(url)
+ .SetWindowSize(bounds.size())
+ .Build());
return content::DevToolsAgentHost::GetOrCreateFor(
web_contents_impl->web_contents());
}
@@ -279,8 +316,10 @@ HeadlessDevToolsManagerDelegate::CreateTarget(
const base::DictionaryValue* params) {
std::string url;
std::string browser_context_id;
- int width = browser_->options()->window_size.width();
- int height = browser_->options()->window_size.height();
+ gfx::Rect bounds =
+ BoundsOnScreen(browser_->window(), browser_->options()->screen_size);
+ int width = bounds.width();
+ int height = bounds.height();
if (!params || !params->GetString("url", &url))
return CreateInvalidParamResponse(command_id, "url");
params->GetString("browserContextId", &browser_context_id);
@@ -378,4 +417,135 @@ HeadlessDevToolsManagerDelegate::DisposeBrowserContext(
return CreateSuccessResponse(command_id, std::move(result));
}
+std::unique_ptr<base::DictionaryValue>
+HeadlessDevToolsManagerDelegate::GetWindowForTarget(
+ int command_id,
+ const base::DictionaryValue* params) {
+ std::string target_id;
+ if (!params->GetString("targetId", &target_id))
+ return CreateInvalidParamResponse(command_id, "targetId");
+
+ bool found_web_contents = false;
+ for (HeadlessBrowserContext* context : browser_->GetAllBrowserContexts()) {
+ if (context->GetWebContentsForDevToolsAgentHostId(target_id)) {
+ found_web_contents = true;
+ break;
+ }
+ }
+ if (!found_web_contents) {
+ return CreateErrorResponse(command_id, kErrorServerError,
+ "No web contents for the given target id");
+ }
+
+ auto result = base::MakeUnique<base::DictionaryValue>();
+ result->SetInteger("windowId", 0);
Sami 2017/05/22 16:30:57 Let's make this a named constant -- and also non-z
+ result->Set("bounds", CreateBoundsDict(browser_->window(),
+ browser_->options()->screen_size));
+ return CreateSuccessResponse(command_id, std::move(result));
+}
+
+std::unique_ptr<base::DictionaryValue>
+HeadlessDevToolsManagerDelegate::GetWindowBounds(
+ int command_id,
+ const base::DictionaryValue* params) {
+ int window_id;
+ if (!params->GetInteger("windowId", &window_id))
+ return CreateInvalidParamResponse(command_id, "windowId");
+ if (window_id != 0) {
+ return CreateErrorResponse(command_id, kErrorServerError,
+ "Browser window not found");
+ }
+
+ auto result = base::MakeUnique<base::DictionaryValue>();
+ result->Set("bounds", CreateBoundsDict(browser_->window(),
+ browser_->options()->screen_size));
+ return CreateSuccessResponse(command_id, std::move(result));
+}
+
+std::unique_ptr<base::DictionaryValue>
+HeadlessDevToolsManagerDelegate::SetWindowBounds(
+ int command_id,
+ const base::DictionaryValue* params) {
+ int window_id;
+ if (!params->GetInteger("windowId", &window_id))
+ return CreateInvalidParamResponse(command_id, "windowId");
+ if (window_id != 0) {
+ return CreateErrorResponse(command_id, kErrorServerError,
+ "Browser window not found");
+ }
+
+ const base::Value* value = nullptr;
+ const base::DictionaryValue* bounds_dict = nullptr;
+ if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict))
+ return CreateInvalidParamResponse(command_id, "bounds");
+
+ std::string window_state;
+ if (!bounds_dict->GetString("windowState", &window_state))
Sami 2017/05/22 16:30:57 nit: Add {}s please
jzfeng 2017/05/24 05:05:39 Done.
+ window_state = "normal";
+ else if (window_state != "normal" && window_state != "minimized" &&
+ window_state != "maximized" && window_state != "fullscreen")
+ return CreateInvalidParamResponse(command_id, "windowState");
+
+ // Compute updated bounds when window state is normal.
+ bool set_bounds = false;
+ gfx::Rect bounds = browser_->window()->bounds();
+ int left, top, width, height;
+ if (bounds_dict->GetInteger("left", &left)) {
+ bounds.set_x(left);
+ set_bounds = true;
+ }
+ if (bounds_dict->GetInteger("top", &top)) {
+ bounds.set_y(top);
+ set_bounds = true;
+ }
+ if (bounds_dict->GetInteger("width", &width)) {
+ if (width < 0)
+ return CreateInvalidParamResponse(command_id, "width");
+ bounds.set_width(width);
+ set_bounds = true;
+ }
+ if (bounds_dict->GetInteger("height", &height)) {
+ if (height < 0)
+ return CreateInvalidParamResponse(command_id, "height");
+ bounds.set_height(height);
+ set_bounds = true;
+ }
+
+ if (set_bounds && window_state != "normal") {
+ return CreateErrorResponse(
+ command_id, kErrorServerError,
+ "The 'minimized', 'maximized' and 'fullscreen' states cannot be "
+ "combined with 'left', 'top', 'width' or 'height'");
+ }
+
+ if (set_bounds && browser_->window()->state() != "normal") {
+ return CreateErrorResponse(
+ command_id, kErrorServerError,
+ "To resize minimized/maximized/fullscreen window, restore it to normal "
+ "state first.");
+ }
+
+ browser_->window()->set_state(window_state);
+
+ if (window_state == "minimized")
+ return CreateSuccessResponse(command_id, nullptr);
+
+ if (window_state == "maximized" || window_state == "fullscreen")
+ bounds = gfx::Rect(browser_->options()->screen_size);
+ else
+ browser_->window()->set_bounds(bounds);
+
+ for (HeadlessBrowserContext* context : browser_->GetAllBrowserContexts()) {
+ for (HeadlessWebContents* web_contents : context->GetAllWebContents()) {
Eric Seckler 2017/05/22 19:13:40 We should allow controlling the window size of ind
+ auto* contents = HeadlessWebContentsImpl::From(web_contents);
+ if (contents) {
+ contents->web_contents()->GetRenderWidgetHostView()->SetSize(
+ bounds.size());
+ }
+ }
+ }
+
+ return CreateSuccessResponse(command_id, nullptr);
+}
+
} // namespace headless

Powered by Google App Engine
This is Rietveld 408576698