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 |