OLD | NEW |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "headless/lib/browser/headless_devtools_manager_delegate.h" | 5 #include "headless/lib/browser/headless_devtools_manager_delegate.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "content/public/browser/browser_thread.h" | 10 #include "content/public/browser/browser_thread.h" |
11 #include "content/public/browser/devtools_agent_host.h" | 11 #include "content/public/browser/devtools_agent_host.h" |
12 #include "content/public/browser/devtools_frontend_host.h" | 12 #include "content/public/browser/devtools_frontend_host.h" |
| 13 #include "content/public/browser/render_widget_host_view.h" |
13 #include "content/public/browser/web_contents.h" | 14 #include "content/public/browser/web_contents.h" |
14 #include "headless/grit/headless_lib_resources.h" | 15 #include "headless/grit/headless_lib_resources.h" |
15 #include "headless/lib/browser/headless_browser_context_impl.h" | 16 #include "headless/lib/browser/headless_browser_context_impl.h" |
16 #include "headless/lib/browser/headless_browser_impl.h" | 17 #include "headless/lib/browser/headless_browser_impl.h" |
17 #include "headless/lib/browser/headless_web_contents_impl.h" | 18 #include "headless/lib/browser/headless_web_contents_impl.h" |
18 #include "headless/public/devtools/domains/target.h" | 19 #include "headless/public/devtools/domains/target.h" |
19 #include "printing/units.h" | 20 #include "printing/units.h" |
20 #include "ui/base/resource/resource_bundle.h" | 21 #include "ui/base/resource/resource_bundle.h" |
21 | 22 |
22 namespace headless { | 23 namespace headless { |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
61 } | 62 } |
62 | 63 |
63 std::unique_ptr<base::DictionaryValue> CreateInvalidParamResponse( | 64 std::unique_ptr<base::DictionaryValue> CreateInvalidParamResponse( |
64 int command_id, | 65 int command_id, |
65 const std::string& param) { | 66 const std::string& param) { |
66 return CreateErrorResponse( | 67 return CreateErrorResponse( |
67 command_id, kErrorInvalidParam, | 68 command_id, kErrorInvalidParam, |
68 base::StringPrintf("Missing or invalid '%s' parameter", param.c_str())); | 69 base::StringPrintf("Missing or invalid '%s' parameter", param.c_str())); |
69 } | 70 } |
70 | 71 |
| 72 std::unique_ptr<base::DictionaryValue> CreateBoundsDict( |
| 73 const HeadlessWebContentsImpl* web_contents) { |
| 74 auto bounds_object = base::MakeUnique<base::DictionaryValue>(); |
| 75 gfx::Rect bounds = |
| 76 web_contents->web_contents()->GetRenderWidgetHostView()->GetViewBounds(); |
| 77 bounds_object->SetInteger("left", bounds.x()); |
| 78 bounds_object->SetInteger("top", bounds.y()); |
| 79 bounds_object->SetInteger("width", bounds.width()); |
| 80 bounds_object->SetInteger("height", bounds.height()); |
| 81 bounds_object->SetString("windowState", web_contents->window_state()); |
| 82 return bounds_object; |
| 83 } |
| 84 |
71 #if BUILDFLAG(ENABLE_BASIC_PRINTING) | 85 #if BUILDFLAG(ENABLE_BASIC_PRINTING) |
72 void PDFCreated( | 86 void PDFCreated( |
73 const content::DevToolsManagerDelegate::CommandCallback& callback, | 87 const content::DevToolsManagerDelegate::CommandCallback& callback, |
74 int command_id, | 88 int command_id, |
75 printing::HeadlessPrintManager::PrintResult print_result, | 89 printing::HeadlessPrintManager::PrintResult print_result, |
76 const std::string& data) { | 90 const std::string& data) { |
77 std::unique_ptr<base::DictionaryValue> response; | 91 std::unique_ptr<base::DictionaryValue> response; |
78 if (print_result == printing::HeadlessPrintManager::PRINT_SUCCESS) { | 92 if (print_result == printing::HeadlessPrintManager::PRINT_SUCCESS) { |
79 response = CreateSuccessResponse( | 93 response = CreateSuccessResponse( |
80 command_id, | 94 command_id, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
162 command_map_["Target.createTarget"] = base::Bind( | 176 command_map_["Target.createTarget"] = base::Bind( |
163 &HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this)); | 177 &HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this)); |
164 command_map_["Target.closeTarget"] = base::Bind( | 178 command_map_["Target.closeTarget"] = base::Bind( |
165 &HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this)); | 179 &HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this)); |
166 command_map_["Target.createBrowserContext"] = | 180 command_map_["Target.createBrowserContext"] = |
167 base::Bind(&HeadlessDevToolsManagerDelegate::CreateBrowserContext, | 181 base::Bind(&HeadlessDevToolsManagerDelegate::CreateBrowserContext, |
168 base::Unretained(this)); | 182 base::Unretained(this)); |
169 command_map_["Target.disposeBrowserContext"] = | 183 command_map_["Target.disposeBrowserContext"] = |
170 base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext, | 184 base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext, |
171 base::Unretained(this)); | 185 base::Unretained(this)); |
| 186 command_map_["Browser.getWindowForTarget"] = |
| 187 base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowForTarget, |
| 188 base::Unretained(this)); |
| 189 command_map_["Browser.getWindowBounds"] = |
| 190 base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowBounds, |
| 191 base::Unretained(this)); |
| 192 command_map_["Browser.setWindowBounds"] = |
| 193 base::Bind(&HeadlessDevToolsManagerDelegate::SetWindowBounds, |
| 194 base::Unretained(this)); |
172 | 195 |
173 async_command_map_["Page.printToPDF"] = base::Bind( | 196 async_command_map_["Page.printToPDF"] = base::Bind( |
174 &HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this)); | 197 &HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this)); |
175 } | 198 } |
176 | 199 |
177 HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {} | 200 HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {} |
178 | 201 |
179 base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand( | 202 base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand( |
180 content::DevToolsAgentHost* agent_host, | 203 content::DevToolsAgentHost* agent_host, |
181 base::DictionaryValue* command) { | 204 base::DictionaryValue* command) { |
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 205 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
183 | 206 |
184 if (!browser_) | 207 if (!browser_) |
185 return nullptr; | 208 return nullptr; |
186 | 209 |
187 int id; | 210 int id; |
188 std::string method; | 211 std::string method; |
189 if (!command->GetInteger("id", &id) || !command->GetString("method", &method)) | 212 if (!command->GetInteger("id", &id) || !command->GetString("method", &method)) |
190 return nullptr; | 213 return nullptr; |
191 | 214 |
192 auto find_it = command_map_.find(method); | 215 auto find_it = command_map_.find(method); |
193 if (find_it == command_map_.end()) | 216 if (find_it == command_map_.end()) |
194 return nullptr; | 217 return nullptr; |
195 | 218 |
| 219 // Handle Browser domain commands only from Browser DevToolsAgentHost. |
| 220 if (method.find("Browser.") == 0 && |
| 221 agent_host->GetType() != content::DevToolsAgentHost::kTypeBrowser) |
| 222 return nullptr; |
| 223 |
196 const base::DictionaryValue* params = nullptr; | 224 const base::DictionaryValue* params = nullptr; |
197 command->GetDictionary("params", ¶ms); | 225 command->GetDictionary("params", ¶ms); |
198 auto cmd_result = find_it->second.Run(id, params); | 226 auto cmd_result = find_it->second.Run(id, params); |
199 return cmd_result.release(); | 227 return cmd_result.release(); |
200 } | 228 } |
201 | 229 |
202 bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand( | 230 bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand( |
203 content::DevToolsAgentHost* agent_host, | 231 content::DevToolsAgentHost* agent_host, |
204 base::DictionaryValue* command, | 232 base::DictionaryValue* command, |
205 const CommandCallback& callback) { | 233 const CommandCallback& callback) { |
(...skipping 165 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
371 } | 399 } |
372 | 400 |
373 std::unique_ptr<base::Value> result( | 401 std::unique_ptr<base::Value> result( |
374 target::DisposeBrowserContextResult::Builder() | 402 target::DisposeBrowserContextResult::Builder() |
375 .SetSuccess(success) | 403 .SetSuccess(success) |
376 .Build() | 404 .Build() |
377 ->Serialize()); | 405 ->Serialize()); |
378 return CreateSuccessResponse(command_id, std::move(result)); | 406 return CreateSuccessResponse(command_id, std::move(result)); |
379 } | 407 } |
380 | 408 |
| 409 std::unique_ptr<base::DictionaryValue> |
| 410 HeadlessDevToolsManagerDelegate::GetWindowForTarget( |
| 411 int command_id, |
| 412 const base::DictionaryValue* params) { |
| 413 std::string target_id; |
| 414 if (!params->GetString("targetId", &target_id)) |
| 415 return CreateInvalidParamResponse(command_id, "targetId"); |
| 416 |
| 417 HeadlessWebContentsImpl* web_contents = HeadlessWebContentsImpl::From( |
| 418 browser_->GetWebContentsForDevToolsAgentHostId(target_id)); |
| 419 if (!web_contents) { |
| 420 return CreateErrorResponse(command_id, kErrorServerError, |
| 421 "No web contents for the given target id"); |
| 422 } |
| 423 |
| 424 auto result = base::MakeUnique<base::DictionaryValue>(); |
| 425 result->SetInteger("windowId", web_contents->window_id()); |
| 426 result->Set("bounds", CreateBoundsDict(web_contents)); |
| 427 return CreateSuccessResponse(command_id, std::move(result)); |
| 428 } |
| 429 |
| 430 std::unique_ptr<base::DictionaryValue> |
| 431 HeadlessDevToolsManagerDelegate::GetWindowBounds( |
| 432 int command_id, |
| 433 const base::DictionaryValue* params) { |
| 434 int window_id; |
| 435 if (!params->GetInteger("windowId", &window_id)) |
| 436 return CreateInvalidParamResponse(command_id, "windowId"); |
| 437 HeadlessWebContentsImpl* web_contents = |
| 438 browser_->GetWebContentsForWindowId(window_id); |
| 439 if (!web_contents) { |
| 440 return CreateErrorResponse(command_id, kErrorServerError, |
| 441 "Browser window not found"); |
| 442 } |
| 443 |
| 444 auto result = base::MakeUnique<base::DictionaryValue>(); |
| 445 result->Set("bounds", CreateBoundsDict(web_contents)); |
| 446 return CreateSuccessResponse(command_id, std::move(result)); |
| 447 } |
| 448 |
| 449 std::unique_ptr<base::DictionaryValue> |
| 450 HeadlessDevToolsManagerDelegate::SetWindowBounds( |
| 451 int command_id, |
| 452 const base::DictionaryValue* params) { |
| 453 int window_id; |
| 454 if (!params->GetInteger("windowId", &window_id)) |
| 455 return CreateInvalidParamResponse(command_id, "windowId"); |
| 456 HeadlessWebContentsImpl* web_contents = |
| 457 browser_->GetWebContentsForWindowId(window_id); |
| 458 if (!web_contents) { |
| 459 return CreateErrorResponse(command_id, kErrorServerError, |
| 460 "Browser window not found"); |
| 461 } |
| 462 |
| 463 const base::Value* value = nullptr; |
| 464 const base::DictionaryValue* bounds_dict = nullptr; |
| 465 if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict)) |
| 466 return CreateInvalidParamResponse(command_id, "bounds"); |
| 467 |
| 468 std::string window_state; |
| 469 if (!bounds_dict->GetString("windowState", &window_state)) { |
| 470 window_state = "normal"; |
| 471 } else if (window_state != "normal" && window_state != "minimized" && |
| 472 window_state != "maximized" && window_state != "fullscreen") { |
| 473 return CreateInvalidParamResponse(command_id, "windowState"); |
| 474 } |
| 475 |
| 476 // Compute updated bounds when window state is normal. |
| 477 bool set_bounds = false; |
| 478 gfx::Rect bounds = |
| 479 web_contents->web_contents()->GetRenderWidgetHostView()->GetViewBounds(); |
| 480 int left, top, width, height; |
| 481 if (bounds_dict->GetInteger("left", &left)) { |
| 482 bounds.set_x(left); |
| 483 set_bounds = true; |
| 484 } |
| 485 if (bounds_dict->GetInteger("top", &top)) { |
| 486 bounds.set_y(top); |
| 487 set_bounds = true; |
| 488 } |
| 489 if (bounds_dict->GetInteger("width", &width)) { |
| 490 if (width < 0) |
| 491 return CreateInvalidParamResponse(command_id, "width"); |
| 492 bounds.set_width(width); |
| 493 set_bounds = true; |
| 494 } |
| 495 if (bounds_dict->GetInteger("height", &height)) { |
| 496 if (height < 0) |
| 497 return CreateInvalidParamResponse(command_id, "height"); |
| 498 bounds.set_height(height); |
| 499 set_bounds = true; |
| 500 } |
| 501 |
| 502 if (set_bounds && window_state != "normal") { |
| 503 return CreateErrorResponse( |
| 504 command_id, kErrorServerError, |
| 505 "The 'minimized', 'maximized' and 'fullscreen' states cannot be " |
| 506 "combined with 'left', 'top', 'width' or 'height'"); |
| 507 } |
| 508 |
| 509 if (set_bounds && web_contents->window_state() != "normal") { |
| 510 return CreateErrorResponse( |
| 511 command_id, kErrorServerError, |
| 512 "To resize minimized/maximized/fullscreen window, restore it to normal " |
| 513 "state first."); |
| 514 } |
| 515 |
| 516 web_contents->set_window_state(window_state); |
| 517 web_contents->web_contents()->GetRenderWidgetHostView()->SetBounds(bounds); |
| 518 return CreateSuccessResponse(command_id, nullptr); |
| 519 } |
| 520 |
381 } // namespace headless | 521 } // namespace headless |
OLD | NEW |