| 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" |
| 11 #include "base/strings/string16.h" | 11 #include "base/strings/string16.h" |
| 12 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
| 13 #include "base/threading/worker_pool.h" |
| 13 #include "content/browser/devtools/protocol/color_picker.h" | 14 #include "content/browser/devtools/protocol/color_picker.h" |
| 14 #include "content/browser/devtools/protocol/usage_and_quota_query.h" | 15 #include "content/browser/devtools/protocol/usage_and_quota_query.h" |
| 15 #include "content/browser/geolocation/geolocation_service_context.h" | 16 #include "content/browser/geolocation/geolocation_service_context.h" |
| 16 #include "content/browser/renderer_host/render_view_host_impl.h" | 17 #include "content/browser/renderer_host/render_view_host_impl.h" |
| 17 #include "content/browser/renderer_host/render_widget_host_view_base.h" | 18 #include "content/browser/renderer_host/render_widget_host_view_base.h" |
| 18 #include "content/browser/web_contents/web_contents_impl.h" | 19 #include "content/browser/web_contents/web_contents_impl.h" |
| 19 #include "content/common/view_messages.h" | 20 #include "content/common/view_messages.h" |
| 20 #include "content/public/browser/browser_thread.h" | 21 #include "content/public/browser/browser_thread.h" |
| 21 #include "content/public/browser/javascript_dialog_manager.h" | 22 #include "content/public/browser/javascript_dialog_manager.h" |
| 22 #include "content/public/browser/navigation_controller.h" | 23 #include "content/public/browser/navigation_controller.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 39 namespace devtools { | 40 namespace devtools { |
| 40 namespace page { | 41 namespace page { |
| 41 | 42 |
| 42 namespace { | 43 namespace { |
| 43 | 44 |
| 44 static const char kPng[] = "png"; | 45 static const char kPng[] = "png"; |
| 45 static const char kJpeg[] = "jpeg"; | 46 static const char kJpeg[] = "jpeg"; |
| 46 static int kDefaultScreenshotQuality = 80; | 47 static int kDefaultScreenshotQuality = 80; |
| 47 static int kFrameRetryDelayMs = 100; | 48 static int kFrameRetryDelayMs = 100; |
| 48 static int kCaptureRetryLimit = 2; | 49 static int kCaptureRetryLimit = 2; |
| 49 static int kMaxScreencastFramesInFlight = 4; | 50 static int kMaxScreencastFramesInFlight = 2; |
| 50 | 51 |
| 51 void QueryUsageAndQuotaCompletedOnIOThread( | 52 void QueryUsageAndQuotaCompletedOnIOThread( |
| 52 const UsageAndQuotaQuery::Callback& callback, | 53 const UsageAndQuotaQuery::Callback& callback, |
| 53 scoped_refptr<QueryUsageAndQuotaResponse> response) { | 54 scoped_refptr<QueryUsageAndQuotaResponse> response) { |
| 54 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, | 55 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, |
| 55 base::Bind(callback, response)); | 56 base::Bind(callback, response)); |
| 56 } | 57 } |
| 57 | 58 |
| 58 void QueryUsageAndQuotaOnIOThread( | 59 void QueryUsageAndQuotaOnIOThread( |
| 59 scoped_refptr<storage::QuotaManager> quota_manager, | 60 scoped_refptr<storage::QuotaManager> quota_manager, |
| 60 const GURL& security_origin, | 61 const GURL& security_origin, |
| 61 const UsageAndQuotaQuery::Callback& callback) { | 62 const UsageAndQuotaQuery::Callback& callback) { |
| 62 new UsageAndQuotaQuery( | 63 new UsageAndQuotaQuery( |
| 63 quota_manager, | 64 quota_manager, |
| 64 security_origin, | 65 security_origin, |
| 65 base::Bind(&QueryUsageAndQuotaCompletedOnIOThread, | 66 base::Bind(&QueryUsageAndQuotaCompletedOnIOThread, |
| 66 callback)); | 67 callback)); |
| 67 } | 68 } |
| 68 | 69 |
| 70 std::string EncodeScreencastFrame(const SkBitmap& bitmap, |
| 71 const std::string& format, |
| 72 int quality) { |
| 73 std::vector<unsigned char> data; |
| 74 SkAutoLockPixels lock_image(bitmap); |
| 75 bool encoded; |
| 76 if (format == kPng) { |
| 77 encoded = gfx::PNGCodec::Encode( |
| 78 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), |
| 79 gfx::PNGCodec::FORMAT_SkBitmap, |
| 80 gfx::Size(bitmap.width(), bitmap.height()), |
| 81 bitmap.width() * bitmap.bytesPerPixel(), |
| 82 false, std::vector<gfx::PNGCodec::Comment>(), &data); |
| 83 } else if (format == kJpeg) { |
| 84 encoded = gfx::JPEGCodec::Encode( |
| 85 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), |
| 86 gfx::JPEGCodec::FORMAT_SkBitmap, |
| 87 bitmap.width(), |
| 88 bitmap.height(), |
| 89 bitmap.width() * bitmap.bytesPerPixel(), |
| 90 quality, &data); |
| 91 } else { |
| 92 encoded = false; |
| 93 } |
| 94 |
| 95 if (!encoded) |
| 96 return std::string(); |
| 97 |
| 98 std::string base_64_data; |
| 99 base::Base64Encode( |
| 100 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), |
| 101 &base_64_data); |
| 102 |
| 103 return base_64_data; |
| 104 } |
| 105 |
| 69 } // namespace | 106 } // namespace |
| 70 | 107 |
| 71 typedef DevToolsProtocolClient::Response Response; | 108 typedef DevToolsProtocolClient::Response Response; |
| 72 | 109 |
| 73 PageHandler::PageHandler() | 110 PageHandler::PageHandler() |
| 74 : enabled_(false), | 111 : enabled_(false), |
| 75 touch_emulation_enabled_(false), | 112 touch_emulation_enabled_(false), |
| 76 screencast_enabled_(false), | 113 screencast_enabled_(false), |
| 77 screencast_quality_(kDefaultScreenshotQuality), | 114 screencast_quality_(kDefaultScreenshotQuality), |
| 78 screencast_max_width_(-1), | 115 screencast_max_width_(-1), |
| (...skipping 391 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 470 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( | 507 gfx::Size snapshot_size_dip(gfx::ToRoundedSize( |
| 471 gfx::ScaleSize(viewport_size_dip, scale))); | 508 gfx::ScaleSize(viewport_size_dip, scale))); |
| 472 | 509 |
| 473 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { | 510 if (snapshot_size_dip.width() > 0 && snapshot_size_dip.height() > 0) { |
| 474 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); | 511 gfx::Rect viewport_bounds_dip(gfx::ToRoundedSize(viewport_size_dip)); |
| 475 view->CopyFromCompositingSurface( | 512 view->CopyFromCompositingSurface( |
| 476 viewport_bounds_dip, | 513 viewport_bounds_dip, |
| 477 snapshot_size_dip, | 514 snapshot_size_dip, |
| 478 base::Bind(&PageHandler::ScreencastFrameCaptured, | 515 base::Bind(&PageHandler::ScreencastFrameCaptured, |
| 479 weak_factory_.GetWeakPtr(), | 516 weak_factory_.GetWeakPtr(), |
| 480 screencast_format_, | |
| 481 screencast_quality_, | |
| 482 last_compositor_frame_metadata_), | 517 last_compositor_frame_metadata_), |
| 483 kN32_SkColorType); | 518 kN32_SkColorType); |
| 484 } | 519 } |
| 485 } | 520 } |
| 486 | 521 |
| 487 void PageHandler::ScreencastFrameCaptured( | 522 void PageHandler::ScreencastFrameCaptured( |
| 488 const std::string& format, | |
| 489 int quality, | |
| 490 const cc::CompositorFrameMetadata& metadata, | 523 const cc::CompositorFrameMetadata& metadata, |
| 491 const SkBitmap& bitmap, | 524 const SkBitmap& bitmap, |
| 492 ReadbackResponse response) { | 525 ReadbackResponse response) { |
| 493 if (response != READBACK_SUCCESS) { | 526 if (response != READBACK_SUCCESS) { |
| 494 if (capture_retry_count_) { | 527 if (capture_retry_count_) { |
| 495 --capture_retry_count_; | 528 --capture_retry_count_; |
| 496 base::MessageLoop::current()->PostDelayedTask( | 529 base::MessageLoop::current()->PostDelayedTask( |
| 497 FROM_HERE, | 530 FROM_HERE, |
| 498 base::Bind(&PageHandler::InnerSwapCompositorFrame, | 531 base::Bind(&PageHandler::InnerSwapCompositorFrame, |
| 499 weak_factory_.GetWeakPtr()), | 532 weak_factory_.GetWeakPtr()), |
| 500 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); | 533 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); |
| 501 } | 534 } |
| 502 return; | 535 return; |
| 503 } | 536 } |
| 537 base::PostTaskAndReplyWithResult( |
| 538 base::WorkerPool::GetTaskRunner(true).get(), |
| 539 FROM_HERE, |
| 540 base::Bind(&EncodeScreencastFrame, |
| 541 bitmap, screencast_format_, screencast_quality_), |
| 542 base::Bind(&PageHandler::ScreencastFrameEncoded, |
| 543 weak_factory_.GetWeakPtr(), metadata)); |
| 544 } |
| 504 | 545 |
| 505 std::vector<unsigned char> data; | 546 void PageHandler::ScreencastFrameEncoded( |
| 506 SkAutoLockPixels lock_image(bitmap); | 547 const cc::CompositorFrameMetadata& metadata, |
| 507 bool encoded; | 548 const std::string& data) { |
| 508 if (format == kPng) { | |
| 509 encoded = gfx::PNGCodec::Encode( | |
| 510 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), | |
| 511 gfx::PNGCodec::FORMAT_SkBitmap, | |
| 512 gfx::Size(bitmap.width(), bitmap.height()), | |
| 513 bitmap.width() * bitmap.bytesPerPixel(), | |
| 514 false, std::vector<gfx::PNGCodec::Comment>(), &data); | |
| 515 } else if (format == kJpeg) { | |
| 516 encoded = gfx::JPEGCodec::Encode( | |
| 517 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), | |
| 518 gfx::JPEGCodec::FORMAT_SkBitmap, | |
| 519 bitmap.width(), | |
| 520 bitmap.height(), | |
| 521 bitmap.width() * bitmap.bytesPerPixel(), | |
| 522 quality, &data); | |
| 523 } else { | |
| 524 encoded = false; | |
| 525 } | |
| 526 | |
| 527 if (!encoded) | |
| 528 return; | |
| 529 | |
| 530 std::string base_64_data; | |
| 531 base::Base64Encode( | |
| 532 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), | |
| 533 &base_64_data); | |
| 534 | |
| 535 // Consider metadata empty in case it has no device scale factor. | 549 // Consider metadata empty in case it has no device scale factor. |
| 536 if (metadata.device_scale_factor == 0 || !host_) | 550 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) |
| 537 return; | 551 return; |
| 538 | 552 |
| 539 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( | 553 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>( |
| 540 host_->GetView()); | 554 host_->GetView()); |
| 541 if (!view) | 555 if (!view) |
| 542 return; | 556 return; |
| 543 | 557 |
| 544 gfx::SizeF screen_size_dip = gfx::ScaleSize( | 558 gfx::SizeF screen_size_dip = gfx::ScaleSize( |
| 545 view->GetPhysicalBackingSize(), 1 / metadata.device_scale_factor); | 559 view->GetPhysicalBackingSize(), 1 / metadata.device_scale_factor); |
| 546 scoped_refptr<ScreencastFrameMetadata> param_metadata = | 560 scoped_refptr<ScreencastFrameMetadata> param_metadata = |
| 547 ScreencastFrameMetadata::Create() | 561 ScreencastFrameMetadata::Create() |
| 548 ->set_page_scale_factor(metadata.page_scale_factor) | 562 ->set_page_scale_factor(metadata.page_scale_factor) |
| 549 ->set_offset_top(metadata.location_bar_content_translation.y()) | 563 ->set_offset_top(metadata.location_bar_content_translation.y()) |
| 550 ->set_device_width(screen_size_dip.width()) | 564 ->set_device_width(screen_size_dip.width()) |
| 551 ->set_device_height(screen_size_dip.height()) | 565 ->set_device_height(screen_size_dip.height()) |
| 552 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) | 566 ->set_scroll_offset_x(metadata.root_scroll_offset.x()) |
| 553 ->set_scroll_offset_y(metadata.root_scroll_offset.y()); | 567 ->set_scroll_offset_y(metadata.root_scroll_offset.y()); |
| 554 client_->ScreencastFrame(ScreencastFrameParams::Create() | 568 client_->ScreencastFrame(ScreencastFrameParams::Create() |
| 555 ->set_data(base_64_data) | 569 ->set_data(data) |
| 556 ->set_metadata(param_metadata) | 570 ->set_metadata(param_metadata) |
| 557 ->set_frame_number(++screencast_frame_sent_)); | 571 ->set_frame_number(++screencast_frame_sent_)); |
| 558 } | 572 } |
| 559 | 573 |
| 560 void PageHandler::ScreenshotCaptured( | 574 void PageHandler::ScreenshotCaptured( |
| 561 scoped_refptr<DevToolsProtocol::Command> command, | 575 scoped_refptr<DevToolsProtocol::Command> command, |
| 562 const unsigned char* png_data, | 576 const unsigned char* png_data, |
| 563 size_t png_size) { | 577 size_t png_size) { |
| 564 if (!png_data || !png_size) { | 578 if (!png_data || !png_size) { |
| 565 client_->SendInternalErrorResponse(command, | 579 client_->SendInternalErrorResponse(command, |
| (...skipping 18 matching lines...) Expand all Loading... |
| 584 | 598 |
| 585 void PageHandler::QueryUsageAndQuotaCompleted( | 599 void PageHandler::QueryUsageAndQuotaCompleted( |
| 586 scoped_refptr<DevToolsProtocol::Command> command, | 600 scoped_refptr<DevToolsProtocol::Command> command, |
| 587 scoped_refptr<QueryUsageAndQuotaResponse> response_data) { | 601 scoped_refptr<QueryUsageAndQuotaResponse> response_data) { |
| 588 client_->SendQueryUsageAndQuotaResponse(command, response_data); | 602 client_->SendQueryUsageAndQuotaResponse(command, response_data); |
| 589 } | 603 } |
| 590 | 604 |
| 591 } // namespace page | 605 } // namespace page |
| 592 } // namespace devtools | 606 } // namespace devtools |
| 593 } // namespace content | 607 } // namespace content |
| OLD | NEW |