Chromium Code Reviews| 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", ¶ms); |
| 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 |