Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 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 "content/browser/devtools/protocol/page_handler.h" | 5 #include "content/browser/devtools/protocol/page_handler.h" |
| 6 | 6 |
| 7 #include <string> | 7 #include <string> |
| 8 | 8 |
| 9 #include "base/base64.h" | 9 #include "base/base64.h" |
| 10 #include "base/bind.h" | 10 #include "base/bind.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 89 } // namespace | 89 } // namespace |
| 90 | 90 |
| 91 typedef DevToolsProtocolClient::Response Response; | 91 typedef DevToolsProtocolClient::Response Response; |
| 92 | 92 |
| 93 PageHandler::PageHandler() | 93 PageHandler::PageHandler() |
| 94 : enabled_(false), | 94 : enabled_(false), |
| 95 screencast_enabled_(false), | 95 screencast_enabled_(false), |
| 96 screencast_quality_(kDefaultScreenshotQuality), | 96 screencast_quality_(kDefaultScreenshotQuality), |
| 97 screencast_max_width_(-1), | 97 screencast_max_width_(-1), |
| 98 screencast_max_height_(-1), | 98 screencast_max_height_(-1), |
| 99 capture_every_nth_frame_(1), | |
| 99 capture_retry_count_(0), | 100 capture_retry_count_(0), |
| 100 has_compositor_frame_metadata_(false), | 101 has_compositor_frame_metadata_(false), |
| 101 screencast_frame_sent_(0), | 102 frame_counter_(0), |
| 102 screencast_frame_acked_(0), | 103 frames_in_flight_(0), |
| 103 processing_screencast_frame_(false), | |
| 104 color_picker_(new ColorPicker(base::Bind( | 104 color_picker_(new ColorPicker(base::Bind( |
| 105 &PageHandler::OnColorPicked, base::Unretained(this)))), | 105 &PageHandler::OnColorPicked, base::Unretained(this)))), |
| 106 host_(nullptr), | 106 host_(nullptr), |
| 107 weak_factory_(this) { | 107 weak_factory_(this) { |
| 108 } | 108 } |
| 109 | 109 |
| 110 PageHandler::~PageHandler() { | 110 PageHandler::~PageHandler() { |
| 111 } | 111 } |
| 112 | 112 |
| 113 void PageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { | 113 void PageHandler::SetRenderFrameHost(RenderFrameHostImpl* host) { |
| (...skipping 167 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 281 *result = true; | 281 *result = true; |
| 282 #else | 282 #else |
| 283 *result = false; | 283 *result = false; |
| 284 #endif // defined(OS_ANDROID) | 284 #endif // defined(OS_ANDROID) |
| 285 return Response::OK(); | 285 return Response::OK(); |
| 286 } | 286 } |
| 287 | 287 |
| 288 Response PageHandler::StartScreencast(const std::string* format, | 288 Response PageHandler::StartScreencast(const std::string* format, |
| 289 const int* quality, | 289 const int* quality, |
| 290 const int* max_width, | 290 const int* max_width, |
| 291 const int* max_height) { | 291 const int* max_height, |
| 292 const int* every_nth_frame) { | |
| 292 RenderWidgetHostImpl* widget_host = | 293 RenderWidgetHostImpl* widget_host = |
| 293 host_ ? host_->GetRenderWidgetHost() : nullptr; | 294 host_ ? host_->GetRenderWidgetHost() : nullptr; |
| 294 if (!widget_host) | 295 if (!widget_host) |
| 295 return Response::InternalError("Could not connect to view"); | 296 return Response::InternalError("Could not connect to view"); |
| 296 | 297 |
| 297 screencast_enabled_ = true; | 298 screencast_enabled_ = true; |
| 298 screencast_format_ = format ? *format : kPng; | 299 screencast_format_ = format ? *format : kPng; |
| 299 screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality; | 300 screencast_quality_ = quality ? *quality : kDefaultScreenshotQuality; |
| 300 if (screencast_quality_ < 0 || screencast_quality_ > 100) | 301 if (screencast_quality_ < 0 || screencast_quality_ > 100) |
| 301 screencast_quality_ = kDefaultScreenshotQuality; | 302 screencast_quality_ = kDefaultScreenshotQuality; |
| 302 screencast_max_width_ = max_width ? *max_width : -1; | 303 screencast_max_width_ = max_width ? *max_width : -1; |
| 303 screencast_max_height_ = max_height ? *max_height : -1; | 304 screencast_max_height_ = max_height ? *max_height : -1; |
| 305 frame_counter_ = 0; | |
| 306 frames_in_flight_ = 0; | |
|
dgozman
2015/11/21 02:03:23
Let's pass session id around.
| |
| 307 capture_every_nth_frame_ = every_nth_frame ? *every_nth_frame : 1; | |
| 304 | 308 |
| 305 bool visible = !widget_host->is_hidden(); | 309 bool visible = !widget_host->is_hidden(); |
| 306 NotifyScreencastVisibility(visible); | 310 NotifyScreencastVisibility(visible); |
| 307 if (visible) { | 311 if (visible) { |
| 308 if (has_compositor_frame_metadata_) { | 312 if (has_compositor_frame_metadata_) { |
| 309 InnerSwapCompositorFrame(); | 313 InnerSwapCompositorFrame(); |
| 310 } else { | 314 } else { |
| 311 widget_host->Send( | 315 widget_host->Send( |
| 312 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); | 316 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); |
| 313 } | 317 } |
| 314 } | 318 } |
| 315 return Response::FallThrough(); | 319 return Response::FallThrough(); |
| 316 } | 320 } |
| 317 | 321 |
| 318 Response PageHandler::StopScreencast() { | 322 Response PageHandler::StopScreencast() { |
| 319 screencast_enabled_ = false; | 323 screencast_enabled_ = false; |
| 320 return Response::FallThrough(); | 324 return Response::FallThrough(); |
| 321 } | 325 } |
| 322 | 326 |
| 323 Response PageHandler::ScreencastFrameAck(int frame_number) { | 327 Response PageHandler::ScreencastFrameAck() { |
| 324 screencast_frame_acked_ = frame_number; | 328 --frames_in_flight_; |
| 325 return Response::OK(); | 329 return Response::OK(); |
| 326 } | 330 } |
| 327 | 331 |
| 328 Response PageHandler::HandleJavaScriptDialog(bool accept, | 332 Response PageHandler::HandleJavaScriptDialog(bool accept, |
| 329 const std::string* prompt_text) { | 333 const std::string* prompt_text) { |
| 330 base::string16 prompt_override; | 334 base::string16 prompt_override; |
| 331 if (prompt_text) | 335 if (prompt_text) |
| 332 prompt_override = base::UTF8ToUTF16(*prompt_text); | 336 prompt_override = base::UTF8ToUTF16(*prompt_text); |
| 333 | 337 |
| 334 WebContentsImpl* web_contents = GetWebContents(); | 338 WebContentsImpl* web_contents = GetWebContents(); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 365 } | 369 } |
| 366 | 370 |
| 367 void PageHandler::NotifyScreencastVisibility(bool visible) { | 371 void PageHandler::NotifyScreencastVisibility(bool visible) { |
| 368 if (visible) | 372 if (visible) |
| 369 capture_retry_count_ = kCaptureRetryLimit; | 373 capture_retry_count_ = kCaptureRetryLimit; |
| 370 client_->ScreencastVisibilityChanged( | 374 client_->ScreencastVisibilityChanged( |
| 371 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); | 375 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); |
| 372 } | 376 } |
| 373 | 377 |
| 374 void PageHandler::InnerSwapCompositorFrame() { | 378 void PageHandler::InnerSwapCompositorFrame() { |
| 375 if (screencast_frame_sent_ - screencast_frame_acked_ > | |
| 376 kMaxScreencastFramesInFlight || processing_screencast_frame_) { | |
| 377 return; | |
| 378 } | |
| 379 | |
| 380 if (!host_ || !host_->GetView()) | 379 if (!host_ || !host_->GetView()) |
| 381 return; | 380 return; |
| 382 | 381 |
| 382 if (frames_in_flight_ > kMaxScreencastFramesInFlight) | |
| 383 return; | |
| 384 | |
| 385 if (++frame_counter_ % capture_every_nth_frame_) | |
| 386 return; | |
| 387 | |
| 388 frames_in_flight_++; | |
|
dgozman
2015/11/21 02:03:23
Move this into last |if| in this function.
| |
| 389 | |
| 383 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 390 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
| 384 host_->GetView()); | 391 host_->GetView()); |
| 385 // TODO(vkuzkokov): do not use previous frame metadata. | 392 // TODO(vkuzkokov): do not use previous frame metadata. |
| 386 cc::CompositorFrameMetadata& metadata = last_compositor_frame_metadata_; | 393 cc::CompositorFrameMetadata& metadata = last_compositor_frame_metadata_; |
| 387 | 394 |
| 388 gfx::SizeF viewport_size_dip = gfx::ScaleSize( | 395 gfx::SizeF viewport_size_dip = gfx::ScaleSize( |
| 389 metadata.scrollable_viewport_size, metadata.page_scale_factor); | 396 metadata.scrollable_viewport_size, metadata.page_scale_factor); |
| 390 gfx::SizeF screen_size_dip = | 397 gfx::SizeF screen_size_dip = |
| 391 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), | 398 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), |
| 392 1 / metadata.device_scale_factor); | 399 1 / metadata.device_scale_factor); |
| (...skipping 12 matching lines...) Expand all Loading... | |
| 405 scale = std::min(scale, max_height_dip / screen_size_dip.height()); | 412 scale = std::min(scale, max_height_dip / screen_size_dip.height()); |
| 406 } | 413 } |
| 407 | 414 |
| 408 if (scale <= 0) | 415 if (scale <= 0) |
| 409 scale = 0.1; | 416 scale = 0.1; |
| 410 | 417 |
| 411 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( | 418 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( |
| 412 gfx::ScaleSize(viewport_size_dip, scale))); | 419 gfx::ScaleSize(viewport_size_dip, scale))); |
| 413 | 420 |
| 414 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { | 421 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { |
| 415 processing_screencast_frame_ = true; | |
| 416 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); | 422 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); |
| 417 view->CopyFromCompositingSurface( | 423 view->CopyFromCompositingSurface( |
| 418 viewport_bounds_dip, | 424 viewport_bounds_dip, |
| 419 snapshot_size_dip, | 425 snapshot_size_dip, |
| 420 base::Bind(&PageHandler::ScreencastFrameCaptured, | 426 base::Bind(&PageHandler::ScreencastFrameCaptured, |
| 421 weak_factory_.GetWeakPtr(), | 427 weak_factory_.GetWeakPtr(), |
| 422 last_compositor_frame_metadata_), | 428 last_compositor_frame_metadata_), |
| 423 kN32_SkColorType); | 429 kN32_SkColorType); |
| 424 } | 430 } |
| 425 } | 431 } |
| 426 | 432 |
| 427 void PageHandler::ScreencastFrameCaptured( | 433 void PageHandler::ScreencastFrameCaptured( |
| 428 const cc::CompositorFrameMetadata& metadata, | 434 const cc::CompositorFrameMetadata& metadata, |
| 429 const SkBitmap& bitmap, | 435 const SkBitmap& bitmap, |
| 430 ReadbackResponse response) { | 436 ReadbackResponse response) { |
| 431 if (response != READBACK_SUCCESS) { | 437 if (response != READBACK_SUCCESS) { |
| 432 processing_screencast_frame_ = false; | |
| 433 if (capture_retry_count_) { | 438 if (capture_retry_count_) { |
| 434 --capture_retry_count_; | 439 --capture_retry_count_; |
| 435 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 440 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 436 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, | 441 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, |
| 437 weak_factory_.GetWeakPtr()), | 442 weak_factory_.GetWeakPtr()), |
| 438 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); | 443 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); |
| 439 } | 444 } |
| 445 --frames_in_flight_; | |
| 440 return; | 446 return; |
| 441 } | 447 } |
| 442 base::PostTaskAndReplyWithResult( | 448 base::PostTaskAndReplyWithResult( |
| 443 base::WorkerPool::GetTaskRunner(true).get(), | 449 base::WorkerPool::GetTaskRunner(true).get(), |
| 444 FROM_HERE, | 450 FROM_HERE, |
| 445 base::Bind(&EncodeScreencastFrame, | 451 base::Bind(&EncodeScreencastFrame, |
| 446 bitmap, screencast_format_, screencast_quality_), | 452 bitmap, screencast_format_, screencast_quality_), |
| 447 base::Bind(&PageHandler::ScreencastFrameEncoded, | 453 base::Bind(&PageHandler::ScreencastFrameEncoded, |
| 448 weak_factory_.GetWeakPtr(), metadata, base::Time::Now())); | 454 weak_factory_.GetWeakPtr(), metadata, base::Time::Now())); |
| 449 } | 455 } |
| 450 | 456 |
| 451 void PageHandler::ScreencastFrameEncoded( | 457 void PageHandler::ScreencastFrameEncoded( |
| 452 const cc::CompositorFrameMetadata& metadata, | 458 const cc::CompositorFrameMetadata& metadata, |
| 453 const base::Time& timestamp, | 459 const base::Time& timestamp, |
| 454 const std::string& data) { | 460 const std::string& data) { |
| 455 processing_screencast_frame_ = false; | |
| 456 | |
| 457 // Consider metadata empty in case it has no device scale factor. | 461 // Consider metadata empty in case it has no device scale factor. |
| 458 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) | 462 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { |
| 463 --frames_in_flight_; | |
| 459 return; | 464 return; |
| 465 } | |
| 460 | 466 |
| 461 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 467 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
| 462 host_->GetView()); | 468 host_->GetView()); |
| 463 if (!view) | 469 if (!view) { |
| 470 --frames_in_flight_; | |
| 464 return; | 471 return; |
| 472 } | |
| 465 | 473 |
| 466 gfx::SizeF screen_size_dip = | 474 gfx::SizeF screen_size_dip = |
| 467 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), | 475 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), |
| 468 1 / metadata.device_scale_factor); | 476 1 / metadata.device_scale_factor); |
| 469 scoped_refptr<ScreencastFrameMetadata> param_metadata = | 477 scoped_refptr<ScreencastFrameMetadata> param_metadata = |
| 470 ScreencastFrameMetadata::Create() | 478 ScreencastFrameMetadata::Create() |
| 471 ->set_page_scale_factor(metadata.page_scale_factor) | 479 ->set_page_scale_factor(metadata.page_scale_factor) |
| 472 ->set_offset_top(metadata.location_bar_content_translation.y()) | 480 ->set_offset_top(metadata.location_bar_content_translation.y()) |
| 473 ->set_device_width(screen_size_dip.width()) | 481 ->set_device_width(screen_size_dip.width()) |
| 474 ->set_device_height(screen_size_dip.height()) | 482 ->set_device_height(screen_size_dip.height()) |
| 475 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) | 483 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) |
| 476 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) | 484 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) |
| 477 ->set_timestamp(timestamp.ToDoubleT()); | 485 ->set_timestamp(timestamp.ToDoubleT()); |
| 478 client_->ScreencastFrame(ScreencastFrameParams::Create() | 486 client_->ScreencastFrame(ScreencastFrameParams::Create() |
| 479 ->set_data(data) | 487 ->set_data(data) |
| 480 ->set_metadata(param_metadata) | 488 ->set_metadata(param_metadata)); |
| 481 ->set_frame_number(++screencast_frame_sent_)); | |
| 482 } | 489 } |
| 483 | 490 |
| 484 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, | 491 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, |
| 485 const unsigned char* png_data, | 492 const unsigned char* png_data, |
| 486 size_t png_size) { | 493 size_t png_size) { |
| 487 if (!png_data || !png_size) { | 494 if (!png_data || !png_size) { |
| 488 client_->SendError(command_id, | 495 client_->SendError(command_id, |
| 489 Response::InternalError("Unable to capture screenshot")); | 496 Response::InternalError("Unable to capture screenshot")); |
| 490 return; | 497 return; |
| 491 } | 498 } |
| 492 | 499 |
| 493 std::string base_64_data; | 500 std::string base_64_data; |
| 494 base::Base64Encode( | 501 base::Base64Encode( |
| 495 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), | 502 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), |
| 496 &base_64_data); | 503 &base_64_data); |
| 497 | 504 |
| 498 client_->SendCaptureScreenshotResponse(command_id, | 505 client_->SendCaptureScreenshotResponse(command_id, |
| 499 CaptureScreenshotResponse::Create()->set_data(base_64_data)); | 506 CaptureScreenshotResponse::Create()->set_data(base_64_data)); |
| 500 } | 507 } |
| 501 | 508 |
| 502 void PageHandler::OnColorPicked(int r, int g, int b, int a) { | 509 void PageHandler::OnColorPicked(int r, int g, int b, int a) { |
| 503 scoped_refptr<dom::RGBA> color = | 510 scoped_refptr<dom::RGBA> color = |
| 504 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); | 511 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); |
| 505 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); | 512 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); |
| 506 } | 513 } |
| 507 | 514 |
| 508 } // namespace page | 515 } // namespace page |
| 509 } // namespace devtools | 516 } // namespace devtools |
| 510 } // namespace content | 517 } // namespace content |
| OLD | NEW |