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

Side by Side Diff: content/browser/devtools/renderer_overrides_handler.cc

Issue 481483002: DevTools: backend part of the color picker (behind experiment). (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Make bots happy. Created 6 years, 4 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 | Annotate | Revision Log
« no previous file with comments | « content/browser/devtools/renderer_overrides_handler.h ('k') | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 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/renderer_overrides_handler.h" 5 #include "content/browser/devtools/renderer_overrides_handler.h"
6 6
7 #include <map> 7 #include <map>
8 #include <string> 8 #include <string>
9 9
10 #include "base/barrier_closure.h" 10 #include "base/barrier_closure.h"
11 #include "base/base64.h" 11 #include "base/base64.h"
12 #include "base/bind.h" 12 #include "base/bind.h"
13 #include "base/bind_helpers.h" 13 #include "base/bind_helpers.h"
14 #include "base/files/file_path.h" 14 #include "base/files/file_path.h"
15 #include "base/strings/string16.h" 15 #include "base/strings/string16.h"
16 #include "base/thread_task_runner_handle.h" 16 #include "base/thread_task_runner_handle.h"
17 #include "base/values.h" 17 #include "base/values.h"
18 #include "content/browser/child_process_security_policy_impl.h" 18 #include "content/browser/child_process_security_policy_impl.h"
19 #include "content/browser/devtools/devtools_protocol_constants.h" 19 #include "content/browser/devtools/devtools_protocol_constants.h"
20 #include "content/browser/devtools/devtools_tracing_handler.h" 20 #include "content/browser/devtools/devtools_tracing_handler.h"
21 #include "content/browser/renderer_host/dip_util.h" 21 #include "content/browser/renderer_host/dip_util.h"
22 #include "content/browser/renderer_host/render_view_host_delegate.h" 22 #include "content/browser/renderer_host/render_view_host_delegate.h"
23 #include "content/browser/renderer_host/render_view_host_impl.h" 23 #include "content/browser/renderer_host/render_view_host_impl.h"
24 #include "content/browser/renderer_host/render_widget_host_view_base.h" 24 #include "content/browser/renderer_host/render_widget_host_view_base.h"
25 #include "content/browser/web_contents/web_contents_impl.h"
26 #include "content/common/cursors/webcursor.h"
25 #include "content/common/view_messages.h" 27 #include "content/common/view_messages.h"
26 #include "content/public/browser/browser_thread.h" 28 #include "content/public/browser/browser_thread.h"
27 #include "content/public/browser/content_browser_client.h" 29 #include "content/public/browser/content_browser_client.h"
28 #include "content/public/browser/devtools_agent_host.h" 30 #include "content/public/browser/devtools_agent_host.h"
29 #include "content/public/browser/javascript_dialog_manager.h" 31 #include "content/public/browser/javascript_dialog_manager.h"
30 #include "content/public/browser/navigation_controller.h" 32 #include "content/public/browser/navigation_controller.h"
31 #include "content/public/browser/navigation_entry.h" 33 #include "content/public/browser/navigation_entry.h"
32 #include "content/public/browser/render_process_host.h" 34 #include "content/public/browser/render_process_host.h"
33 #include "content/public/browser/render_view_host.h" 35 #include "content/public/browser/render_view_host.h"
34 #include "content/public/browser/render_widget_host_view.h" 36 #include "content/public/browser/render_widget_host_view.h"
35 #include "content/public/browser/storage_partition.h" 37 #include "content/public/browser/storage_partition.h"
36 #include "content/public/browser/web_contents.h" 38 #include "content/public/browser/web_contents.h"
37 #include "content/public/browser/web_contents_delegate.h" 39 #include "content/public/browser/web_contents_delegate.h"
38 #include "content/public/common/content_client.h" 40 #include "content/public/common/content_client.h"
39 #include "content/public/common/page_transition_types.h" 41 #include "content/public/common/page_transition_types.h"
40 #include "content/public/common/referrer.h" 42 #include "content/public/common/referrer.h"
41 #include "ipc/ipc_sender.h" 43 #include "ipc/ipc_sender.h"
42 #include "net/base/net_util.h" 44 #include "net/base/net_util.h"
45 #include "third_party/WebKit/public/platform/WebCursorInfo.h"
43 #include "third_party/WebKit/public/platform/WebScreenInfo.h" 46 #include "third_party/WebKit/public/platform/WebScreenInfo.h"
44 #include "third_party/WebKit/public/web/WebInputEvent.h" 47 #include "third_party/WebKit/public/web/WebInputEvent.h"
48 #include "third_party/skia/include/core/SkCanvas.h"
45 #include "ui/gfx/codec/jpeg_codec.h" 49 #include "ui/gfx/codec/jpeg_codec.h"
46 #include "ui/gfx/codec/png_codec.h" 50 #include "ui/gfx/codec/png_codec.h"
47 #include "ui/gfx/display.h" 51 #include "ui/gfx/display.h"
48 #include "ui/gfx/screen.h" 52 #include "ui/gfx/screen.h"
49 #include "ui/gfx/size_conversions.h" 53 #include "ui/gfx/size_conversions.h"
50 #include "ui/snapshot/snapshot.h" 54 #include "ui/snapshot/snapshot.h"
51 #include "url/gurl.h" 55 #include "url/gurl.h"
52 #include "webkit/browser/quota/quota_manager.h" 56 #include "webkit/browser/quota/quota_manager.h"
53 57
54 using blink::WebGestureEvent; 58 using blink::WebGestureEvent;
55 using blink::WebInputEvent; 59 using blink::WebInputEvent;
56 using blink::WebMouseEvent; 60 using blink::WebMouseEvent;
57 61
58 namespace content { 62 namespace content {
59 63
60 namespace { 64 namespace {
61 65
62 static const char kPng[] = "png"; 66 static const char kPng[] = "png";
63 static const char kJpeg[] = "jpeg"; 67 static const char kJpeg[] = "jpeg";
64 static int kDefaultScreenshotQuality = 80; 68 static int kDefaultScreenshotQuality = 80;
65 static int kFrameRateThresholdMs = 100; 69 static int kFrameRateThresholdMs = 100;
66 static int kCaptureRetryLimit = 2; 70 static int kCaptureRetryLimit = 2;
67 71
68 } // namespace 72 } // namespace
69 73
70 RendererOverridesHandler::RendererOverridesHandler() 74 RendererOverridesHandler::RendererOverridesHandler()
71 : has_last_compositor_frame_metadata_(false), 75 : has_last_compositor_frame_metadata_(false),
72 capture_retry_count_(0), 76 capture_retry_count_(0),
77 color_picker_enabled_(false),
73 weak_factory_(this) { 78 weak_factory_(this) {
74 RegisterCommandHandler( 79 RegisterCommandHandler(
75 devtools::DOM::setFileInputFiles::kName, 80 devtools::DOM::setFileInputFiles::kName,
76 base::Bind( 81 base::Bind(
77 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles, 82 &RendererOverridesHandler::GrantPermissionsForSetFileInputFiles,
78 base::Unretained(this))); 83 base::Unretained(this)));
79 RegisterCommandHandler( 84 RegisterCommandHandler(
80 devtools::Network::clearBrowserCache::kName, 85 devtools::Network::clearBrowserCache::kName,
81 base::Bind( 86 base::Bind(
82 &RendererOverridesHandler::ClearBrowserCache, 87 &RendererOverridesHandler::ClearBrowserCache,
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
134 devtools::Page::stopScreencast::kName, 139 devtools::Page::stopScreencast::kName,
135 base::Bind( 140 base::Bind(
136 &RendererOverridesHandler::PageStopScreencast, 141 &RendererOverridesHandler::PageStopScreencast,
137 base::Unretained(this))); 142 base::Unretained(this)));
138 RegisterCommandHandler( 143 RegisterCommandHandler(
139 devtools::Page::queryUsageAndQuota::kName, 144 devtools::Page::queryUsageAndQuota::kName,
140 base::Bind( 145 base::Bind(
141 &RendererOverridesHandler::PageQueryUsageAndQuota, 146 &RendererOverridesHandler::PageQueryUsageAndQuota,
142 base::Unretained(this))); 147 base::Unretained(this)));
143 RegisterCommandHandler( 148 RegisterCommandHandler(
149 devtools::Page::setColorPickerEnabled::kName,
150 base::Bind(
151 &RendererOverridesHandler::PageSetColorPickerEnabled,
152 base::Unretained(this)));
153 RegisterCommandHandler(
144 devtools::Input::emulateTouchFromMouseEvent::kName, 154 devtools::Input::emulateTouchFromMouseEvent::kName,
145 base::Bind( 155 base::Bind(
146 &RendererOverridesHandler::InputEmulateTouchFromMouseEvent, 156 &RendererOverridesHandler::InputEmulateTouchFromMouseEvent,
147 base::Unretained(this))); 157 base::Unretained(this)));
158 mouse_event_callback_ = base::Bind(
159 &RendererOverridesHandler::HandleMouseEvent,
160 base::Unretained(this));
148 } 161 }
149 162
150 RendererOverridesHandler::~RendererOverridesHandler() {} 163 RendererOverridesHandler::~RendererOverridesHandler() {}
151 164
152 void RendererOverridesHandler::OnClientDetached() { 165 void RendererOverridesHandler::OnClientDetached() {
153 if (screencast_command_ && host_) 166 if (screencast_command_ && host_)
154 host_->SetTouchEventEmulationEnabled(false, false); 167 host_->SetTouchEventEmulationEnabled(false, false);
155 screencast_command_ = NULL; 168 screencast_command_ = NULL;
169 SetColorPickerEnabled(false);
156 } 170 }
157 171
158 void RendererOverridesHandler::OnSwapCompositorFrame( 172 void RendererOverridesHandler::OnSwapCompositorFrame(
159 const cc::CompositorFrameMetadata& frame_metadata) { 173 const cc::CompositorFrameMetadata& frame_metadata) {
160 last_compositor_frame_metadata_ = frame_metadata; 174 last_compositor_frame_metadata_ = frame_metadata;
161 has_last_compositor_frame_metadata_ = true; 175 has_last_compositor_frame_metadata_ = true;
162 176
163 if (screencast_command_) 177 if (screencast_command_)
164 InnerSwapCompositorFrame(); 178 InnerSwapCompositorFrame();
179 if (color_picker_enabled_)
180 UpdateColorPickerFrame();
165 } 181 }
166 182
167 void RendererOverridesHandler::OnVisibilityChanged(bool visible) { 183 void RendererOverridesHandler::OnVisibilityChanged(bool visible) {
168 if (!screencast_command_) 184 if (!screencast_command_)
169 return; 185 return;
170 NotifyScreencastVisibility(visible); 186 NotifyScreencastVisibility(visible);
171 } 187 }
172 188
173 void RendererOverridesHandler::SetRenderViewHost( 189 void RendererOverridesHandler::SetRenderViewHost(
174 RenderViewHostImpl* host) { 190 RenderViewHostImpl* host) {
175 host_ = host; 191 host_ = host;
176 if (screencast_command_ && host) 192 if (screencast_command_ && host)
177 host->SetTouchEventEmulationEnabled(true, true); 193 host->SetTouchEventEmulationEnabled(true, true);
194 if (color_picker_enabled_)
195 host->AddMouseEventCallback(mouse_event_callback_);
178 } 196 }
179 197
180 void RendererOverridesHandler::ClearRenderViewHost() { 198 void RendererOverridesHandler::ClearRenderViewHost() {
199 if (host_)
200 host_->RemoveMouseEventCallback(mouse_event_callback_);
181 host_ = NULL; 201 host_ = NULL;
182 } 202 }
183 203
184 bool RendererOverridesHandler::OnSetTouchEventEmulationEnabled() { 204 bool RendererOverridesHandler::OnSetTouchEventEmulationEnabled() {
185 return screencast_command_.get() != NULL; 205 return screencast_command_.get() != NULL;
186 } 206 }
187 207
188 void RendererOverridesHandler::InnerSwapCompositorFrame() { 208 void RendererOverridesHandler::InnerSwapCompositorFrame() {
189 if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() < 209 if ((base::TimeTicks::Now() - last_frame_time_).InMilliseconds() <
190 kFrameRateThresholdMs) { 210 kFrameRateThresholdMs) {
(...skipping 649 matching lines...) Expand 10 before | Expand all | Expand 10 after
840 void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) { 860 void RendererOverridesHandler::NotifyScreencastVisibility(bool visible) {
841 if (visible) 861 if (visible)
842 capture_retry_count_ = kCaptureRetryLimit; 862 capture_retry_count_ = kCaptureRetryLimit;
843 base::DictionaryValue* params = new base::DictionaryValue(); 863 base::DictionaryValue* params = new base::DictionaryValue();
844 params->SetBoolean( 864 params->SetBoolean(
845 devtools::Page::screencastVisibilityChanged::kParamVisible, visible); 865 devtools::Page::screencastVisibilityChanged::kParamVisible, visible);
846 SendNotification( 866 SendNotification(
847 devtools::Page::screencastVisibilityChanged::kName, params); 867 devtools::Page::screencastVisibilityChanged::kName, params);
848 } 868 }
849 869
870 scoped_refptr<DevToolsProtocol::Response>
871 RendererOverridesHandler::PageSetColorPickerEnabled(
872 scoped_refptr<DevToolsProtocol::Command> command) {
873 base::DictionaryValue* params = command->params();
874 bool color_picker_enabled = false;
875 if (!params || !params->GetBoolean(
876 devtools::Page::setColorPickerEnabled::kParamEnabled,
877 &color_picker_enabled)) {
878 return command->InvalidParamResponse(
879 devtools::Page::setColorPickerEnabled::kParamEnabled);
880 }
881
882 SetColorPickerEnabled(color_picker_enabled);
883 return command->SuccessResponse(NULL);
884 }
885
886 void RendererOverridesHandler::SetColorPickerEnabled(bool enabled) {
887 if (color_picker_enabled_ == enabled)
888 return;
889
890 color_picker_enabled_ = enabled;
891
892 if (!host_)
893 return;
894
895 if (enabled) {
896 host_->AddMouseEventCallback(mouse_event_callback_);
897 UpdateColorPickerFrame();
898 } else {
899 host_->RemoveMouseEventCallback(mouse_event_callback_);
900 color_picker_frame_.reset();
901
902 WebCursor pointer_cursor;
903 WebCursor::CursorInfo cursor_info;
904 cursor_info.type = blink::WebCursorInfo::TypePointer;
905 pointer_cursor.InitFromCursorInfo(cursor_info);
906 host_->SetCursor(pointer_cursor);
907 }
908 }
909
910 void RendererOverridesHandler::UpdateColorPickerFrame() {
911 if (!host_)
912 return;
913 RenderWidgetHostViewBase* view =
914 static_cast<RenderWidgetHostViewBase*>(host_->GetView());
915 if (!view)
916 return;
917
918 gfx::Size size = view->GetViewBounds().size();
919 view->CopyFromCompositingSurface(
920 gfx::Rect(size), size,
921 base::Bind(&RendererOverridesHandler::ColorPickerFrameUpdated,
922 weak_factory_.GetWeakPtr()),
923 kN32_SkColorType);
924 }
925
926 void RendererOverridesHandler::ColorPickerFrameUpdated(
927 bool succeeded,
928 const SkBitmap& bitmap) {
929 if (succeeded)
930 color_picker_frame_ = bitmap;
931 }
932
933 bool RendererOverridesHandler::HandleMouseEvent(
934 const blink::WebMouseEvent& event) {
935 if (color_picker_frame_.drawsNothing())
936 return true;
937
938 if (event.button == blink::WebMouseEvent::ButtonLeft) {
939 color_picker_frame_.lockPixels();
940 SkColor color = color_picker_frame_.getColor(event.x, event.y);
941 color_picker_frame_.unlockPixels();
942 base::DictionaryValue* color_dict = new base::DictionaryValue();
943 color_dict->SetInteger("r", SkColorGetR(color));
944 color_dict->SetInteger("g", SkColorGetG(color));
945 color_dict->SetInteger("b", SkColorGetB(color));
946 color_dict->SetInteger("a", SkColorGetA(color));
947 base::DictionaryValue* response = new base::DictionaryValue();
948 response->Set(devtools::Page::colorPicked::kParamColor, color_dict);
949 SendNotification(devtools::Page::colorPicked::kName, response);
950 }
951
952 if (!host_)
953 return true;
954
955 // Due to platform limitations, we are using two different cursors
956 // depending on the platform. Mac and Win have large cursors with two circles
957 // for original spot and its magnified projection; Linux gets smaller (64 px)
958 // magnified projection only with centered hotspot.
959 // Mac Retina requires cursor to be > 120px in order to render smoothly.
960
961 #if defined(OS_LINUX)
962 const float kCursorSize = 63;
963 const float kDiameter = 63;
964 const float kHotspotOffset = 32;
965 const float kHotspotRadius = 0;
966 const float kPixelSize = 9;
967 #else
968 const float kCursorSize = 150;
969 const float kDiameter = 110;
970 const float kHotspotOffset = 25;
971 const float kHotspotRadius = 5;
972 const float kPixelSize = 10;
973 #endif
974
975 float device_scale_factor = gfx::Screen::GetNativeScreen()->
dgozman 2014/08/17 04:28:59 It's better to get this via |host_->GetScreenInfo|
pfeldman 2014/08/17 06:13:29 Done.
976 GetPrimaryDisplay().device_scale_factor();
977
978 skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRasterN32(
979 kCursorSize * device_scale_factor,
980 kCursorSize * device_scale_factor));
981 canvas->scale(device_scale_factor, device_scale_factor);
982
983 SkPaint paint;
984
985 // Paint original spot.
986 if (kHotspotRadius) {
987 paint.setStrokeWidth(2);
988 paint.setColor(SK_ColorDKGRAY);
989 paint.setStyle(SkPaint::kStroke_Style);
990 paint.setAntiAlias(true);
991 canvas->drawCircle(kHotspotOffset, kHotspotOffset, kHotspotRadius, paint);
992 canvas->drawLine(kHotspotOffset + kHotspotRadius - 1,
dgozman 2014/08/17 04:28:59 This is actually |kHotspotOffset + kHotspotRadius
pfeldman 2014/08/17 06:13:29 Done.
pfeldman 2014/08/17 06:13:29 Done.
993 kHotspotOffset + kHotspotRadius - 1,
994 kCursorSize / 2, kCursorSize / 2,
995 paint);
996 }
997
998 // Clip circle for magnified projection.
999 float padding = (kCursorSize - kDiameter) / 2;
1000 SkPath clip_path;
1001 clip_path.addOval(SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter));
1002 clip_path.close();
1003 canvas->clipPath(clip_path, SkRegion::kIntersect_Op, true);
1004
1005 // Project pixels.
1006 int pixel_count = kDiameter / kPixelSize;
1007 SkRect src_rect = SkRect::MakeXYWH(event.x - pixel_count / 2,
1008 event.y - pixel_count / 2,
1009 pixel_count, pixel_count);
1010 SkRect dst_rect = SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter);
1011 canvas->drawBitmapRectToRect(color_picker_frame_, &src_rect, dst_rect);
1012
1013 // Paint outline circle.
dgozman 2014/08/17 04:28:59 Wrong comment.
pfeldman 2014/08/17 06:13:29 Done.
1014 paint.setStrokeWidth(1);
1015 paint.setAntiAlias(false);
1016 paint.setColor(SK_ColorGRAY);
1017 for (int i = 0; i < pixel_count; ++i) {
1018 canvas->drawLine(padding + i * kPixelSize, padding,
1019 padding + i * kPixelSize, kCursorSize - padding, paint);
1020 canvas->drawLine(padding, padding + i * kPixelSize,
1021 kCursorSize - padding, padding + i * kPixelSize, paint);
1022 }
1023
1024 // Paint central pixel in red.
1025 SkRect pixel = SkRect::MakeXYWH((kCursorSize - kPixelSize) / 2,
1026 (kCursorSize - kPixelSize) / 2,
1027 kPixelSize, kPixelSize);
1028 paint.setColor(SK_ColorRED);
1029 canvas->drawRect(pixel, paint);
1030
1031 // Paint outline.
1032 paint.setStrokeWidth(2);
1033 paint.setColor(SK_ColorDKGRAY);
1034 paint.setAntiAlias(true);
1035 paint.setStyle(SkPaint::kStroke_Style);
1036 canvas->drawCircle(kCursorSize / 2, kCursorSize / 2, kDiameter / 2, paint);
1037
1038 SkBitmap result;
1039 result.allocN32Pixels(kCursorSize * device_scale_factor,
1040 kCursorSize * device_scale_factor);
1041 canvas->readPixels(&result, 0, 0);
1042
1043 WebCursor cursor;
1044 WebCursor::CursorInfo cursor_info;
1045 cursor_info.type = blink::WebCursorInfo::TypeCustom;
1046 cursor_info.image_scale_factor = device_scale_factor;
1047 cursor_info.custom_image = result;
1048 cursor_info.hotspot =
1049 gfx::Point(kHotspotOffset * device_scale_factor,
1050 kHotspotOffset * device_scale_factor);
1051 #if defined(OS_WIN)
1052 cursor_info.external_handle = 0;
1053 #endif
1054
1055 cursor.InitFromCursorInfo(cursor_info);
1056 DCHECK(host_);
1057 host_->SetCursor(cursor);
1058 return true;
1059 }
1060
850 // Input agent handlers ------------------------------------------------------ 1061 // Input agent handlers ------------------------------------------------------
851 1062
852 scoped_refptr<DevToolsProtocol::Response> 1063 scoped_refptr<DevToolsProtocol::Response>
853 RendererOverridesHandler::InputEmulateTouchFromMouseEvent( 1064 RendererOverridesHandler::InputEmulateTouchFromMouseEvent(
854 scoped_refptr<DevToolsProtocol::Command> command) { 1065 scoped_refptr<DevToolsProtocol::Command> command) {
855 if (!screencast_command_) 1066 if (!screencast_command_)
856 return command->InternalErrorResponse("Screencast should be turned on"); 1067 return command->InternalErrorResponse("Screencast should be turned on");
857 1068
858 base::DictionaryValue* params = command->params(); 1069 base::DictionaryValue* params = command->params();
859 if (!params) 1070 if (!params)
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 return command->InternalErrorResponse("Could not connect to view"); 1183 return command->InternalErrorResponse("Could not connect to view");
973 1184
974 if (event->type == WebInputEvent::MouseWheel) 1185 if (event->type == WebInputEvent::MouseWheel)
975 host_->ForwardWheelEvent(wheel_event); 1186 host_->ForwardWheelEvent(wheel_event);
976 else 1187 else
977 host_->ForwardMouseEvent(mouse_event); 1188 host_->ForwardMouseEvent(mouse_event);
978 return command->SuccessResponse(NULL); 1189 return command->SuccessResponse(NULL);
979 } 1190 }
980 1191
981 } // namespace content 1192 } // namespace content
OLDNEW
« no previous file with comments | « content/browser/devtools/renderer_overrides_handler.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698