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/location.h" | 11 #include "base/location.h" |
12 #include "base/memory/ref_counted.h" | |
13 #include "base/memory/ref_counted_memory.h" | |
12 #include "base/single_thread_task_runner.h" | 14 #include "base/single_thread_task_runner.h" |
13 #include "base/strings/string16.h" | 15 #include "base/strings/string16.h" |
14 #include "base/strings/utf_string_conversions.h" | 16 #include "base/strings/utf_string_conversions.h" |
15 #include "base/task_scheduler/post_task.h" | 17 #include "base/task_scheduler/post_task.h" |
16 #include "base/threading/thread_task_runner_handle.h" | 18 #include "base/threading/thread_task_runner_handle.h" |
17 #include "content/browser/devtools/devtools_session.h" | 19 #include "content/browser/devtools/devtools_session.h" |
18 #include "content/browser/devtools/page_navigation_throttle.h" | 20 #include "content/browser/devtools/page_navigation_throttle.h" |
19 #include "content/browser/devtools/protocol/color_picker.h" | 21 #include "content/browser/devtools/protocol/color_picker.h" |
20 #include "content/browser/renderer_host/render_widget_host_impl.h" | 22 #include "content/browser/renderer_host/render_widget_host_impl.h" |
21 #include "content/browser/renderer_host/render_widget_host_view_base.h" | 23 #include "content/browser/renderer_host/render_widget_host_view_base.h" |
22 #include "content/browser/web_contents/web_contents_impl.h" | 24 #include "content/browser/web_contents/web_contents_impl.h" |
23 #include "content/browser/web_contents/web_contents_view.h" | 25 #include "content/browser/web_contents/web_contents_view.h" |
24 #include "content/common/view_messages.h" | 26 #include "content/common/view_messages.h" |
25 #include "content/public/browser/browser_thread.h" | 27 #include "content/public/browser/browser_thread.h" |
26 #include "content/public/browser/javascript_dialog_manager.h" | 28 #include "content/public/browser/javascript_dialog_manager.h" |
27 #include "content/public/browser/navigation_controller.h" | 29 #include "content/public/browser/navigation_controller.h" |
28 #include "content/public/browser/navigation_entry.h" | 30 #include "content/public/browser/navigation_entry.h" |
29 #include "content/public/browser/navigation_handle.h" | 31 #include "content/public/browser/navigation_handle.h" |
30 #include "content/public/browser/notification_service.h" | 32 #include "content/public/browser/notification_service.h" |
31 #include "content/public/browser/notification_types.h" | 33 #include "content/public/browser/notification_types.h" |
32 #include "content/public/browser/storage_partition.h" | 34 #include "content/public/browser/storage_partition.h" |
33 #include "content/public/browser/web_contents_delegate.h" | 35 #include "content/public/browser/web_contents_delegate.h" |
34 #include "content/public/common/referrer.h" | 36 #include "content/public/common/referrer.h" |
35 #include "third_party/skia/include/core/SkBitmap.h" | 37 #include "third_party/skia/include/core/SkBitmap.h" |
36 #include "ui/base/page_transition_types.h" | 38 #include "ui/base/page_transition_types.h" |
37 #include "ui/gfx/codec/jpeg_codec.h" | 39 #include "ui/gfx/codec/jpeg_codec.h" |
38 #include "ui/gfx/codec/png_codec.h" | 40 #include "ui/gfx/codec/png_codec.h" |
39 #include "ui/gfx/geometry/size_conversions.h" | 41 #include "ui/gfx/geometry/size_conversions.h" |
42 #include "ui/gfx/image/image.h" | |
43 #include "ui/gfx/image/image_util.h" | |
40 #include "ui/snapshot/snapshot.h" | 44 #include "ui/snapshot/snapshot.h" |
41 #include "url/gurl.h" | 45 #include "url/gurl.h" |
42 | 46 |
43 namespace content { | 47 namespace content { |
44 namespace protocol { | 48 namespace protocol { |
45 | 49 |
46 namespace { | 50 namespace { |
47 | 51 |
48 static const char kPng[] = "png"; | 52 static const char kPng[] = "png"; |
49 static const char kJpeg[] = "jpeg"; | 53 static const char kJpeg[] = "jpeg"; |
50 static int kDefaultScreenshotQuality = 80; | 54 static int kDefaultScreenshotQuality = 80; |
51 static int kFrameRetryDelayMs = 100; | 55 static int kFrameRetryDelayMs = 100; |
52 static int kCaptureRetryLimit = 2; | 56 static int kCaptureRetryLimit = 2; |
53 static int kMaxScreencastFramesInFlight = 2; | 57 static int kMaxScreencastFramesInFlight = 2; |
54 | 58 |
55 std::string EncodeScreencastFrame(const SkBitmap& bitmap, | 59 std::string EncodeImage(const gfx::Image& image, |
56 const std::string& format, | 60 const std::string& format, |
57 int quality) { | 61 int quality) { |
58 std::vector<unsigned char> data; | 62 DCHECK(!image.IsEmpty()); |
59 SkAutoLockPixels lock_image(bitmap); | 63 |
60 bool encoded; | 64 scoped_refptr<base::RefCountedMemory> data; |
61 if (format == kPng) { | 65 if (format == kPng) { |
62 encoded = gfx::PNGCodec::Encode( | 66 data = image.As1xPNGBytes(); |
63 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), | |
64 gfx::PNGCodec::FORMAT_SkBitmap, | |
65 gfx::Size(bitmap.width(), bitmap.height()), | |
66 bitmap.width() * bitmap.bytesPerPixel(), | |
67 false, std::vector<gfx::PNGCodec::Comment>(), &data); | |
68 } else if (format == kJpeg) { | 67 } else if (format == kJpeg) { |
69 encoded = gfx::JPEGCodec::Encode( | 68 scoped_refptr<base::RefCountedBytes> bytes(new base::RefCountedBytes()); |
70 reinterpret_cast<unsigned char*>(bitmap.getAddr32(0, 0)), | 69 if (gfx::JPEG1xEncodedDataFromImage(image, quality, &bytes->data())) |
71 gfx::JPEGCodec::FORMAT_SkBitmap, | 70 data = bytes; |
72 bitmap.width(), | |
73 bitmap.height(), | |
74 bitmap.width() * bitmap.bytesPerPixel(), | |
75 quality, &data); | |
76 } else { | |
77 encoded = false; | |
78 } | 71 } |
79 | 72 |
80 if (!encoded) | 73 if (!data || !data->front()) |
81 return std::string(); | 74 return std::string(); |
82 | 75 |
83 std::string base_64_data; | 76 std::string base_64_data; |
84 base::Base64Encode( | 77 base::Base64Encode( |
85 base::StringPiece(reinterpret_cast<char*>(&data[0]), data.size()), | 78 base::StringPiece(reinterpret_cast<const char*>(data->front()), |
79 data->size()), | |
86 &base_64_data); | 80 &base_64_data); |
87 | 81 |
88 return base_64_data; | 82 return base_64_data; |
89 } | 83 } |
90 | 84 |
91 } // namespace | 85 } // namespace |
92 | 86 |
93 PageHandler::PageHandler() | 87 PageHandler::PageHandler() |
94 : DevToolsDomainHandler(Page::Metainfo::domainName), | 88 : DevToolsDomainHandler(Page::Metainfo::domainName), |
95 enabled_(false), | 89 enabled_(false), |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
278 if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) { | 272 if (controller.GetEntryAtIndex(i)->GetUniqueID() == entry_id) { |
279 controller.GoToIndex(i); | 273 controller.GoToIndex(i); |
280 return Response::OK(); | 274 return Response::OK(); |
281 } | 275 } |
282 } | 276 } |
283 | 277 |
284 return Response::InvalidParams("No entry with passed id"); | 278 return Response::InvalidParams("No entry with passed id"); |
285 } | 279 } |
286 | 280 |
287 void PageHandler::CaptureScreenshot( | 281 void PageHandler::CaptureScreenshot( |
282 Maybe<std::string> format, | |
283 Maybe<int> quality, | |
288 std::unique_ptr<CaptureScreenshotCallback> callback) { | 284 std::unique_ptr<CaptureScreenshotCallback> callback) { |
289 if (!host_ || !host_->GetRenderWidgetHost()) { | 285 if (!host_ || !host_->GetRenderWidgetHost()) { |
290 callback->sendFailure(Response::InternalError()); | 286 callback->sendFailure(Response::InternalError()); |
291 return; | 287 return; |
292 } | 288 } |
293 | 289 |
290 std::string screenshot_format = format.fromMaybe(kPng); | |
291 int screenshot_quality = quality.fromMaybe(kDefaultScreenshotQuality); | |
292 | |
294 host_->GetRenderWidgetHost()->GetSnapshotFromBrowser( | 293 host_->GetRenderWidgetHost()->GetSnapshotFromBrowser( |
295 base::Bind(&PageHandler::ScreenshotCaptured, | 294 base::Bind(&PageHandler::ScreenshotCaptured, weak_factory_.GetWeakPtr(), |
296 weak_factory_.GetWeakPtr(), base::Passed(std::move(callback)))); | 295 base::Passed(std::move(callback)), screenshot_format, |
296 screenshot_quality)); | |
297 } | 297 } |
298 | 298 |
299 Response PageHandler::StartScreencast(Maybe<std::string> format, | 299 Response PageHandler::StartScreencast(Maybe<std::string> format, |
300 Maybe<int> quality, | 300 Maybe<int> quality, |
301 Maybe<int> max_width, | 301 Maybe<int> max_width, |
302 Maybe<int> max_height, | 302 Maybe<int> max_height, |
303 Maybe<int> every_nth_frame) { | 303 Maybe<int> every_nth_frame) { |
304 RenderWidgetHostImpl* widget_host = | 304 RenderWidgetHostImpl* widget_host = |
305 host_ ? host_->GetRenderWidgetHost() : nullptr; | 305 host_ ? host_->GetRenderWidgetHost() : nullptr; |
306 if (!widget_host) | 306 if (!widget_host) |
(...skipping 205 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
512 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, | 512 FROM_HERE, base::Bind(&PageHandler::InnerSwapCompositorFrame, |
513 weak_factory_.GetWeakPtr()), | 513 weak_factory_.GetWeakPtr()), |
514 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); | 514 base::TimeDelta::FromMilliseconds(kFrameRetryDelayMs)); |
515 } | 515 } |
516 --frames_in_flight_; | 516 --frames_in_flight_; |
517 return; | 517 return; |
518 } | 518 } |
519 base::PostTaskWithTraitsAndReplyWithResult( | 519 base::PostTaskWithTraitsAndReplyWithResult( |
520 FROM_HERE, base::TaskTraits().WithShutdownBehavior( | 520 FROM_HERE, base::TaskTraits().WithShutdownBehavior( |
521 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), | 521 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), |
522 base::Bind(&EncodeScreencastFrame, bitmap, screencast_format_, | 522 base::Bind(&EncodeImage, gfx::Image::CreateFrom1xBitmap(bitmap), |
523 screencast_quality_), | 523 screencast_format_, screencast_quality_), |
524 base::Bind(&PageHandler::ScreencastFrameEncoded, | 524 base::Bind(&PageHandler::ScreencastFrameEncoded, |
525 weak_factory_.GetWeakPtr(), base::Passed(&metadata), | 525 weak_factory_.GetWeakPtr(), base::Passed(&metadata), |
526 base::Time::Now())); | 526 base::Time::Now())); |
527 } | 527 } |
528 | 528 |
529 void PageHandler::ScreencastFrameEncoded(cc::CompositorFrameMetadata metadata, | 529 void PageHandler::ScreencastFrameEncoded(cc::CompositorFrameMetadata metadata, |
530 const base::Time& timestamp, | 530 const base::Time& timestamp, |
531 const std::string& data) { | 531 const std::string& data) { |
532 // Consider metadata empty in case it has no device scale factor. | 532 // Consider metadata empty in case it has no device scale factor. |
533 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { | 533 if (metadata.device_scale_factor == 0 || !host_ || data.empty()) { |
(...skipping 20 matching lines...) Expand all Loading... | |
554 .SetDeviceHeight(screen_size_dip.height()) | 554 .SetDeviceHeight(screen_size_dip.height()) |
555 .SetScrollOffsetX(metadata.root_scroll_offset.x()) | 555 .SetScrollOffsetX(metadata.root_scroll_offset.x()) |
556 .SetScrollOffsetY(metadata.root_scroll_offset.y()) | 556 .SetScrollOffsetY(metadata.root_scroll_offset.y()) |
557 .SetTimestamp(timestamp.ToDoubleT()) | 557 .SetTimestamp(timestamp.ToDoubleT()) |
558 .Build(); | 558 .Build(); |
559 frontend_->ScreencastFrame(data, std::move(param_metadata), session_id_); | 559 frontend_->ScreencastFrame(data, std::move(param_metadata), session_id_); |
560 } | 560 } |
561 | 561 |
562 void PageHandler::ScreenshotCaptured( | 562 void PageHandler::ScreenshotCaptured( |
563 std::unique_ptr<CaptureScreenshotCallback> callback, | 563 std::unique_ptr<CaptureScreenshotCallback> callback, |
564 const unsigned char* png_data, | 564 const std::string& format, |
565 size_t png_size) { | 565 int quality, |
566 if (!png_data || !png_size) { | 566 const gfx::Image& image) { |
567 if (image.IsEmpty()) { | |
567 callback->sendFailure(Response::Error("Unable to capture screenshot")); | 568 callback->sendFailure(Response::Error("Unable to capture screenshot")); |
568 return; | 569 return; |
569 } | 570 } |
570 | 571 |
571 std::string base_64_data; | 572 base::PostTaskWithTraitsAndReplyWithResult( |
pfeldman
2017/01/07 01:13:27
Why is this necessary? Weren't we doing it synchro
Eric Seckler
2017/01/09 14:52:04
Great, making it synchronous :) Previously, it was
| |
572 base::Base64Encode( | 573 FROM_HERE, base::TaskTraits().WithShutdownBehavior( |
573 base::StringPiece(reinterpret_cast<const char*>(png_data), png_size), | 574 base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN), |
574 &base_64_data); | 575 base::Bind(&EncodeImage, image, format, quality), |
575 callback->sendSuccess(base_64_data); | 576 base::Bind(&PageHandler::ScreenshotEncoded, weak_factory_.GetWeakPtr(), |
577 base::Passed(std::move(callback)))); | |
578 } | |
579 | |
580 void PageHandler::ScreenshotEncoded( | |
581 std::unique_ptr<CaptureScreenshotCallback> callback, | |
582 const std::string& data) { | |
583 callback->sendSuccess(data); | |
576 } | 584 } |
577 | 585 |
578 void PageHandler::OnColorPicked(int r, int g, int b, int a) { | 586 void PageHandler::OnColorPicked(int r, int g, int b, int a) { |
579 frontend_->ColorPicked( | 587 frontend_->ColorPicked( |
580 DOM::RGBA::Create().SetR(r).SetG(g).SetB(b).SetA(a).Build()); | 588 DOM::RGBA::Create().SetR(r).SetG(g).SetB(b).SetA(a).Build()); |
581 } | 589 } |
582 | 590 |
583 Response PageHandler::StopLoading() { | 591 Response PageHandler::StopLoading() { |
584 WebContentsImpl* web_contents = GetWebContents(); | 592 WebContentsImpl* web_contents = GetWebContents(); |
585 if (!web_contents) | 593 if (!web_contents) |
586 return Response::InternalError(); | 594 return Response::InternalError(); |
587 web_contents->Stop(); | 595 web_contents->Stop(); |
588 return Response::OK(); | 596 return Response::OK(); |
589 } | 597 } |
590 | 598 |
591 } // namespace protocol | 599 } // namespace protocol |
592 } // namespace content | 600 } // namespace content |
OLD | NEW |