Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(67)

Side by Side Diff: content/browser/devtools/protocol/page_handler.cc

Issue 2592983002: [devtools] Support different encodings for Page.CaptureScreenshot. (Closed)
Patch Set: Return gfx::Image from ui snapshot methods instead. Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698