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 gfx::Rect BoundsOnScreen(const HeadlessBrowserWindow* window, | |
73 const gfx::Size& screen_size) { | |
74 if (window->state() == "maximized" || window->state() == "fullscreen") | |
75 return gfx::Rect(screen_size); | |
76 return window->bounds(); | |
77 } | |
78 | |
79 std::unique_ptr<base::DictionaryValue> CreateBoundsDict( | |
80 const HeadlessBrowserWindow* window, | |
81 const gfx::Size& screen_size) { | |
82 auto bounds_object = base::MakeUnique<base::DictionaryValue>(); | |
83 gfx::Rect bounds = BoundsOnScreen(window, screen_size); | |
84 bounds_object->SetInteger("left", bounds.x()); | |
85 bounds_object->SetInteger("top", bounds.y()); | |
86 bounds_object->SetInteger("width", bounds.width()); | |
87 bounds_object->SetInteger("height", bounds.height()); | |
88 bounds_object->SetString("windowState", window->state()); | |
89 return bounds_object; | |
90 } | |
91 | |
71 #if BUILDFLAG(ENABLE_BASIC_PRINTING) | 92 #if BUILDFLAG(ENABLE_BASIC_PRINTING) |
72 void PDFCreated( | 93 void PDFCreated( |
73 const content::DevToolsManagerDelegate::CommandCallback& callback, | 94 const content::DevToolsManagerDelegate::CommandCallback& callback, |
74 int command_id, | 95 int command_id, |
75 printing::HeadlessPrintManager::PrintResult print_result, | 96 printing::HeadlessPrintManager::PrintResult print_result, |
76 const std::string& data) { | 97 const std::string& data) { |
77 std::unique_ptr<base::DictionaryValue> response; | 98 std::unique_ptr<base::DictionaryValue> response; |
78 if (print_result == printing::HeadlessPrintManager::PRINT_SUCCESS) { | 99 if (print_result == printing::HeadlessPrintManager::PRINT_SUCCESS) { |
79 response = CreateSuccessResponse( | 100 response = CreateSuccessResponse( |
80 command_id, | 101 command_id, |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
162 command_map_["Target.createTarget"] = base::Bind( | 183 command_map_["Target.createTarget"] = base::Bind( |
163 &HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this)); | 184 &HeadlessDevToolsManagerDelegate::CreateTarget, base::Unretained(this)); |
164 command_map_["Target.closeTarget"] = base::Bind( | 185 command_map_["Target.closeTarget"] = base::Bind( |
165 &HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this)); | 186 &HeadlessDevToolsManagerDelegate::CloseTarget, base::Unretained(this)); |
166 command_map_["Target.createBrowserContext"] = | 187 command_map_["Target.createBrowserContext"] = |
167 base::Bind(&HeadlessDevToolsManagerDelegate::CreateBrowserContext, | 188 base::Bind(&HeadlessDevToolsManagerDelegate::CreateBrowserContext, |
168 base::Unretained(this)); | 189 base::Unretained(this)); |
169 command_map_["Target.disposeBrowserContext"] = | 190 command_map_["Target.disposeBrowserContext"] = |
170 base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext, | 191 base::Bind(&HeadlessDevToolsManagerDelegate::DisposeBrowserContext, |
171 base::Unretained(this)); | 192 base::Unretained(this)); |
193 command_map_["Browser.getWindowForTarget"] = | |
194 base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowForTarget, | |
195 base::Unretained(this)); | |
196 command_map_["Browser.getWindowBounds"] = | |
197 base::Bind(&HeadlessDevToolsManagerDelegate::GetWindowBounds, | |
198 base::Unretained(this)); | |
199 command_map_["Browser.setWindowBounds"] = | |
200 base::Bind(&HeadlessDevToolsManagerDelegate::SetWindowBounds, | |
201 base::Unretained(this)); | |
172 | 202 |
173 async_command_map_["Page.printToPDF"] = base::Bind( | 203 async_command_map_["Page.printToPDF"] = base::Bind( |
174 &HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this)); | 204 &HeadlessDevToolsManagerDelegate::PrintToPDF, base::Unretained(this)); |
175 } | 205 } |
176 | 206 |
177 HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {} | 207 HeadlessDevToolsManagerDelegate::~HeadlessDevToolsManagerDelegate() {} |
178 | 208 |
179 base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand( | 209 base::DictionaryValue* HeadlessDevToolsManagerDelegate::HandleCommand( |
180 content::DevToolsAgentHost* agent_host, | 210 content::DevToolsAgentHost* agent_host, |
181 base::DictionaryValue* command) { | 211 base::DictionaryValue* command) { |
182 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 212 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
183 | 213 |
184 if (!browser_) | 214 if (!browser_) |
185 return nullptr; | 215 return nullptr; |
186 | 216 |
187 int id; | 217 int id; |
188 std::string method; | 218 std::string method; |
189 if (!command->GetInteger("id", &id) || !command->GetString("method", &method)) | 219 if (!command->GetInteger("id", &id) || !command->GetString("method", &method)) |
190 return nullptr; | 220 return nullptr; |
191 | 221 |
192 auto find_it = command_map_.find(method); | 222 auto find_it = command_map_.find(method); |
193 if (find_it == command_map_.end()) | 223 if (find_it == command_map_.end()) |
194 return nullptr; | 224 return nullptr; |
195 | 225 |
226 // 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.
| |
227 if (method.find("Browser.") == 0 && | |
228 agent_host->GetType() != content::DevToolsAgentHost::kTypeBrowser) | |
229 return nullptr; | |
230 | |
196 const base::DictionaryValue* params = nullptr; | 231 const base::DictionaryValue* params = nullptr; |
197 command->GetDictionary("params", ¶ms); | 232 command->GetDictionary("params", ¶ms); |
198 auto cmd_result = find_it->second.Run(id, params); | 233 auto cmd_result = find_it->second.Run(id, params); |
199 return cmd_result.release(); | 234 return cmd_result.release(); |
200 } | 235 } |
201 | 236 |
202 bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand( | 237 bool HeadlessDevToolsManagerDelegate::HandleAsyncCommand( |
203 content::DevToolsAgentHost* agent_host, | 238 content::DevToolsAgentHost* agent_host, |
204 base::DictionaryValue* command, | 239 base::DictionaryValue* command, |
205 const CommandCallback& callback) { | 240 const CommandCallback& callback) { |
(...skipping 13 matching lines...) Expand all Loading... | |
219 | 254 |
220 const base::DictionaryValue* params = nullptr; | 255 const base::DictionaryValue* params = nullptr; |
221 command->GetDictionary("params", ¶ms); | 256 command->GetDictionary("params", ¶ms); |
222 find_it->second.Run(agent_host, id, params, callback); | 257 find_it->second.Run(agent_host, id, params, callback); |
223 return true; | 258 return true; |
224 } | 259 } |
225 | 260 |
226 scoped_refptr<content::DevToolsAgentHost> | 261 scoped_refptr<content::DevToolsAgentHost> |
227 HeadlessDevToolsManagerDelegate::CreateNewTarget(const GURL& url) { | 262 HeadlessDevToolsManagerDelegate::CreateNewTarget(const GURL& url) { |
228 HeadlessBrowserContext* context = browser_->GetDefaultBrowserContext(); | 263 HeadlessBrowserContext* context = browser_->GetDefaultBrowserContext(); |
229 HeadlessWebContentsImpl* web_contents_impl = HeadlessWebContentsImpl::From( | 264 gfx::Rect bounds = |
230 context->CreateWebContentsBuilder() | 265 BoundsOnScreen(browser_->window(), browser_->options()->screen_size); |
231 .SetInitialURL(url) | 266 HeadlessWebContentsImpl* web_contents_impl = |
232 .SetWindowSize(browser_->options()->window_size) | 267 HeadlessWebContentsImpl::From(context->CreateWebContentsBuilder() |
233 .Build()); | 268 .SetInitialURL(url) |
269 .SetWindowSize(bounds.size()) | |
270 .Build()); | |
234 return content::DevToolsAgentHost::GetOrCreateFor( | 271 return content::DevToolsAgentHost::GetOrCreateFor( |
235 web_contents_impl->web_contents()); | 272 web_contents_impl->web_contents()); |
236 } | 273 } |
237 | 274 |
238 std::string HeadlessDevToolsManagerDelegate::GetDiscoveryPageHTML() { | 275 std::string HeadlessDevToolsManagerDelegate::GetDiscoveryPageHTML() { |
239 return ResourceBundle::GetSharedInstance() | 276 return ResourceBundle::GetSharedInstance() |
240 .GetRawDataResource(IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE) | 277 .GetRawDataResource(IDR_HEADLESS_LIB_DEVTOOLS_DISCOVERY_PAGE) |
241 .as_string(); | 278 .as_string(); |
242 } | 279 } |
243 | 280 |
(...skipping 28 matching lines...) Expand all Loading... | |
272 "Printing is not enabled")); | 309 "Printing is not enabled")); |
273 #endif | 310 #endif |
274 } | 311 } |
275 | 312 |
276 std::unique_ptr<base::DictionaryValue> | 313 std::unique_ptr<base::DictionaryValue> |
277 HeadlessDevToolsManagerDelegate::CreateTarget( | 314 HeadlessDevToolsManagerDelegate::CreateTarget( |
278 int command_id, | 315 int command_id, |
279 const base::DictionaryValue* params) { | 316 const base::DictionaryValue* params) { |
280 std::string url; | 317 std::string url; |
281 std::string browser_context_id; | 318 std::string browser_context_id; |
282 int width = browser_->options()->window_size.width(); | 319 gfx::Rect bounds = |
283 int height = browser_->options()->window_size.height(); | 320 BoundsOnScreen(browser_->window(), browser_->options()->screen_size); |
321 int width = bounds.width(); | |
322 int height = bounds.height(); | |
284 if (!params || !params->GetString("url", &url)) | 323 if (!params || !params->GetString("url", &url)) |
285 return CreateInvalidParamResponse(command_id, "url"); | 324 return CreateInvalidParamResponse(command_id, "url"); |
286 params->GetString("browserContextId", &browser_context_id); | 325 params->GetString("browserContextId", &browser_context_id); |
287 params->GetInteger("width", &width); | 326 params->GetInteger("width", &width); |
288 params->GetInteger("height", &height); | 327 params->GetInteger("height", &height); |
289 | 328 |
290 HeadlessBrowserContext* context = | 329 HeadlessBrowserContext* context = |
291 browser_->GetBrowserContextForId(browser_context_id); | 330 browser_->GetBrowserContextForId(browser_context_id); |
292 if (!browser_context_id.empty()) { | 331 if (!browser_context_id.empty()) { |
293 context = browser_->GetBrowserContextForId(browser_context_id); | 332 context = browser_->GetBrowserContextForId(browser_context_id); |
(...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
371 } | 410 } |
372 | 411 |
373 std::unique_ptr<base::Value> result( | 412 std::unique_ptr<base::Value> result( |
374 target::DisposeBrowserContextResult::Builder() | 413 target::DisposeBrowserContextResult::Builder() |
375 .SetSuccess(success) | 414 .SetSuccess(success) |
376 .Build() | 415 .Build() |
377 ->Serialize()); | 416 ->Serialize()); |
378 return CreateSuccessResponse(command_id, std::move(result)); | 417 return CreateSuccessResponse(command_id, std::move(result)); |
379 } | 418 } |
380 | 419 |
420 std::unique_ptr<base::DictionaryValue> | |
421 HeadlessDevToolsManagerDelegate::GetWindowForTarget( | |
422 int command_id, | |
423 const base::DictionaryValue* params) { | |
424 std::string target_id; | |
425 if (!params->GetString("targetId", &target_id)) | |
426 return CreateInvalidParamResponse(command_id, "targetId"); | |
427 | |
428 bool found_web_contents = false; | |
429 for (HeadlessBrowserContext* context : browser_->GetAllBrowserContexts()) { | |
430 if (context->GetWebContentsForDevToolsAgentHostId(target_id)) { | |
431 found_web_contents = true; | |
432 break; | |
433 } | |
434 } | |
435 if (!found_web_contents) { | |
436 return CreateErrorResponse(command_id, kErrorServerError, | |
437 "No web contents for the given target id"); | |
438 } | |
439 | |
440 auto result = base::MakeUnique<base::DictionaryValue>(); | |
441 result->SetInteger("windowId", 0); | |
Sami
2017/05/22 16:30:57
Let's make this a named constant -- and also non-z
| |
442 result->Set("bounds", CreateBoundsDict(browser_->window(), | |
443 browser_->options()->screen_size)); | |
444 return CreateSuccessResponse(command_id, std::move(result)); | |
445 } | |
446 | |
447 std::unique_ptr<base::DictionaryValue> | |
448 HeadlessDevToolsManagerDelegate::GetWindowBounds( | |
449 int command_id, | |
450 const base::DictionaryValue* params) { | |
451 int window_id; | |
452 if (!params->GetInteger("windowId", &window_id)) | |
453 return CreateInvalidParamResponse(command_id, "windowId"); | |
454 if (window_id != 0) { | |
455 return CreateErrorResponse(command_id, kErrorServerError, | |
456 "Browser window not found"); | |
457 } | |
458 | |
459 auto result = base::MakeUnique<base::DictionaryValue>(); | |
460 result->Set("bounds", CreateBoundsDict(browser_->window(), | |
461 browser_->options()->screen_size)); | |
462 return CreateSuccessResponse(command_id, std::move(result)); | |
463 } | |
464 | |
465 std::unique_ptr<base::DictionaryValue> | |
466 HeadlessDevToolsManagerDelegate::SetWindowBounds( | |
467 int command_id, | |
468 const base::DictionaryValue* params) { | |
469 int window_id; | |
470 if (!params->GetInteger("windowId", &window_id)) | |
471 return CreateInvalidParamResponse(command_id, "windowId"); | |
472 if (window_id != 0) { | |
473 return CreateErrorResponse(command_id, kErrorServerError, | |
474 "Browser window not found"); | |
475 } | |
476 | |
477 const base::Value* value = nullptr; | |
478 const base::DictionaryValue* bounds_dict = nullptr; | |
479 if (!params->Get("bounds", &value) || !value->GetAsDictionary(&bounds_dict)) | |
480 return CreateInvalidParamResponse(command_id, "bounds"); | |
481 | |
482 std::string window_state; | |
483 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.
| |
484 window_state = "normal"; | |
485 else if (window_state != "normal" && window_state != "minimized" && | |
486 window_state != "maximized" && window_state != "fullscreen") | |
487 return CreateInvalidParamResponse(command_id, "windowState"); | |
488 | |
489 // Compute updated bounds when window state is normal. | |
490 bool set_bounds = false; | |
491 gfx::Rect bounds = browser_->window()->bounds(); | |
492 int left, top, width, height; | |
493 if (bounds_dict->GetInteger("left", &left)) { | |
494 bounds.set_x(left); | |
495 set_bounds = true; | |
496 } | |
497 if (bounds_dict->GetInteger("top", &top)) { | |
498 bounds.set_y(top); | |
499 set_bounds = true; | |
500 } | |
501 if (bounds_dict->GetInteger("width", &width)) { | |
502 if (width < 0) | |
503 return CreateInvalidParamResponse(command_id, "width"); | |
504 bounds.set_width(width); | |
505 set_bounds = true; | |
506 } | |
507 if (bounds_dict->GetInteger("height", &height)) { | |
508 if (height < 0) | |
509 return CreateInvalidParamResponse(command_id, "height"); | |
510 bounds.set_height(height); | |
511 set_bounds = true; | |
512 } | |
513 | |
514 if (set_bounds && window_state != "normal") { | |
515 return CreateErrorResponse( | |
516 command_id, kErrorServerError, | |
517 "The 'minimized', 'maximized' and 'fullscreen' states cannot be " | |
518 "combined with 'left', 'top', 'width' or 'height'"); | |
519 } | |
520 | |
521 if (set_bounds && browser_->window()->state() != "normal") { | |
522 return CreateErrorResponse( | |
523 command_id, kErrorServerError, | |
524 "To resize minimized/maximized/fullscreen window, restore it to normal " | |
525 "state first."); | |
526 } | |
527 | |
528 browser_->window()->set_state(window_state); | |
529 | |
530 if (window_state == "minimized") | |
531 return CreateSuccessResponse(command_id, nullptr); | |
532 | |
533 if (window_state == "maximized" || window_state == "fullscreen") | |
534 bounds = gfx::Rect(browser_->options()->screen_size); | |
535 else | |
536 browser_->window()->set_bounds(bounds); | |
537 | |
538 for (HeadlessBrowserContext* context : browser_->GetAllBrowserContexts()) { | |
539 for (HeadlessWebContents* web_contents : context->GetAllWebContents()) { | |
Eric Seckler
2017/05/22 19:13:40
We should allow controlling the window size of ind
| |
540 auto* contents = HeadlessWebContentsImpl::From(web_contents); | |
541 if (contents) { | |
542 contents->web_contents()->GetRenderWidgetHostView()->SetSize( | |
543 bounds.size()); | |
544 } | |
545 } | |
546 } | |
547 | |
548 return CreateSuccessResponse(command_id, nullptr); | |
549 } | |
550 | |
381 } // namespace headless | 551 } // namespace headless |
OLD | NEW |