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

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: float... 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_)
aandrey 2014/08/17 19:07:01 there is "&& host" check above before accessing ho
pfeldman 2014/08/17 19:09:40 This should not happen, but I agree I should follo
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 RenderWidgetHostViewBase* view = static_cast<RenderWidgetHostViewBase*>(
955 host_->GetView());
956 if (!view)
957 return true;
958
959 // Due to platform limitations, we are using two different cursors
960 // depending on the platform. Mac and Win have large cursors with two circles
961 // for original spot and its magnified projection; Linux gets smaller (64 px)
962 // magnified projection only with centered hotspot.
963 // Mac Retina requires cursor to be > 120px in order to render smoothly.
964
965 #if defined(OS_LINUX)
966 const float kCursorSize = 63;
967 const float kDiameter = 63;
968 const float kHotspotOffset = 32;
969 const float kHotspotRadius = 0;
970 const float kPixelSize = 9;
971 #else
972 const float kCursorSize = 150;
973 const float kDiameter = 110;
974 const float kHotspotOffset = 25;
975 const float kHotspotRadius = 5;
976 const float kPixelSize = 10;
977 #endif
978
979 const float kSqrt2 = 1.41f;
980
981 blink::WebScreenInfo screen_info;
982 view->GetScreenInfo(&screen_info);
983 double device_scale_factor = screen_info.deviceScaleFactor;
984
985 skia::RefPtr<SkCanvas> canvas = skia::AdoptRef(SkCanvas::NewRasterN32(
986 kCursorSize * device_scale_factor,
987 kCursorSize * device_scale_factor));
988 canvas->scale(device_scale_factor, device_scale_factor);
989
990 SkPaint paint;
991
992 // Paint original spot.
993 if (kHotspotRadius) {
994 paint.setStrokeWidth(2);
995 paint.setColor(SK_ColorDKGRAY);
996 paint.setStyle(SkPaint::kStroke_Style);
997 paint.setAntiAlias(true);
998 canvas->drawCircle(kHotspotOffset, kHotspotOffset, kHotspotRadius, paint);
999 canvas->drawLine(kHotspotOffset + kHotspotRadius / kSqrt2,
1000 kHotspotOffset + kHotspotRadius / kSqrt2,
1001 kCursorSize / 2, kCursorSize / 2,
1002 paint);
1003 }
1004
1005 // Clip circle for magnified projection.
1006 float padding = (kCursorSize - kDiameter) / 2;
1007 SkPath clip_path;
1008 clip_path.addOval(SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter));
1009 clip_path.close();
1010 canvas->clipPath(clip_path, SkRegion::kIntersect_Op, true);
1011
1012 // Project pixels.
1013 int pixel_count = kDiameter / kPixelSize;
1014 SkRect src_rect = SkRect::MakeXYWH(event.x - pixel_count / 2,
1015 event.y - pixel_count / 2,
1016 pixel_count, pixel_count);
1017 SkRect dst_rect = SkRect::MakeXYWH(padding, padding, kDiameter, kDiameter);
1018 canvas->drawBitmapRectToRect(color_picker_frame_, &src_rect, dst_rect);
1019
1020 // Paint grid.
1021 paint.setStrokeWidth(1);
1022 paint.setAntiAlias(false);
1023 paint.setColor(SK_ColorGRAY);
1024 for (int i = 0; i < pixel_count; ++i) {
1025 canvas->drawLine(padding + i * kPixelSize, padding,
1026 padding + i * kPixelSize, kCursorSize - padding, paint);
1027 canvas->drawLine(padding, padding + i * kPixelSize,
1028 kCursorSize - padding, padding + i * kPixelSize, paint);
1029 }
1030
1031 // Paint central pixel in red.
1032 SkRect pixel = SkRect::MakeXYWH((kCursorSize - kPixelSize) / 2,
1033 (kCursorSize - kPixelSize) / 2,
1034 kPixelSize, kPixelSize);
1035 paint.setColor(SK_ColorRED);
1036 canvas->drawRect(pixel, paint);
1037
1038 // Paint outline.
1039 paint.setStrokeWidth(2);
1040 paint.setColor(SK_ColorDKGRAY);
1041 paint.setAntiAlias(true);
1042 paint.setStyle(SkPaint::kStroke_Style);
1043 canvas->drawCircle(kCursorSize / 2, kCursorSize / 2, kDiameter / 2, paint);
1044
1045 SkBitmap result;
1046 result.allocN32Pixels(kCursorSize * device_scale_factor,
1047 kCursorSize * device_scale_factor);
1048 canvas->readPixels(&result, 0, 0);
1049
1050 WebCursor cursor;
1051 WebCursor::CursorInfo cursor_info;
1052 cursor_info.type = blink::WebCursorInfo::TypeCustom;
1053 cursor_info.image_scale_factor = device_scale_factor;
1054 cursor_info.custom_image = result;
1055 cursor_info.hotspot =
1056 gfx::Point(kHotspotOffset * device_scale_factor,
1057 kHotspotOffset * device_scale_factor);
1058 #if defined(OS_WIN)
1059 cursor_info.external_handle = 0;
1060 #endif
1061
1062 cursor.InitFromCursorInfo(cursor_info);
1063 DCHECK(host_);
1064 host_->SetCursor(cursor);
1065 return true;
1066 }
1067
850 // Input agent handlers ------------------------------------------------------ 1068 // Input agent handlers ------------------------------------------------------
851 1069
852 scoped_refptr<DevToolsProtocol::Response> 1070 scoped_refptr<DevToolsProtocol::Response>
853 RendererOverridesHandler::InputEmulateTouchFromMouseEvent( 1071 RendererOverridesHandler::InputEmulateTouchFromMouseEvent(
854 scoped_refptr<DevToolsProtocol::Command> command) { 1072 scoped_refptr<DevToolsProtocol::Command> command) {
855 if (!screencast_command_) 1073 if (!screencast_command_)
856 return command->InternalErrorResponse("Screencast should be turned on"); 1074 return command->InternalErrorResponse("Screencast should be turned on");
857 1075
858 base::DictionaryValue* params = command->params(); 1076 base::DictionaryValue* params = command->params();
859 if (!params) 1077 if (!params)
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
972 return command->InternalErrorResponse("Could not connect to view"); 1190 return command->InternalErrorResponse("Could not connect to view");
973 1191
974 if (event->type == WebInputEvent::MouseWheel) 1192 if (event->type == WebInputEvent::MouseWheel)
975 host_->ForwardWheelEvent(wheel_event); 1193 host_->ForwardWheelEvent(wheel_event);
976 else 1194 else
977 host_->ForwardMouseEvent(mouse_event); 1195 host_->ForwardMouseEvent(mouse_event);
978 return command->SuccessResponse(NULL); 1196 return command->SuccessResponse(NULL);
979 } 1197 }
980 1198
981 } // namespace content 1199 } // 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