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 screencast_frame_sent_(0), |
| 102 screencast_frame_acked_(0), | 103 screencast_frame_acked_(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 screencast_frame_acked_ = screencast_frame_sent_; | |
| 306 capture_every_nth_frame_ = every_nth_frame ? *every_nth_frame : 1; | |
| 304 | 307 |
| 305 bool visible = !widget_host->is_hidden(); | 308 bool visible = !widget_host->is_hidden(); |
| 306 NotifyScreencastVisibility(visible); | 309 NotifyScreencastVisibility(visible); |
| 307 if (visible) { | 310 if (visible) { |
| 308 if (has_compositor_frame_metadata_) { | 311 if (has_compositor_frame_metadata_) { |
| 309 InnerSwapCompositorFrame(); | 312 InnerSwapCompositorFrame(); |
| 310 } else { | 313 } else { |
| 311 widget_host->Send( | 314 widget_host->Send( |
| 312 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); | 315 new ViewMsg_ForceRedraw(widget_host->GetRoutingID(), 0)); |
| 313 } | 316 } |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 365 } | 368 } |
| 366 | 369 |
| 367 void PageHandler::NotifyScreencastVisibility(bool visible) { | 370 void PageHandler::NotifyScreencastVisibility(bool visible) { |
| 368 if (visible) | 371 if (visible) |
| 369 capture_retry_count_ = kCaptureRetryLimit; | 372 capture_retry_count_ = kCaptureRetryLimit; |
| 370 client_->ScreencastVisibilityChanged( | 373 client_->ScreencastVisibilityChanged( |
| 371 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); | 374 ScreencastVisibilityChangedParams::Create()->set_visible(visible)); |
| 372 } | 375 } |
| 373 | 376 |
| 374 void PageHandler::InnerSwapCompositorFrame() { | 377 void PageHandler::InnerSwapCompositorFrame() { |
| 378 if (!host_ || !host_->GetView()) | |
| 379 return; | |
| 380 | |
| 375 if (screencast_frame_sent_ - screencast_frame_acked_ > | 381 if (screencast_frame_sent_ - screencast_frame_acked_ > |
| 376 kMaxScreencastFramesInFlight || processing_screencast_frame_) { | 382 kMaxScreencastFramesInFlight) { |
| 377 return; | 383 return; |
| 378 } | 384 } |
| 379 | 385 |
| 380 if (!host_ || !host_->GetView()) | 386 static int global_frame_counter = 0; |
|
dgozman
2015/11/20 22:53:23
With two different screencasts active it may happe
pfeldman
2015/11/20 23:18:25
Yep.
| |
| 387 if (++global_frame_counter % capture_every_nth_frame_) | |
| 381 return; | 388 return; |
| 382 | 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 = |
| (...skipping 14 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_, |
| 429 ++screencast_frame_sent_), | |
| 423 kN32_SkColorType); | 430 kN32_SkColorType); |
| 424 } | 431 } |
| 425 } | 432 } |
| 426 | 433 |
| 427 void PageHandler::ScreencastFrameCaptured( | 434 void PageHandler::ScreencastFrameCaptured( |
| 428 const cc::CompositorFrameMetadata& metadata, | 435 const cc::CompositorFrameMetadata& metadata, |
| 436 int frame_number, | |
| 429 const SkBitmap& bitmap, | 437 const SkBitmap& bitmap, |
| 430 ReadbackResponse response) { | 438 ReadbackResponse response) { |
| 431 if (response != READBACK_SUCCESS) { | 439 if (response != READBACK_SUCCESS) { |
| 432 processing_screencast_frame_ = false; | |
| 433 if (capture_retry_count_) { | 440 if (capture_retry_count_) { |
| 434 --capture_retry_count_; | 441 --capture_retry_count_; |
| 435 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 442 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( |
| 436 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, | 443 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, |
| 437 weak_factory_.GetWeakPtr()), | 444 weak_factory_.GetWeakPtr()), |
| 438 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); | 445 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); |
| 439 } | 446 } |
| 447 --screencast_frame_sent_; | |
|
dgozman
2015/11/20 22:53:23
This violates the assumption of increasing screenc
pfeldman
2015/11/20 23:18:25
Not really.
| |
| 440 return; | 448 return; |
| 441 } | 449 } |
| 442 base::PostTaskAndReplyWithResult( | 450 base::PostTaskAndReplyWithResult( |
| 443 base::WorkerPool::GetTaskRunner(true).get(), | 451 base::WorkerPool::GetTaskRunner(true).get(), |
| 444 FROM_HERE, | 452 FROM_HERE, |
| 445 base::Bind(&EncodeScreencastFrame, | 453 base::Bind(&EncodeScreencastFrame, |
| 446 bitmap, screencast_format_, screencast_quality_), | 454 bitmap, screencast_format_, screencast_quality_), |
| 447 base::Bind(&PageHandler::ScreencastFrameEncoded, | 455 base::Bind(&PageHandler::ScreencastFrameEncoded, |
| 448 weak_factory_.GetWeakPtr(), metadata, base::Time::Now())); | 456 weak_factory_.GetWeakPtr(), metadata, |
| 457 frame_number, base::Time::Now())); | |
| 449 } | 458 } |
| 450 | 459 |
| 451 void PageHandler::ScreencastFrameEncoded( | 460 void PageHandler::ScreencastFrameEncoded( |
| 452 const cc::CompositorFrameMetadata& metadata, | 461 const cc::CompositorFrameMetadata& metadata, |
| 462 int frame_number, | |
| 453 const base::Time& timestamp, | 463 const base::Time& timestamp, |
| 454 const std::string& data) { | 464 const std::string& data) { |
| 455 processing_screencast_frame_ = false; | |
| 456 | |
| 457 // Consider metadata empty in case it has no device scale factor. | 465 // Consider metadata empty in case it has no device scale factor. |
| 458 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) | 466 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { |
| 467 --screencast_frame_sent_; | |
| 459 return; | 468 return; |
| 469 } | |
| 460 | 470 |
| 461 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 471 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
| 462 host_->GetView()); | 472 host_->GetView()); |
| 463 if (!view) | 473 if (!view) { |
| 474 --screencast_frame_sent_; | |
| 464 return; | 475 return; |
| 476 } | |
| 465 | 477 |
| 466 gfx::SizeF screen_size_dip = | 478 gfx::SizeF screen_size_dip = |
| 467 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), | 479 gfx::ScaleSize(gfx::SizeF(view->GetPhysicalBackingSize()), |
| 468 1 / metadata.device_scale_factor); | 480 1 / metadata.device_scale_factor); |
| 469 scoped_refptr<ScreencastFrameMetadata> param_metadata = | 481 scoped_refptr<ScreencastFrameMetadata> param_metadata = |
| 470 ScreencastFrameMetadata::Create() | 482 ScreencastFrameMetadata::Create() |
| 471 ->set_page_scale_factor(metadata.page_scale_factor) | 483 ->set_page_scale_factor(metadata.page_scale_factor) |
| 472 ->set_offset_top(metadata.location_bar_content_translation.y()) | 484 ->set_offset_top(metadata.location_bar_content_translation.y()) |
| 473 ->set_device_width(screen_size_dip.width()) | 485 ->set_device_width(screen_size_dip.width()) |
| 474 ->set_device_height(screen_size_dip.height()) | 486 ->set_device_height(screen_size_dip.height()) |
| 475 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) | 487 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) |
| 476 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) | 488 ->set_scroll_offset_y(metadata.root_scroll_offset.y()) |
| 477 ->set_timestamp(timestamp.ToDoubleT()); | 489 ->set_timestamp(timestamp.ToDoubleT()); |
| 478 client_->ScreencastFrame(ScreencastFrameParams::Create() | 490 client_->ScreencastFrame(ScreencastFrameParams::Create() |
| 479 ->set_data(data) | 491 ->set_data(data) |
| 480 ->set_metadata(param_metadata) | 492 ->set_metadata(param_metadata) |
| 481 ->set_frame_number(++screencast_frame_sent_)); | 493 ->set_frame_number(frame_number)); |
| 482 } | 494 } |
| 483 | 495 |
| 484 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, | 496 void PageHandler::ScreenshotCaptured(DevToolsCommandId command_id, |
| 485 const unsigned char* png_data, | 497 const unsigned char* png_data, |
| 486 size_t png_size) { | 498 size_t png_size) { |
| 487 if (!png_data || !png_size) { | 499 if (!png_data || !png_size) { |
| 488 client_->SendError(command_id, | 500 client_->SendError(command_id, |
| 489 Response::InternalError("Unable to capture screenshot")); | 501 Response::InternalError("Unable to capture screenshot")); |
| 490 return; | 502 return; |
| 491 } | 503 } |
| 492 | 504 |
| 493 std::string base_64_data; | 505 std::string base_64_data; |
| 494 base::Base64Encode( | 506 base::Base64Encode( |
| 495 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), | 507 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), |
| 496 &base_64_data); | 508 &base_64_data); |
| 497 | 509 |
| 498 client_->SendCaptureScreenshotResponse(command_id, | 510 client_->SendCaptureScreenshotResponse(command_id, |
| 499 CaptureScreenshotResponse::Create()->set_data(base_64_data)); | 511 CaptureScreenshotResponse::Create()->set_data(base_64_data)); |
| 500 } | 512 } |
| 501 | 513 |
| 502 void PageHandler::OnColorPicked(int r, int g, int b, int a) { | 514 void PageHandler::OnColorPicked(int r, int g, int b, int a) { |
| 503 scoped_refptr<dom::RGBA> color = | 515 scoped_refptr<dom::RGBA> color = |
| 504 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); | 516 dom::RGBA::Create()->set_r(r)->set_g(g)->set_b(b)->set_a(a); |
| 505 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); | 517 client_->ColorPicked(ColorPickedParams::Create()->set_color(color)); |
| 506 } | 518 } |
| 507 | 519 |
| 508 } // namespace page | 520 } // namespace page |
| 509 } // namespace devtools | 521 } // namespace devtools |
| 510 } // namespace content | 522 } // namespace content |
| OLD | NEW |