1 /*
2  * Copyright (C) 2011 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  *
8  * 1.  Redistributions of source code must retain the above copyright
9  *     notice, this list of conditions and the following disclaimer.
10  * 2.  Redistributions in binary form must reproduce the above copyright
11  *     notice, this list of conditions and the following disclaimer in the
12  *     documentation and/or other materials provided with the distribution.
13  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28 
29 #include "third_party/blink/renderer/core/inspector/inspector_overlay_agent.h"
30 
31 #include <algorithm>
32 #include <memory>
33 #include <utility>
34 
35 #include "base/auto_reset.h"
36 #include "build/build_config.h"
37 #include "cc/layers/picture_layer.h"
38 #include "third_party/blink/public/platform/platform.h"
39 #include "third_party/blink/public/platform/task_type.h"
40 #include "third_party/blink/public/platform/web_data.h"
41 #include "third_party/blink/public/resources/grit/inspector_overlay_resources_map.h"
42 #include "third_party/blink/public/web/web_widget_client.h"
43 #include "third_party/blink/renderer/bindings/core/v8/script_source_code.h"
44 #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h"
45 #include "third_party/blink/renderer/bindings/core/v8/v8_inspector_overlay_host.h"
46 #include "third_party/blink/renderer/core/display_lock/display_lock_utilities.h"
47 #include "third_party/blink/renderer/core/dom/dom_node_ids.h"
48 #include "third_party/blink/renderer/core/dom/node.h"
49 #include "third_party/blink/renderer/core/dom/static_node_list.h"
50 #include "third_party/blink/renderer/core/events/web_input_event_conversion.h"
51 #include "third_party/blink/renderer/core/exported/web_view_impl.h"
52 #include "third_party/blink/renderer/core/frame/frame_overlay.h"
53 #include "third_party/blink/renderer/core/frame/local_frame.h"
54 #include "third_party/blink/renderer/core/frame/local_frame_client.h"
55 #include "third_party/blink/renderer/core/frame/local_frame_view.h"
56 #include "third_party/blink/renderer/core/frame/root_frame_viewport.h"
57 #include "third_party/blink/renderer/core/frame/settings.h"
58 #include "third_party/blink/renderer/core/frame/visual_viewport.h"
59 #include "third_party/blink/renderer/core/frame/web_frame_widget_base.h"
60 #include "third_party/blink/renderer/core/frame/web_local_frame_impl.h"
61 #include "third_party/blink/renderer/core/html/html_frame_owner_element.h"
62 #include "third_party/blink/renderer/core/input/event_handler.h"
63 #include "third_party/blink/renderer/core/inspector/identifiers_factory.h"
64 #include "third_party/blink/renderer/core/inspector/inspect_tools.h"
65 #include "third_party/blink/renderer/core/inspector/inspected_frames.h"
66 #include "third_party/blink/renderer/core/inspector/inspector_css_agent.h"
67 #include "third_party/blink/renderer/core/inspector/inspector_dom_agent.h"
68 #include "third_party/blink/renderer/core/inspector/inspector_overlay_host.h"
69 #include "third_party/blink/renderer/core/layout/layout_view.h"
70 #include "third_party/blink/renderer/core/loader/empty_clients.h"
71 #include "third_party/blink/renderer/core/loader/frame_load_request.h"
72 #include "third_party/blink/renderer/core/page/chrome_client.h"
73 #include "third_party/blink/renderer/core/page/page.h"
74 #include "third_party/blink/renderer/core/script/classic_script.h"
75 #include "third_party/blink/renderer/platform/bindings/script_forbidden_scope.h"
76 #include "third_party/blink/renderer/platform/data_resource_helper.h"
77 #include "third_party/blink/renderer/platform/graphics/color.h"
78 #include "third_party/blink/renderer/platform/graphics/graphics_context.h"
79 #include "third_party/blink/renderer/platform/graphics/paint/cull_rect.h"
80 #include "third_party/blink/renderer/platform/graphics/paint/drawing_recorder.h"
81 #include "third_party/blink/renderer/platform/graphics/paint/foreign_layer_display_item.h"
82 #include "third_party/blink/renderer/platform/graphics/paint/paint_record_builder.h"
83 #include "third_party/blink/renderer/platform/heap/heap.h"
84 #include "third_party/blink/renderer/platform/keyboard_codes.h"
85 #include "third_party/inspector_protocol/crdtp/json.h"
86 #include "v8/include/v8.h"
87 
88 using crdtp::SpanFrom;
89 using crdtp::json::ConvertCBORToJSON;
90 
91 namespace blink {
92 
93 using protocol::Maybe;
94 using protocol::Response;
95 
96 namespace {
97 
ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array,FloatQuad * quad)98 bool ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array,
99                FloatQuad* quad) {
100   const size_t kCoordinatesInQuad = 8;
101   if (!quad_array || quad_array->size() != kCoordinatesInQuad)
102     return false;
103   quad->SetP1(FloatPoint((*quad_array)[0], (*quad_array)[1]));
104   quad->SetP2(FloatPoint((*quad_array)[2], (*quad_array)[3]));
105   quad->SetP3(FloatPoint((*quad_array)[4], (*quad_array)[5]));
106   quad->SetP4(FloatPoint((*quad_array)[6], (*quad_array)[7]));
107   return true;
108 }
109 
110 }  // namespace
111 
112 // OverlayNames ----------------------------------------------------------------
113 const char* OverlayNames::OVERLAY_HIGHLIGHT = "highlight";
114 const char* OverlayNames::OVERLAY_HIGHLIGHT_GRID = "highlightGrid";
115 const char* OverlayNames::OVERLAY_SOURCE_ORDER = "sourceOrder";
116 const char* OverlayNames::OVERLAY_DISTANCES = "distances";
117 const char* OverlayNames::OVERLAY_VIEWPORT_SIZE = "viewportSize";
118 const char* OverlayNames::OVERLAY_SCREENSHOT = "screenshot";
119 const char* OverlayNames::OVERLAY_PAUSED = "paused";
120 
121 // InspectTool -----------------------------------------------------------------
HandleInputEvent(LocalFrameView * frame_view,const WebInputEvent & input_event,bool * swallow_next_mouse_up)122 bool InspectTool::HandleInputEvent(LocalFrameView* frame_view,
123                                    const WebInputEvent& input_event,
124                                    bool* swallow_next_mouse_up) {
125   if (input_event.GetType() == WebInputEvent::Type::kGestureTap) {
126     // We only have a use for gesture tap.
127     WebGestureEvent transformed_event = TransformWebGestureEvent(
128         frame_view, static_cast<const WebGestureEvent&>(input_event));
129     return HandleGestureTapEvent(transformed_event);
130   }
131 
132   if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
133     WebMouseEvent transformed_event = TransformWebMouseEvent(
134         frame_view, static_cast<const WebMouseEvent&>(input_event));
135     return HandleMouseEvent(transformed_event, swallow_next_mouse_up);
136   }
137 
138   if (WebInputEvent::IsPointerEventType(input_event.GetType())) {
139     WebPointerEvent transformed_event = TransformWebPointerEvent(
140         frame_view, static_cast<const WebPointerEvent&>(input_event));
141     return HandlePointerEvent(transformed_event);
142   }
143 
144   if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
145     return HandleKeyboardEvent(
146         static_cast<const WebKeyboardEvent&>(input_event));
147   }
148 
149   return false;
150 }
151 
HandleMouseEvent(const WebMouseEvent & mouse_event,bool * swallow_next_mouse_up)152 bool InspectTool::HandleMouseEvent(const WebMouseEvent& mouse_event,
153                                    bool* swallow_next_mouse_up) {
154   if (mouse_event.GetType() == WebInputEvent::Type::kMouseMove)
155     return HandleMouseMove(mouse_event);
156 
157   if (mouse_event.GetType() == WebInputEvent::Type::kMouseDown)
158     return HandleMouseDown(mouse_event, swallow_next_mouse_up);
159 
160   if (mouse_event.GetType() == WebInputEvent::Type::kMouseUp)
161     return HandleMouseUp(mouse_event);
162 
163   return false;
164 }
165 
HandleMouseDown(const WebMouseEvent &,bool * swallow_next_mouse_up)166 bool InspectTool::HandleMouseDown(const WebMouseEvent&,
167                                   bool* swallow_next_mouse_up) {
168   return false;
169 }
170 
HandleMouseUp(const WebMouseEvent &)171 bool InspectTool::HandleMouseUp(const WebMouseEvent&) {
172   return false;
173 }
174 
HandleMouseMove(const WebMouseEvent &)175 bool InspectTool::HandleMouseMove(const WebMouseEvent&) {
176   return false;
177 }
178 
HandleGestureTapEvent(const WebGestureEvent &)179 bool InspectTool::HandleGestureTapEvent(const WebGestureEvent&) {
180   return false;
181 }
182 
HandlePointerEvent(const WebPointerEvent &)183 bool InspectTool::HandlePointerEvent(const WebPointerEvent&) {
184   return false;
185 }
186 
HandleKeyboardEvent(const WebKeyboardEvent &)187 bool InspectTool::HandleKeyboardEvent(const WebKeyboardEvent&) {
188   return false;
189 }
190 
ForwardEventsToOverlay()191 bool InspectTool::ForwardEventsToOverlay() {
192   return true;
193 }
194 
SupportsPersistentOverlays()195 bool InspectTool::SupportsPersistentOverlays() {
196   return false;
197 }
198 
HideOnMouseMove()199 bool InspectTool::HideOnMouseMove() {
200   return false;
201 }
202 
HideOnHideHighlight()203 bool InspectTool::HideOnHideHighlight() {
204   return false;
205 }
206 
Trace(Visitor * visitor) const207 void InspectTool::Trace(Visitor* visitor) const {
208   visitor->Trace(overlay_);
209 }
210 
211 // Hinge -----------------------------------------------------------------------
212 
Hinge(FloatQuad quad,Color content_color,Color outline_color,InspectorOverlayAgent * overlay)213 Hinge::Hinge(FloatQuad quad,
214              Color content_color,
215              Color outline_color,
216              InspectorOverlayAgent* overlay)
217     : quad_(quad),
218       content_color_(content_color),
219       outline_color_(outline_color),
220       overlay_(overlay) {}
221 
GetOverlayName()222 String Hinge::GetOverlayName() {
223   // TODO (soxia): In the future, we should make the hinge working properly
224   // with tools using different resources.
225   return OverlayNames::OVERLAY_HIGHLIGHT;
226 }
227 
Trace(Visitor * visitor) const228 void Hinge::Trace(Visitor* visitor) const {
229   visitor->Trace(overlay_);
230 }
231 
Draw(float scale)232 void Hinge::Draw(float scale) {
233   // scaling is applied at the drawHighlight code.
234   InspectorHighlight highlight(1.f);
235   highlight.AppendQuad(quad_, content_color_, outline_color_);
236   overlay_->EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue());
237 }
238 
239 // InspectorOverlayAgent -------------------------------------------------------
240 
241 class InspectorOverlayAgent::InspectorPageOverlayDelegate final
242     : public FrameOverlay::Delegate,
243       public cc::ContentLayerClient {
244  public:
InspectorPageOverlayDelegate(InspectorOverlayAgent & overlay)245   explicit InspectorPageOverlayDelegate(InspectorOverlayAgent& overlay)
246       : overlay_(&overlay) {
247     if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
248       layer_ = cc::PictureLayer::Create(this);
249       layer_->SetIsDrawable(true);
250       layer_->SetHitTestable(false);
251     }
252   }
~InspectorPageOverlayDelegate()253   ~InspectorPageOverlayDelegate() override {
254     if (layer_)
255       layer_->ClearClient();
256   }
257 
PaintFrameOverlay(const FrameOverlay & frame_overlay,GraphicsContext & graphics_context,const IntSize & size) const258   void PaintFrameOverlay(const FrameOverlay& frame_overlay,
259                          GraphicsContext& graphics_context,
260                          const IntSize& size) const override {
261     if (!overlay_->IsVisible())
262       return;
263 
264     overlay_->PaintOverlayPage();
265 
266     if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
267       layer_->SetBounds(gfx::Size(size));
268       DEFINE_STATIC_LOCAL(LiteralDebugNameClient, debug_name_client,
269                           ("InspectorOverlay"));
270       RecordForeignLayer(graphics_context, debug_name_client,
271                          DisplayItem::kForeignLayerDevToolsOverlay, layer_,
272                          IntPoint(), &PropertyTreeState::Root());
273       return;
274     }
275 
276     frame_overlay.Invalidate();
277     DrawingRecorder recorder(graphics_context, frame_overlay,
278                              DisplayItem::kFrameOverlay,
279                              IntRect(IntPoint(), size));
280     // The overlay frame is has a standalone paint property tree. Paint it in
281     // its root space into a paint record, then draw the record into the proper
282     // target space in the overlaid frame.
283     PaintRecordBuilder paint_record_builder(nullptr, &graphics_context);
284     overlay_->OverlayMainFrame()->View()->PaintOutsideOfLifecycle(
285         paint_record_builder.Context(), kGlobalPaintNormalPhase);
286     graphics_context.DrawRecord(paint_record_builder.EndRecording());
287   }
288 
Invalidate()289   void Invalidate() override {
290     if (layer_)
291       layer_->SetNeedsDisplay();
292   }
293 
GetLayer() const294   const cc::Layer* GetLayer() const { return layer_.get(); }
295 
296  private:
297   // cc::ContentLayerClient implementation
PaintableRegion()298   gfx::Rect PaintableRegion() override { return gfx::Rect(layer_->bounds()); }
FillsBoundsCompletely() const299   bool FillsBoundsCompletely() const override { return false; }
300 
PaintContentsToDisplayList()301   scoped_refptr<cc::DisplayItemList> PaintContentsToDisplayList() override {
302     auto display_list = base::MakeRefCounted<cc::DisplayItemList>();
303     display_list->StartPaint();
304     display_list->push<cc::DrawRecordOp>(
305         overlay_->OverlayMainFrame()->View()->GetPaintRecord());
306     display_list->EndPaintOfUnpaired(PaintableRegion());
307     display_list->Finalize();
308     return display_list;
309   }
310 
311   Persistent<InspectorOverlayAgent> overlay_;
312   // For CompositeAfterPaint.
313   scoped_refptr<cc::PictureLayer> layer_;
314 };
315 
316 class InspectorOverlayAgent::InspectorOverlayChromeClient final
317     : public EmptyChromeClient {
318  public:
InspectorOverlayChromeClient(ChromeClient & client,InspectorOverlayAgent & overlay)319   InspectorOverlayChromeClient(ChromeClient& client,
320                                InspectorOverlayAgent& overlay)
321       : client_(&client), overlay_(&overlay) {}
322 
Trace(Visitor * visitor) const323   void Trace(Visitor* visitor) const override {
324     visitor->Trace(client_);
325     visitor->Trace(overlay_);
326     EmptyChromeClient::Trace(visitor);
327   }
328 
SetCursor(const ui::Cursor & cursor,LocalFrame * local_root)329   void SetCursor(const ui::Cursor& cursor, LocalFrame* local_root) override {
330     client_->SetCursorOverridden(false);
331     client_->SetCursor(cursor, overlay_->GetFrame());
332     client_->SetCursorOverridden(true);
333   }
334 
SetToolTip(LocalFrame & frame,const String & tooltip,TextDirection direction)335   void SetToolTip(LocalFrame& frame,
336                   const String& tooltip,
337                   TextDirection direction) override {
338     DCHECK_EQ(&frame, overlay_->OverlayMainFrame());
339     client_->SetToolTip(*overlay_->GetFrame(), tooltip, direction);
340   }
341 
342  private:
343   Member<ChromeClient> client_;
344   Member<InspectorOverlayAgent> overlay_;
345 };
346 
InspectorOverlayAgent(WebLocalFrameImpl * frame_impl,InspectedFrames * inspected_frames,v8_inspector::V8InspectorSession * v8_session,InspectorDOMAgent * dom_agent)347 InspectorOverlayAgent::InspectorOverlayAgent(
348     WebLocalFrameImpl* frame_impl,
349     InspectedFrames* inspected_frames,
350     v8_inspector::V8InspectorSession* v8_session,
351     InspectorDOMAgent* dom_agent)
352     : frame_impl_(frame_impl),
353       inspected_frames_(inspected_frames),
354       resize_timer_active_(false),
355       resize_timer_(
356           frame_impl->GetFrame()->GetTaskRunner(TaskType::kInternalInspector),
357           this,
358           &InspectorOverlayAgent::OnResizeTimer),
359       disposed_(false),
360       v8_session_(v8_session),
361       dom_agent_(dom_agent),
362       swallow_next_mouse_up_(false),
363       backend_node_id_to_inspect_(0),
364       enabled_(&agent_state_, false),
365       show_ad_highlights_(&agent_state_, false),
366       show_debug_borders_(&agent_state_, false),
367       show_fps_counter_(&agent_state_, false),
368       show_paint_rects_(&agent_state_, false),
369       show_layout_shift_regions_(&agent_state_, false),
370       show_scroll_bottleneck_rects_(&agent_state_, false),
371       show_hit_test_borders_(&agent_state_, false),
372       show_size_on_resize_(&agent_state_, false),
373       paused_in_debugger_message_(&agent_state_, String()),
374       inspect_mode_(&agent_state_, protocol::Overlay::InspectModeEnum::None),
375       inspect_mode_protocol_config_(&agent_state_, std::vector<uint8_t>()) {}
376 
~InspectorOverlayAgent()377 InspectorOverlayAgent::~InspectorOverlayAgent() {
378   DCHECK(!overlay_page_ && !inspect_tool_ && !hinge_ && !persistent_tool_);
379 }
380 
Trace(Visitor * visitor) const381 void InspectorOverlayAgent::Trace(Visitor* visitor) const {
382   visitor->Trace(frame_impl_);
383   visitor->Trace(inspected_frames_);
384   visitor->Trace(overlay_page_);
385   visitor->Trace(overlay_chrome_client_);
386   visitor->Trace(overlay_host_);
387   visitor->Trace(dom_agent_);
388   visitor->Trace(inspect_tool_);
389   visitor->Trace(persistent_tool_);
390   visitor->Trace(hinge_);
391   visitor->Trace(document_to_ax_context_);
392   InspectorBaseAgent::Trace(visitor);
393 }
394 
Restore()395 void InspectorOverlayAgent::Restore() {
396   if (enabled_.Get())
397     enable();
398   setShowAdHighlights(show_ad_highlights_.Get());
399   setShowDebugBorders(show_debug_borders_.Get());
400   setShowFPSCounter(show_fps_counter_.Get());
401   setShowPaintRects(show_paint_rects_.Get());
402   setShowLayoutShiftRegions(show_layout_shift_regions_.Get());
403   setShowScrollBottleneckRects(show_scroll_bottleneck_rects_.Get());
404   setShowHitTestBorders(show_hit_test_borders_.Get());
405   setShowViewportSizeOnResize(show_size_on_resize_.Get());
406   PickTheRightTool();
407 }
408 
Dispose()409 void InspectorOverlayAgent::Dispose() {
410   InspectorBaseAgent::Dispose();
411   disposed_ = true;
412 }
413 
enable()414 Response InspectorOverlayAgent::enable() {
415   if (!dom_agent_->Enabled())
416     return Response::ServerError("DOM should be enabled first");
417   enabled_.Set(true);
418   if (backend_node_id_to_inspect_) {
419     GetFrontend()->inspectNodeRequested(
420         static_cast<int>(backend_node_id_to_inspect_));
421   }
422   backend_node_id_to_inspect_ = 0;
423   SetNeedsUnbufferedInput(true);
424   return Response::Success();
425 }
426 
EnsureAXContext(Node * node)427 void InspectorOverlayAgent::EnsureAXContext(Node* node) {
428   Document& document = node->GetDocument();
429   if (!document_to_ax_context_.Contains(&document)) {
430     auto context = std::make_unique<AXContext>(document);
431     document_to_ax_context_.Set(&document, std::move(context));
432   }
433 }
434 
disable()435 Response InspectorOverlayAgent::disable() {
436   enabled_.Clear();
437   setShowAdHighlights(false);
438   setShowDebugBorders(false);
439   setShowFPSCounter(false);
440   setShowPaintRects(false);
441   setShowLayoutShiftRegions(false);
442   setShowScrollBottleneckRects(false);
443   setShowHitTestBorders(false);
444   setShowViewportSizeOnResize(false);
445   paused_in_debugger_message_.Clear();
446   inspect_mode_.Set(protocol::Overlay::InspectModeEnum::None);
447   inspect_mode_protocol_config_.Set(std::vector<uint8_t>());
448   if (overlay_page_) {
449     overlay_page_->WillBeDestroyed();
450     overlay_page_.Clear();
451     overlay_chrome_client_.Clear();
452     overlay_host_->ClearDelegate();
453     overlay_host_.Clear();
454   }
455   resize_timer_.Stop();
456   resize_timer_active_ = false;
457   frame_overlay_.reset();
458   persistent_tool_ = nullptr;
459   PickTheRightTool();
460   SetNeedsUnbufferedInput(false);
461   document_to_ax_context_.clear();
462   return Response::Success();
463 }
464 
setShowAdHighlights(bool show)465 Response InspectorOverlayAgent::setShowAdHighlights(bool show) {
466   show_ad_highlights_.Set(show);
467   frame_impl_->ViewImpl()->GetPage()->GetSettings().SetHighlightAds(show);
468   return Response::Success();
469 }
470 
setShowDebugBorders(bool show)471 Response InspectorOverlayAgent::setShowDebugBorders(bool show) {
472   show_debug_borders_.Set(show);
473   if (show) {
474     Response response = CompositingEnabled();
475     if (!response.IsSuccess())
476       return response;
477   }
478   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
479   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
480   // While a frame is being detached the inspector will shutdown and
481   // turn off debug overlays, but the WebFrameWidget is already gone.
482   if (widget_impl) {
483     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
484     if (show)
485       debug_state.show_debug_borders.set();
486     else
487       debug_state.show_debug_borders.reset();
488     widget_impl->SetLayerTreeDebugState(debug_state);
489   }
490   return Response::Success();
491 }
492 
setShowFPSCounter(bool show)493 Response InspectorOverlayAgent::setShowFPSCounter(bool show) {
494   show_fps_counter_.Set(show);
495   if (show) {
496     Response response = CompositingEnabled();
497     if (!response.IsSuccess())
498       return response;
499   }
500   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
501   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
502   // While a frame is being detached the inspector will shutdown and
503   // turn off debug overlays, but the WebFrameWidget is already gone.
504   if (widget_impl) {
505     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
506     debug_state.show_fps_counter = show;
507     widget_impl->SetLayerTreeDebugState(debug_state);
508   }
509   return Response::Success();
510 }
511 
setShowPaintRects(bool show)512 Response InspectorOverlayAgent::setShowPaintRects(bool show) {
513   show_paint_rects_.Set(show);
514   if (show) {
515     Response response = CompositingEnabled();
516     if (!response.IsSuccess())
517       return response;
518   }
519   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
520   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
521   // While a frame is being detached the inspector will shutdown and
522   // turn off debug overlays, but the WebFrameWidget is already gone.
523   if (widget_impl) {
524     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
525     debug_state.show_paint_rects = show;
526     widget_impl->SetLayerTreeDebugState(debug_state);
527   }
528   if (!show && frame_impl_->GetFrameView())
529     frame_impl_->GetFrameView()->Invalidate();
530   return Response::Success();
531 }
532 
setShowLayoutShiftRegions(bool show)533 Response InspectorOverlayAgent::setShowLayoutShiftRegions(bool show) {
534   show_layout_shift_regions_.Set(show);
535   if (show) {
536     Response response = CompositingEnabled();
537     if (!response.IsSuccess())
538       return response;
539   }
540   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
541   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
542   // While a frame is being detached the inspector will shutdown and
543   // turn off debug overlays, but the WebFrameWidget is already gone.
544   if (widget_impl) {
545     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
546     debug_state.show_layout_shift_regions = show;
547     widget_impl->SetLayerTreeDebugState(debug_state);
548   }
549 
550   if (!show && frame_impl_->GetFrameView())
551     frame_impl_->GetFrameView()->Invalidate();
552   return Response::Success();
553 }
554 
setShowScrollBottleneckRects(bool show)555 Response InspectorOverlayAgent::setShowScrollBottleneckRects(bool show) {
556   show_scroll_bottleneck_rects_.Set(show);
557   if (show) {
558     Response response = CompositingEnabled();
559     if (!response.IsSuccess())
560       return response;
561   }
562   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
563   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
564   // While a frame is being detached the inspector will shutdown and
565   // turn off debug overlays, but the WebFrameWidget is already gone.
566   if (widget_impl) {
567     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
568     debug_state.show_touch_event_handler_rects = show;
569     debug_state.show_wheel_event_handler_rects = show;
570     debug_state.show_non_fast_scrollable_rects = show;
571     debug_state.show_main_thread_scrolling_reason_rects = show;
572     widget_impl->SetLayerTreeDebugState(debug_state);
573   }
574 
575   return Response::Success();
576 }
577 
setShowHitTestBorders(bool show)578 Response InspectorOverlayAgent::setShowHitTestBorders(bool show) {
579   show_hit_test_borders_.Set(show);
580   if (show) {
581     Response response = CompositingEnabled();
582     if (!response.IsSuccess())
583       return response;
584   }
585   WebFrameWidget* widget = frame_impl_->LocalRoot()->FrameWidget();
586   WebFrameWidgetBase* widget_impl = static_cast<WebFrameWidgetBase*>(widget);
587   // While a frame is being detached the inspector will shutdown and
588   // turn off debug overlays, but the WebFrameWidget is already gone.
589   if (widget_impl) {
590     cc::LayerTreeDebugState debug_state = widget_impl->GetLayerTreeDebugState();
591     debug_state.show_hit_test_borders = show;
592     widget_impl->SetLayerTreeDebugState(debug_state);
593   }
594   return Response::Success();
595 }
596 
setShowViewportSizeOnResize(bool show)597 Response InspectorOverlayAgent::setShowViewportSizeOnResize(bool show) {
598   show_size_on_resize_.Set(show);
599   return Response::Success();
600 }
601 
setPausedInDebuggerMessage(Maybe<String> message)602 Response InspectorOverlayAgent::setPausedInDebuggerMessage(
603     Maybe<String> message) {
604   paused_in_debugger_message_.Set(message.fromMaybe(String()));
605   PickTheRightTool();
606   return Response::Success();
607 }
608 
highlightRect(int x,int y,int width,int height,Maybe<protocol::DOM::RGBA> color,Maybe<protocol::DOM::RGBA> outline_color)609 Response InspectorOverlayAgent::highlightRect(
610     int x,
611     int y,
612     int width,
613     int height,
614     Maybe<protocol::DOM::RGBA> color,
615     Maybe<protocol::DOM::RGBA> outline_color) {
616   std::unique_ptr<FloatQuad> quad =
617       std::make_unique<FloatQuad>(FloatRect(x, y, width, height));
618   return SetInspectTool(MakeGarbageCollected<QuadHighlightTool>(
619       this, GetFrontend(), std::move(quad),
620       InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr)),
621       InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr))));
622 }
623 
highlightQuad(std::unique_ptr<protocol::Array<double>> quad_array,Maybe<protocol::DOM::RGBA> color,Maybe<protocol::DOM::RGBA> outline_color)624 Response InspectorOverlayAgent::highlightQuad(
625     std::unique_ptr<protocol::Array<double>> quad_array,
626     Maybe<protocol::DOM::RGBA> color,
627     Maybe<protocol::DOM::RGBA> outline_color) {
628   std::unique_ptr<FloatQuad> quad = std::make_unique<FloatQuad>();
629   if (!ParseQuad(std::move(quad_array), quad.get()))
630     return Response::ServerError("Invalid Quad format");
631   return SetInspectTool(MakeGarbageCollected<QuadHighlightTool>(
632       this, GetFrontend(), std::move(quad),
633       InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr)),
634       InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr))));
635 }
636 
setShowHinge(protocol::Maybe<protocol::Overlay::HingeConfig> tool_config)637 Response InspectorOverlayAgent::setShowHinge(
638     protocol::Maybe<protocol::Overlay::HingeConfig> tool_config) {
639   // Hide the hinge when called without a configuration.
640   if (!tool_config.isJust()) {
641     hinge_ = nullptr;
642     if (!inspect_tool_)
643       DisableFrameOverlay();
644     ScheduleUpdate();
645     return Response::Success();
646   }
647 
648   // Create a hinge
649   protocol::Overlay::HingeConfig* config = tool_config.fromJust();
650   protocol::DOM::Rect* rect = config->getRect();
651   int x = rect->getX();
652   int y = rect->getY();
653   int width = rect->getWidth();
654   int height = rect->getHeight();
655   if (x < 0 || y < 0 || width < 0 || height < 0)
656     return Response::InvalidParams("Invalid hinge rectangle.");
657 
658   // Use default color if a content color is not provided.
659   Color content_color =
660       config->hasContentColor()
661           ? InspectorDOMAgent::ParseColor(config->getContentColor(nullptr))
662           : Color(38, 38, 38);
663   // outlineColor uses a kTransparent default from ParseColor if not provided.
664   Color outline_color =
665       InspectorDOMAgent::ParseColor(config->getOutlineColor(nullptr));
666 
667   DCHECK(frame_impl_->GetFrameView() && GetFrame());
668 
669   FloatQuad quad(FloatRect(x, y, width, height));
670   hinge_ =
671       MakeGarbageCollected<Hinge>(quad, content_color, outline_color, this);
672 
673   LoadOverlayPageResource();
674   EvaluateInOverlay("setOverlay", hinge_->GetOverlayName());
675   EnsureEnableFrameOverlay();
676 
677   ScheduleUpdate();
678 
679   return Response::Success();
680 }
681 
highlightNode(std::unique_ptr<protocol::Overlay::HighlightConfig> highlight_inspector_object,Maybe<int> node_id,Maybe<int> backend_node_id,Maybe<String> object_id,Maybe<String> selector_list)682 Response InspectorOverlayAgent::highlightNode(
683     std::unique_ptr<protocol::Overlay::HighlightConfig>
684         highlight_inspector_object,
685     Maybe<int> node_id,
686     Maybe<int> backend_node_id,
687     Maybe<String> object_id,
688     Maybe<String> selector_list) {
689   Node* node = nullptr;
690   Response response =
691       dom_agent_->AssertNode(node_id, backend_node_id, object_id, node);
692   if (!response.IsSuccess())
693     return response;
694 
695   std::unique_ptr<InspectorHighlightConfig> highlight_config;
696   response = HighlightConfigFromInspectorObject(
697       std::move(highlight_inspector_object), &highlight_config);
698   if (!response.IsSuccess())
699     return response;
700 
701   return SetInspectTool(MakeGarbageCollected<NodeHighlightTool>(
702       this, GetFrontend(), node, selector_list.fromMaybe(String()),
703       std::move(highlight_config)));
704 }
705 
setShowGridOverlays(std::unique_ptr<protocol::Array<protocol::Overlay::GridNodeHighlightConfig>> grid_node_highlight_configs)706 Response InspectorOverlayAgent::setShowGridOverlays(
707     std::unique_ptr<protocol::Array<protocol::Overlay::GridNodeHighlightConfig>>
708         grid_node_highlight_configs) {
709   persistent_tool_ = nullptr;
710 
711   if (grid_node_highlight_configs->size()) {
712     GridHighlightTool* grid_tool =
713         MakeGarbageCollected<GridHighlightTool>(this, GetFrontend());
714     for (std::unique_ptr<protocol::Overlay::GridNodeHighlightConfig>& config :
715          *grid_node_highlight_configs) {
716       Node* node = nullptr;
717       Response response = dom_agent_->AssertNode(config->getNodeId(), node);
718       if (!response.IsSuccess())
719         return response;
720       grid_tool->AddGridConfig(node,
721                                InspectorOverlayAgent::ToGridHighlightConfig(
722                                    config->getGridHighlightConfig()));
723     }
724     persistent_tool_ = grid_tool;
725   }
726 
727   PickTheRightTool();
728 
729   return Response::Success();
730 }
731 
highlightSourceOrder(std::unique_ptr<protocol::Overlay::SourceOrderConfig> source_order_inspector_object,Maybe<int> node_id,Maybe<int> backend_node_id,Maybe<String> object_id)732 Response InspectorOverlayAgent::highlightSourceOrder(
733     std::unique_ptr<protocol::Overlay::SourceOrderConfig>
734         source_order_inspector_object,
735     Maybe<int> node_id,
736     Maybe<int> backend_node_id,
737     Maybe<String> object_id) {
738   Node* node = nullptr;
739   Response response =
740       dom_agent_->AssertNode(node_id, backend_node_id, object_id, node);
741   if (!response.IsSuccess())
742     return response;
743 
744   InspectorSourceOrderConfig config = SourceOrderConfigFromInspectorObject(
745       std::move(source_order_inspector_object));
746   std::unique_ptr<InspectorSourceOrderConfig> source_order_config =
747       std::make_unique<InspectorSourceOrderConfig>(config);
748 
749   return SetInspectTool(MakeGarbageCollected<SourceOrderTool>(
750       this, GetFrontend(), node, std::move(source_order_config)));
751 }
752 
highlightFrame(const String & frame_id,Maybe<protocol::DOM::RGBA> color,Maybe<protocol::DOM::RGBA> outline_color)753 Response InspectorOverlayAgent::highlightFrame(
754     const String& frame_id,
755     Maybe<protocol::DOM::RGBA> color,
756     Maybe<protocol::DOM::RGBA> outline_color) {
757   LocalFrame* frame =
758       IdentifiersFactory::FrameById(inspected_frames_, frame_id);
759   // FIXME: Inspector doesn't currently work cross process.
760   if (!frame)
761     return Response::ServerError("Invalid frame id");
762   if (!frame->DeprecatedLocalOwner()) {
763     PickTheRightTool();
764     return Response::Success();
765   }
766 
767   std::unique_ptr<InspectorHighlightConfig> highlight_config =
768       std::make_unique<InspectorHighlightConfig>();
769   highlight_config->show_info = true;  // Always show tooltips for frames.
770   highlight_config->content =
771       InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr));
772   highlight_config->content_outline =
773       InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr));
774 
775   return SetInspectTool(MakeGarbageCollected<NodeHighlightTool>(
776       this, GetFrontend(), frame->DeprecatedLocalOwner(), String(),
777       std::move(highlight_config)));
778 }
779 
hideHighlight()780 Response InspectorOverlayAgent::hideHighlight() {
781   if (inspect_tool_ && inspect_tool_->HideOnHideHighlight())
782     PickTheRightTool();
783 
784   return Response::Success();
785 }
786 
getHighlightObjectForTest(int node_id,Maybe<bool> include_distance,Maybe<bool> include_style,Maybe<String> colorFormat,Maybe<bool> show_accessibility_info,std::unique_ptr<protocol::DictionaryValue> * result)787 Response InspectorOverlayAgent::getHighlightObjectForTest(
788     int node_id,
789     Maybe<bool> include_distance,
790     Maybe<bool> include_style,
791     Maybe<String> colorFormat,
792     Maybe<bool> show_accessibility_info,
793     std::unique_ptr<protocol::DictionaryValue>* result) {
794   Node* node = nullptr;
795   Response response = dom_agent_->AssertNode(node_id, node);
796   if (!response.IsSuccess())
797     return response;
798 
799   auto config = std::make_unique<InspectorHighlightConfig>(
800       InspectorHighlight::DefaultConfig());
801   config->show_styles = include_style.fromMaybe(false);
802   config->show_accessibility_info = show_accessibility_info.fromMaybe(true);
803   String format = colorFormat.fromMaybe("hex");
804   namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
805   if (format == ColorFormatEnum::Hsl) {
806     config->color_format = ColorFormat::HSL;
807   } else if (format == ColorFormatEnum::Rgb) {
808     config->color_format = ColorFormat::RGB;
809   } else {
810     config->color_format = ColorFormat::HEX;
811   }
812 
813   NodeHighlightTool tool(this, GetFrontend(), node, "" /* selector_list */,
814                          std::move(config));
815   *result = tool.GetNodeInspectorHighlightAsJson(
816       true /* append_element_info */, include_distance.fromMaybe(false));
817   return Response::Success();
818 }
819 
getGridHighlightObjectsForTest(std::unique_ptr<protocol::Array<int>> node_ids,std::unique_ptr<protocol::DictionaryValue> * highlights)820 Response InspectorOverlayAgent::getGridHighlightObjectsForTest(
821     std::unique_ptr<protocol::Array<int>> node_ids,
822     std::unique_ptr<protocol::DictionaryValue>* highlights) {
823   GridHighlightTool grid_highlight_tool(this, GetFrontend());
824   for (const int node_id : *node_ids) {
825     Node* node = nullptr;
826     Response response = dom_agent_->AssertNode(node_id, node);
827     if (!response.IsSuccess())
828       return response;
829     grid_highlight_tool.AddGridConfig(
830         node, std::make_unique<InspectorGridHighlightConfig>(
831                   InspectorHighlight::DefaultGridConfig()));
832   }
833   *highlights = grid_highlight_tool.GetGridInspectorHighlightsAsJson();
834   return Response::Success();
835 }
836 
getSourceOrderHighlightObjectForTest(int node_id,std::unique_ptr<protocol::DictionaryValue> * result)837 Response InspectorOverlayAgent::getSourceOrderHighlightObjectForTest(
838     int node_id,
839     std::unique_ptr<protocol::DictionaryValue>* result) {
840   Node* node = nullptr;
841   Response response = dom_agent_->AssertNode(node_id, node);
842   if (!response.IsSuccess())
843     return response;
844 
845   auto config = std::make_unique<InspectorSourceOrderConfig>(
846       InspectorSourceOrderHighlight::DefaultConfig());
847 
848   SourceOrderTool tool(this, GetFrontend(), node, std::move(config));
849   *result = tool.GetNodeInspectorSourceOrderHighlightAsJson();
850   return Response::Success();
851 }
852 
UpdatePrePaint()853 void InspectorOverlayAgent::UpdatePrePaint() {
854   if (frame_overlay_)
855     frame_overlay_->UpdatePrePaint();
856 }
857 
PaintOverlay(GraphicsContext & context)858 void InspectorOverlayAgent::PaintOverlay(GraphicsContext& context) {
859   DCHECK(RuntimeEnabledFeatures::CompositeAfterPaintEnabled());
860   if (frame_overlay_)
861     frame_overlay_->Paint(context);
862 }
863 
IsInspectorLayer(const cc::Layer * layer) const864 bool InspectorOverlayAgent::IsInspectorLayer(const cc::Layer* layer) const {
865   if (!frame_overlay_)
866     return false;
867   if (RuntimeEnabledFeatures::CompositeAfterPaintEnabled()) {
868     return layer == static_cast<const InspectorPageOverlayDelegate*>(
869                         frame_overlay_->GetDelegate())
870                         ->GetLayer();
871   }
872   return layer == &frame_overlay_->GetGraphicsLayer()->CcLayer();
873 }
874 
GetFrame() const875 LocalFrame* InspectorOverlayAgent::GetFrame() const {
876   return frame_impl_->GetFrame();
877 }
878 
DispatchBufferedTouchEvents()879 void InspectorOverlayAgent::DispatchBufferedTouchEvents() {
880   if (!inspect_tool_)
881     return;
882   OverlayMainFrame()->GetEventHandler().DispatchBufferedTouchEvents();
883 }
884 
HandleInputEvent(const WebInputEvent & input_event)885 WebInputEventResult InspectorOverlayAgent::HandleInputEvent(
886     const WebInputEvent& input_event) {
887   if (!enabled_.Get())
888     return WebInputEventResult::kNotHandled;
889 
890   if (input_event.GetType() == WebInputEvent::Type::kMouseUp &&
891       swallow_next_mouse_up_) {
892     swallow_next_mouse_up_ = false;
893     return WebInputEventResult::kHandledSuppressed;
894   }
895 
896   LocalFrame* frame = GetFrame();
897   if (!frame || !frame->View() || !frame->ContentLayoutObject() ||
898       !inspect_tool_)
899     return WebInputEventResult::kNotHandled;
900 
901   bool handled = inspect_tool_->HandleInputEvent(
902       frame_impl_->GetFrameView(), input_event, &swallow_next_mouse_up_);
903 
904   if (handled) {
905     ScheduleUpdate();
906     return WebInputEventResult::kHandledSuppressed;
907   }
908 
909   if (inspect_tool_->ForwardEventsToOverlay()) {
910     WebInputEventResult result = HandleInputEventInOverlay(input_event);
911     if (result != WebInputEventResult::kNotHandled) {
912       ScheduleUpdate();
913       return result;
914     }
915   }
916 
917   // Exit tool upon unhandled Esc.
918   if (input_event.GetType() == WebInputEvent::Type::kRawKeyDown) {
919     const WebKeyboardEvent& keyboard_event =
920         static_cast<const WebKeyboardEvent&>(input_event);
921     if (keyboard_event.windows_key_code == VKEY_ESCAPE) {
922       GetFrontend()->inspectModeCanceled();
923       return WebInputEventResult::kNotHandled;
924     }
925   }
926 
927   if (input_event.GetType() == WebInputEvent::Type::kMouseMove &&
928       inspect_tool_->HideOnMouseMove()) {
929     PickTheRightTool();
930   }
931 
932   return WebInputEventResult::kNotHandled;
933 }
934 
HandleInputEventInOverlay(const WebInputEvent & input_event)935 WebInputEventResult InspectorOverlayAgent::HandleInputEventInOverlay(
936     const WebInputEvent& input_event) {
937   if (input_event.GetType() == WebInputEvent::Type::kGestureTap) {
938     return OverlayMainFrame()->GetEventHandler().HandleGestureEvent(
939         static_cast<const WebGestureEvent&>(input_event));
940   }
941 
942   if (WebInputEvent::IsMouseEventType(input_event.GetType())) {
943     WebMouseEvent mouse_event = static_cast<const WebMouseEvent&>(input_event);
944     if (mouse_event.GetType() == WebInputEvent::Type::kMouseMove) {
945       return OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent(
946           mouse_event, {}, {});
947     }
948     if (mouse_event.GetType() == WebInputEvent::Type::kMouseDown) {
949       return OverlayMainFrame()->GetEventHandler().HandleMousePressEvent(
950           mouse_event);
951     }
952     if (mouse_event.GetType() == WebInputEvent::Type::kMouseUp) {
953       return OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent(
954           mouse_event);
955     }
956     return WebInputEventResult::kNotHandled;
957   }
958 
959   if (WebInputEvent::IsPointerEventType(input_event.GetType())) {
960     return OverlayMainFrame()->GetEventHandler().HandlePointerEvent(
961         static_cast<const WebPointerEvent&>(input_event),
962         Vector<WebPointerEvent>(), Vector<WebPointerEvent>());
963   }
964 
965   if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) {
966     return OverlayMainFrame()->GetEventHandler().KeyEvent(
967         static_cast<const WebKeyboardEvent&>(input_event));
968   }
969 
970   if (input_event.GetType() == WebInputEvent::Type::kMouseWheel) {
971     return OverlayMainFrame()->GetEventHandler().HandleWheelEvent(
972         static_cast<const WebMouseWheelEvent&>(input_event));
973   }
974 
975   return WebInputEventResult::kNotHandled;
976 }
977 
ScheduleUpdate()978 void InspectorOverlayAgent::ScheduleUpdate() {
979   if (IsVisible()) {
980     GetFrame()->GetPage()->GetChromeClient().ScheduleAnimation(
981         GetFrame()->View());
982   }
983 }
984 
PaintOverlayPage()985 void InspectorOverlayAgent::PaintOverlayPage() {
986   DCHECK(overlay_page_);
987 
988   LocalFrameView* view = frame_impl_->GetFrameView();
989   LocalFrame* frame = GetFrame();
990   if (!view || !frame)
991     return;
992 
993   LocalFrame* overlay_frame = OverlayMainFrame();
994   // To make overlay render the same size text with any emulation scale,
995   // compensate the emulation scale using page scale.
996   float emulation_scale =
997       frame->GetPage()->GetChromeClient().InputEventsScaleForEmulation();
998   IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size();
999   viewport_size.Scale(emulation_scale);
1000   overlay_page_->GetVisualViewport().SetSize(viewport_size);
1001   overlay_page_->SetDefaultPageScaleLimits(1 / emulation_scale,
1002                                            1 / emulation_scale);
1003   overlay_page_->GetVisualViewport().SetScale(1 / emulation_scale);
1004   overlay_frame->SetPageZoomFactor(WindowToViewportScale());
1005   overlay_frame->View()->Resize(viewport_size);
1006 
1007   Reset(viewport_size);
1008 
1009   float scale = WindowToViewportScale();
1010 
1011   if (inspect_tool_) {
1012     inspect_tool_->Draw(scale);
1013     if (persistent_tool_ && inspect_tool_->SupportsPersistentOverlays())
1014       persistent_tool_->Draw(scale);
1015   }
1016 
1017   if (hinge_)
1018     hinge_->Draw(scale);
1019 
1020   OverlayMainFrame()->View()->UpdateAllLifecyclePhases(
1021       DocumentUpdateReason::kInspector);
1022 }
1023 
BuildObjectForSize(const IntSize & size)1024 static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize(
1025     const IntSize& size) {
1026   std::unique_ptr<protocol::DictionaryValue> result =
1027       protocol::DictionaryValue::create();
1028   result->setInteger("width", size.Width());
1029   result->setInteger("height", size.Height());
1030   return result;
1031 }
1032 
WindowToViewportScale() const1033 float InspectorOverlayAgent::WindowToViewportScale() const {
1034   LocalFrame* frame = GetFrame();
1035   if (!frame)
1036     return 1.0f;
1037   return frame->GetPage()->GetChromeClient().WindowToViewportScalar(frame,
1038                                                                     1.0f);
1039 }
1040 
LoadOverlayPageResource()1041 void InspectorOverlayAgent::LoadOverlayPageResource() {
1042   if (overlay_page_)
1043     return;
1044 
1045   ScriptForbiddenScope::AllowUserAgentScript allow_script;
1046 
1047   Page::PageClients page_clients;
1048   FillWithEmptyClients(page_clients);
1049   DCHECK(!overlay_chrome_client_);
1050   overlay_chrome_client_ = MakeGarbageCollected<InspectorOverlayChromeClient>(
1051       GetFrame()->GetPage()->GetChromeClient(), *this);
1052   page_clients.chrome_client = overlay_chrome_client_.Get();
1053   overlay_page_ = Page::CreateNonOrdinary(page_clients);
1054   overlay_host_ = MakeGarbageCollected<InspectorOverlayHost>(this);
1055 
1056   Settings& settings = GetFrame()->GetPage()->GetSettings();
1057   Settings& overlay_settings = overlay_page_->GetSettings();
1058 
1059   overlay_settings.GetGenericFontFamilySettings().UpdateStandard(
1060       settings.GetGenericFontFamilySettings().Standard());
1061   overlay_settings.GetGenericFontFamilySettings().UpdateFixed(
1062       settings.GetGenericFontFamilySettings().Fixed());
1063   overlay_settings.GetGenericFontFamilySettings().UpdateSerif(
1064       settings.GetGenericFontFamilySettings().Serif());
1065   overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif(
1066       settings.GetGenericFontFamilySettings().SansSerif());
1067   overlay_settings.GetGenericFontFamilySettings().UpdateCursive(
1068       settings.GetGenericFontFamilySettings().Cursive());
1069   overlay_settings.GetGenericFontFamilySettings().UpdateFantasy(
1070       settings.GetGenericFontFamilySettings().Fantasy());
1071   overlay_settings.GetGenericFontFamilySettings().UpdatePictograph(
1072       settings.GetGenericFontFamilySettings().Pictograph());
1073   overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize());
1074   overlay_settings.SetMinimumLogicalFontSize(
1075       settings.GetMinimumLogicalFontSize());
1076   overlay_settings.SetScriptEnabled(true);
1077   overlay_settings.SetPluginsEnabled(false);
1078   overlay_settings.SetLoadsImagesAutomatically(true);
1079 
1080   DEFINE_STATIC_LOCAL(Persistent<LocalFrameClient>, dummy_local_frame_client,
1081                       (MakeGarbageCollected<EmptyLocalFrameClient>()));
1082   auto* frame = MakeGarbageCollected<LocalFrame>(
1083       dummy_local_frame_client, *overlay_page_, nullptr, nullptr, nullptr,
1084       FrameInsertType::kInsertInConstructor, base::UnguessableToken::Create(),
1085       nullptr, nullptr, /* policy_container */ nullptr);
1086   frame->SetView(MakeGarbageCollected<LocalFrameView>(*frame));
1087   frame->Init(nullptr);
1088   frame->View()->SetCanHaveScrollbars(false);
1089   frame->View()->SetBaseBackgroundColor(Color::kTransparent);
1090 
1091   scoped_refptr<SharedBuffer> data = SharedBuffer::Create();
1092 
1093   data->Append("<script>", static_cast<size_t>(8));
1094   data->Append(UncompressResourceAsBinary(IDR_INSPECT_TOOL_MAIN_JS));
1095   data->Append("</script>", static_cast<size_t>(9));
1096 
1097   frame->ForceSynchronousDocumentInstall("text/html", data);
1098 
1099   v8::Isolate* isolate = ToIsolate(frame);
1100   ScriptState* script_state = ToScriptStateForMainWorld(frame);
1101   DCHECK(script_state);
1102   ScriptState::Scope scope(script_state);
1103   v8::Local<v8::Object> global = script_state->GetContext()->Global();
1104   v8::Local<v8::Value> overlay_host_obj =
1105       ToV8(overlay_host_.Get(), global, isolate);
1106   DCHECK(!overlay_host_obj.IsEmpty());
1107   global
1108       ->Set(script_state->GetContext(),
1109             V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj)
1110       .ToChecked();
1111 
1112 #if defined(OS_WIN)
1113   EvaluateInOverlay("setPlatform", "windows");
1114 #elif defined(OS_MAC)
1115   EvaluateInOverlay("setPlatform", "mac");
1116 #elif defined(OS_POSIX)
1117   EvaluateInOverlay("setPlatform", "linux");
1118 #else
1119   EvaluateInOverlay("setPlatform", "other");
1120 #endif
1121 }
1122 
OverlayMainFrame()1123 LocalFrame* InspectorOverlayAgent::OverlayMainFrame() {
1124   DCHECK(overlay_page_);
1125   return To<LocalFrame>(overlay_page_->MainFrame());
1126 }
1127 
Reset(const IntSize & viewport_size)1128 void InspectorOverlayAgent::Reset(const IntSize& viewport_size) {
1129   std::unique_ptr<protocol::DictionaryValue> reset_data =
1130       protocol::DictionaryValue::create();
1131   reset_data->setDouble("deviceScaleFactor",
1132                         GetFrame()->GetPage()->DeviceScaleFactorDeprecated());
1133   reset_data->setDouble(
1134       "emulationScaleFactor",
1135       GetFrame()->GetPage()->GetChromeClient().InputEventsScaleForEmulation());
1136   reset_data->setDouble("pageScaleFactor",
1137                         GetFrame()->GetPage()->GetVisualViewport().Scale());
1138 
1139   IntRect viewport_in_screen =
1140       GetFrame()->GetPage()->GetChromeClient().ViewportToScreen(
1141           IntRect(IntPoint(), viewport_size), GetFrame()->View());
1142   reset_data->setObject("viewportSize",
1143                         BuildObjectForSize(viewport_in_screen.Size()));
1144 
1145   // The zoom factor in the overlay frame already has been multiplied by the
1146   // window to viewport scale (aka device scale factor), so cancel it.
1147   reset_data->setDouble("pageZoomFactor",
1148                         GetFrame()->PageZoomFactor() / WindowToViewportScale());
1149 
1150   // TODO(szager): These values have been zero since root layer scrolling
1151   // landed. Probably they should be derived from
1152   // LocalFrameView::LayoutViewport(); but I have no idea who the consumers
1153   // of these values are, so I'm leaving them zero pending investigation.
1154   reset_data->setInteger("scrollX", 0);
1155   reset_data->setInteger("scrollY", 0);
1156   EvaluateInOverlay("reset", std::move(reset_data));
1157 }
1158 
EvaluateInOverlay(const String & method,const String & argument)1159 void InspectorOverlayAgent::EvaluateInOverlay(const String& method,
1160                                               const String& argument) {
1161   ScriptForbiddenScope::AllowUserAgentScript allow_script;
1162   std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
1163   command->pushValue(protocol::StringValue::create(method));
1164   command->pushValue(protocol::StringValue::create(argument));
1165   std::vector<uint8_t> json;
1166   ConvertCBORToJSON(SpanFrom(command->Serialize()), &json);
1167   ClassicScript::CreateUnspecifiedScript(
1168       ScriptSourceCode(
1169           "dispatch(" +
1170               String(reinterpret_cast<const char*>(json.data()), json.size()) +
1171               ")",
1172           ScriptSourceLocationType::kInspector))
1173       ->RunScript(To<LocalFrame>(OverlayMainFrame())->DomWindow(),
1174                   ScriptController::kExecuteScriptWhenScriptsDisabled);
1175 }
1176 
EvaluateInOverlay(const String & method,std::unique_ptr<protocol::Value> argument)1177 void InspectorOverlayAgent::EvaluateInOverlay(
1178     const String& method,
1179     std::unique_ptr<protocol::Value> argument) {
1180   ScriptForbiddenScope::AllowUserAgentScript allow_script;
1181   std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create();
1182   command->pushValue(protocol::StringValue::create(method));
1183   command->pushValue(std::move(argument));
1184   std::vector<uint8_t> json;
1185   ConvertCBORToJSON(SpanFrom(command->Serialize()), &json);
1186   ClassicScript::CreateUnspecifiedScript(
1187       ScriptSourceCode(
1188           "dispatch(" +
1189               String(reinterpret_cast<const char*>(json.data()), json.size()) +
1190               ")",
1191           ScriptSourceLocationType::kInspector))
1192       ->RunScript(To<LocalFrame>(OverlayMainFrame())->DomWindow(),
1193                   ScriptController::kExecuteScriptWhenScriptsDisabled);
1194 }
1195 
EvaluateInOverlayForTest(const String & script)1196 String InspectorOverlayAgent::EvaluateInOverlayForTest(const String& script) {
1197   ScriptForbiddenScope::AllowUserAgentScript allow_script;
1198   v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame()));
1199   v8::Local<v8::Value> string =
1200       ClassicScript::CreateUnspecifiedScript(
1201           ScriptSourceCode(script, ScriptSourceLocationType::kInspector))
1202           ->RunScriptAndReturnValue(
1203               To<LocalFrame>(OverlayMainFrame())->DomWindow(),
1204               ScriptController::kExecuteScriptWhenScriptsDisabled);
1205   return ToCoreStringWithUndefinedOrNullCheck(string);
1206 }
1207 
OnResizeTimer(TimerBase *)1208 void InspectorOverlayAgent::OnResizeTimer(TimerBase*) {
1209   if (resize_timer_active_) {
1210     // Restore the original tool.
1211     PickTheRightTool();
1212     return;
1213   }
1214 
1215   // Show the resize tool.
1216   SetInspectTool(MakeGarbageCollected<ShowViewSizeTool>(this, GetFrontend()));
1217   resize_timer_active_ = true;
1218   resize_timer_.Stop();
1219   resize_timer_.StartOneShot(base::TimeDelta::FromSeconds(1), FROM_HERE);
1220 }
1221 
Dispatch(const String & message)1222 void InspectorOverlayAgent::Dispatch(const String& message) {
1223   inspect_tool_->Dispatch(message);
1224 }
1225 
PageLayoutInvalidated(bool resized)1226 void InspectorOverlayAgent::PageLayoutInvalidated(bool resized) {
1227   if (resized && show_size_on_resize_.Get()) {
1228     resize_timer_active_ = false;
1229     // Handle the resize in the next cycle to decouple overlay page rebuild from
1230     // the main page layout to avoid document lifecycle issues caused by
1231     // Microtask::PerformCheckpoint() called when we rebuild the overlay page.
1232     resize_timer_.Stop();
1233     resize_timer_.StartOneShot(base::TimeDelta::FromSeconds(0), FROM_HERE);
1234     return;
1235   }
1236   ScheduleUpdate();
1237 }
1238 
CompositingEnabled()1239 Response InspectorOverlayAgent::CompositingEnabled() {
1240   bool main_frame = frame_impl_->ViewImpl() && !frame_impl_->Parent();
1241   if (!main_frame || !frame_impl_->ViewImpl()
1242                           ->GetPage()
1243                           ->GetSettings()
1244                           .GetAcceleratedCompositingEnabled())
1245     return Response::ServerError("Compositing mode is not supported");
1246   return Response::Success();
1247 }
1248 
InSomeInspectMode()1249 bool InspectorOverlayAgent::InSomeInspectMode() {
1250   return inspect_mode_.Get() != protocol::Overlay::InspectModeEnum::None;
1251 }
1252 
Inspect(Node * inspected_node)1253 void InspectorOverlayAgent::Inspect(Node* inspected_node) {
1254   if (!inspected_node)
1255     return;
1256 
1257   Node* node = inspected_node;
1258   while (node && !node->IsElementNode() && !node->IsDocumentNode() &&
1259          !node->IsDocumentFragment())
1260     node = node->ParentOrShadowHostNode();
1261   if (!node)
1262     return;
1263 
1264   DOMNodeId backend_node_id = DOMNodeIds::IdForNode(node);
1265   if (!enabled_.Get()) {
1266     backend_node_id_to_inspect_ = backend_node_id;
1267     return;
1268   }
1269 
1270   GetFrontend()->inspectNodeRequested(IdentifiersFactory::IntIdForNode(node));
1271 }
1272 
setInspectMode(const String & mode,Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object)1273 Response InspectorOverlayAgent::setInspectMode(
1274     const String& mode,
1275     Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object) {
1276   if (mode != protocol::Overlay::InspectModeEnum::None &&
1277       mode != protocol::Overlay::InspectModeEnum::SearchForNode &&
1278       mode != protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM &&
1279       mode != protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot &&
1280       mode != protocol::Overlay::InspectModeEnum::ShowDistances) {
1281     return Response::ServerError(
1282         String("Unknown mode \"" + mode + "\" was provided.").Utf8());
1283   }
1284 
1285   std::vector<uint8_t> serialized_config;
1286   if (highlight_inspector_object.isJust()) {
1287     highlight_inspector_object.fromJust()->AppendSerialized(&serialized_config);
1288   }
1289   std::unique_ptr<InspectorHighlightConfig> config;
1290   Response response = HighlightConfigFromInspectorObject(
1291       std::move(highlight_inspector_object), &config);
1292   if (!response.IsSuccess())
1293     return response;
1294   inspect_mode_.Set(mode);
1295   inspect_mode_protocol_config_.Set(serialized_config);
1296   PickTheRightTool();
1297   return Response::Success();
1298 }
1299 
PickTheRightTool()1300 void InspectorOverlayAgent::PickTheRightTool() {
1301   InspectTool* inspect_tool = nullptr;
1302 
1303   String inspect_mode = inspect_mode_.Get();
1304   if (inspect_mode == protocol::Overlay::InspectModeEnum::SearchForNode ||
1305       inspect_mode ==
1306           protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM) {
1307     inspect_tool = MakeGarbageCollected<SearchingForNodeTool>(
1308         this, GetFrontend(), dom_agent_,
1309         inspect_mode ==
1310             protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM,
1311         inspect_mode_protocol_config_.Get());
1312   } else if (inspect_mode ==
1313              protocol::Overlay::InspectModeEnum::CaptureAreaScreenshot) {
1314     inspect_tool = MakeGarbageCollected<ScreenshotTool>(this, GetFrontend());
1315   } else if (inspect_mode ==
1316              protocol::Overlay::InspectModeEnum::ShowDistances) {
1317     inspect_tool =
1318         MakeGarbageCollected<NearbyDistanceTool>(this, GetFrontend());
1319   } else if (!paused_in_debugger_message_.Get().IsNull()) {
1320     inspect_tool = MakeGarbageCollected<PausedInDebuggerTool>(
1321         this, GetFrontend(), v8_session_, paused_in_debugger_message_.Get());
1322   } else if (persistent_tool_) {
1323     inspect_tool = persistent_tool_;
1324   }
1325 
1326   SetInspectTool(inspect_tool);
1327 }
1328 
DisableFrameOverlay()1329 void InspectorOverlayAgent::DisableFrameOverlay() {
1330   if (IsVisible() || !frame_overlay_)
1331     return;
1332 
1333   frame_overlay_.reset();
1334   auto& client = GetFrame()->GetPage()->GetChromeClient();
1335   client.SetCursorOverridden(false);
1336   client.SetCursor(PointerCursor(), GetFrame());
1337 
1338   if (auto* frame_view = frame_impl_->GetFrameView())
1339     frame_view->SetPaintArtifactCompositorNeedsUpdate();
1340 }
1341 
EnsureEnableFrameOverlay()1342 void InspectorOverlayAgent::EnsureEnableFrameOverlay() {
1343   if (frame_overlay_)
1344     return;
1345 
1346   frame_overlay_ = std::make_unique<FrameOverlay>(
1347       GetFrame(), std::make_unique<InspectorPageOverlayDelegate>(*this));
1348 }
1349 
ClearInspectTool()1350 void InspectorOverlayAgent::ClearInspectTool() {
1351   inspect_tool_ = nullptr;
1352   if (!hinge_)
1353     DisableFrameOverlay();
1354 }
1355 
SetInspectTool(InspectTool * inspect_tool)1356 Response InspectorOverlayAgent::SetInspectTool(InspectTool* inspect_tool) {
1357   ClearInspectTool();
1358 
1359   if (!inspect_tool)
1360     return Response::Success();
1361 
1362   if (!enabled_.Get()) {
1363     return Response::InvalidRequest(
1364         "Overlay must be enabled before a tool can be shown");
1365   }
1366 
1367   LocalFrameView* view = frame_impl_->GetFrameView();
1368   LocalFrame* frame = GetFrame();
1369   if (!view || !frame)
1370     return Response::InternalError();
1371 
1372   inspect_tool_ = inspect_tool;
1373   // If the tool supports persistent overlays, the resources of the persistent
1374   // tool will be included into the JS resource.
1375   LoadOverlayPageResource();
1376   EvaluateInOverlay("setOverlay", inspect_tool->GetOverlayName());
1377   EnsureEnableFrameOverlay();
1378   ScheduleUpdate();
1379   return Response::Success();
1380 }
1381 
1382 InspectorSourceOrderConfig
SourceOrderConfigFromInspectorObject(std::unique_ptr<protocol::Overlay::SourceOrderConfig> source_order_inspector_object)1383 InspectorOverlayAgent::SourceOrderConfigFromInspectorObject(
1384     std::unique_ptr<protocol::Overlay::SourceOrderConfig>
1385         source_order_inspector_object) {
1386   InspectorSourceOrderConfig source_order_config = InspectorSourceOrderConfig();
1387   source_order_config.parent_outline_color = InspectorDOMAgent::ParseColor(
1388       source_order_inspector_object->getParentOutlineColor());
1389   source_order_config.child_outline_color = InspectorDOMAgent::ParseColor(
1390       source_order_inspector_object->getChildOutlineColor());
1391 
1392   return source_order_config;
1393 }
1394 
HighlightConfigFromInspectorObject(Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object,std::unique_ptr<InspectorHighlightConfig> * out_config)1395 Response InspectorOverlayAgent::HighlightConfigFromInspectorObject(
1396     Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object,
1397     std::unique_ptr<InspectorHighlightConfig>* out_config) {
1398   if (!highlight_inspector_object.isJust()) {
1399     return Response::ServerError(
1400         "Internal error: highlight configuration parameter is missing");
1401   }
1402   protocol::Overlay::HighlightConfig* config =
1403       highlight_inspector_object.fromJust();
1404 
1405   namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
1406 
1407   String format = config->getColorFormat("hex");
1408 
1409   if (format != ColorFormatEnum::Rgb && format != ColorFormatEnum::Hex &&
1410       format != ColorFormatEnum::Hsl) {
1411     return Response::InvalidParams("Unknown color format");
1412   }
1413 
1414   *out_config = InspectorOverlayAgent::ToHighlightConfig(config);
1415   return Response::Success();
1416 }
1417 
1418 // static
1419 std::unique_ptr<InspectorGridHighlightConfig>
ToGridHighlightConfig(protocol::Overlay::GridHighlightConfig * config)1420 InspectorOverlayAgent::ToGridHighlightConfig(
1421     protocol::Overlay::GridHighlightConfig* config) {
1422   if (!config) {
1423     return nullptr;
1424   }
1425   std::unique_ptr<InspectorGridHighlightConfig> highlight_config =
1426       std::make_unique<InspectorGridHighlightConfig>();
1427   highlight_config->show_positive_line_numbers =
1428       config->getShowPositiveLineNumbers(false);
1429   highlight_config->show_negative_line_numbers =
1430       config->getShowNegativeLineNumbers(false);
1431   highlight_config->show_area_names = config->getShowAreaNames(false);
1432   highlight_config->show_line_names = config->getShowLineNames(false);
1433   highlight_config->show_grid_extension_lines =
1434       config->getShowGridExtensionLines(false);
1435   highlight_config->grid_border_dash = config->getGridBorderDash(false);
1436 
1437   // cellBorderDash is deprecated. We only use it if defined and none of the new
1438   // properties are.
1439   bool hasLegacyBorderDash = !config->hasRowLineDash() &&
1440                              !config->hasColumnLineDash() &&
1441                              config->hasCellBorderDash();
1442   highlight_config->row_line_dash = hasLegacyBorderDash
1443                                         ? config->getCellBorderDash(false)
1444                                         : config->getRowLineDash(false);
1445   highlight_config->column_line_dash = hasLegacyBorderDash
1446                                            ? config->getCellBorderDash(false)
1447                                            : config->getColumnLineDash(false);
1448 
1449   highlight_config->show_track_sizes = config->getShowTrackSizes(false);
1450   highlight_config->grid_color =
1451       InspectorDOMAgent::ParseColor(config->getGridBorderColor(nullptr));
1452 
1453   // cellBorderColor is deprecated. We only use it if defined and none of the
1454   // new properties are.
1455   bool hasLegacyBorderColors = !config->hasRowLineColor() &&
1456                                !config->hasColumnLineColor() &&
1457                                config->hasCellBorderColor();
1458   highlight_config->row_line_color =
1459       hasLegacyBorderColors
1460           ? InspectorDOMAgent::ParseColor(config->getCellBorderColor(nullptr))
1461           : InspectorDOMAgent::ParseColor(config->getRowLineColor(nullptr));
1462   highlight_config->column_line_color =
1463       hasLegacyBorderColors
1464           ? InspectorDOMAgent::ParseColor(config->getCellBorderColor(nullptr))
1465           : InspectorDOMAgent::ParseColor(config->getColumnLineColor(nullptr));
1466 
1467   highlight_config->row_gap_color =
1468       InspectorDOMAgent::ParseColor(config->getRowGapColor(nullptr));
1469   highlight_config->column_gap_color =
1470       InspectorDOMAgent::ParseColor(config->getColumnGapColor(nullptr));
1471   highlight_config->row_hatch_color =
1472       InspectorDOMAgent::ParseColor(config->getRowHatchColor(nullptr));
1473   highlight_config->column_hatch_color =
1474       InspectorDOMAgent::ParseColor(config->getColumnHatchColor(nullptr));
1475   highlight_config->area_border_color =
1476       InspectorDOMAgent::ParseColor(config->getAreaBorderColor(nullptr));
1477   highlight_config->grid_background_color =
1478       InspectorDOMAgent::ParseColor(config->getGridBackgroundColor(nullptr));
1479   return highlight_config;
1480 }
1481 
1482 // static
1483 std::unique_ptr<InspectorFlexContainerHighlightConfig>
ToFlexContainerHighlightConfig(protocol::Overlay::FlexContainerHighlightConfig * config)1484 InspectorOverlayAgent::ToFlexContainerHighlightConfig(
1485     protocol::Overlay::FlexContainerHighlightConfig* config) {
1486   if (!config) {
1487     return nullptr;
1488   }
1489   std::unique_ptr<InspectorFlexContainerHighlightConfig> highlight_config =
1490       std::make_unique<InspectorFlexContainerHighlightConfig>();
1491   highlight_config->container_border =
1492       InspectorOverlayAgent::ToLineStyle(config->getContainerBorder(nullptr));
1493   highlight_config->line_separator =
1494       InspectorOverlayAgent::ToLineStyle(config->getLineSeparator(nullptr));
1495   highlight_config->item_separator =
1496       InspectorOverlayAgent::ToLineStyle(config->getItemSeparator(nullptr));
1497 
1498   return highlight_config;
1499 }
1500 
1501 // static
ToLineStyle(protocol::Overlay::LineStyle * config)1502 std::unique_ptr<LineStyle> InspectorOverlayAgent::ToLineStyle(
1503     protocol::Overlay::LineStyle* config) {
1504   if (!config) {
1505     return nullptr;
1506   }
1507   std::unique_ptr<LineStyle> line_style = std::make_unique<LineStyle>();
1508   line_style->color = InspectorDOMAgent::ParseColor(config->getColor(nullptr));
1509   line_style->pattern = config->getPattern("solid");
1510 
1511   return line_style;
1512 }
1513 
1514 // static
1515 std::unique_ptr<InspectorHighlightConfig>
ToHighlightConfig(protocol::Overlay::HighlightConfig * config)1516 InspectorOverlayAgent::ToHighlightConfig(
1517     protocol::Overlay::HighlightConfig* config) {
1518   std::unique_ptr<InspectorHighlightConfig> highlight_config =
1519       std::make_unique<InspectorHighlightConfig>();
1520   highlight_config->show_info = config->getShowInfo(false);
1521   highlight_config->show_accessibility_info =
1522       config->getShowAccessibilityInfo(true);
1523   highlight_config->show_styles = config->getShowStyles(false);
1524   highlight_config->show_rulers = config->getShowRulers(false);
1525   highlight_config->show_extension_lines = config->getShowExtensionLines(false);
1526   highlight_config->content =
1527       InspectorDOMAgent::ParseColor(config->getContentColor(nullptr));
1528   highlight_config->padding =
1529       InspectorDOMAgent::ParseColor(config->getPaddingColor(nullptr));
1530   highlight_config->border =
1531       InspectorDOMAgent::ParseColor(config->getBorderColor(nullptr));
1532   highlight_config->margin =
1533       InspectorDOMAgent::ParseColor(config->getMarginColor(nullptr));
1534   highlight_config->event_target =
1535       InspectorDOMAgent::ParseColor(config->getEventTargetColor(nullptr));
1536   highlight_config->shape =
1537       InspectorDOMAgent::ParseColor(config->getShapeColor(nullptr));
1538   highlight_config->shape_margin =
1539       InspectorDOMAgent::ParseColor(config->getShapeMarginColor(nullptr));
1540   highlight_config->css_grid =
1541       InspectorDOMAgent::ParseColor(config->getCssGridColor(nullptr));
1542 
1543   namespace ColorFormatEnum = protocol::Overlay::ColorFormatEnum;
1544 
1545   String format = config->getColorFormat("hex");
1546 
1547   if (format == ColorFormatEnum::Hsl) {
1548     highlight_config->color_format = ColorFormat::HSL;
1549   } else if (format == ColorFormatEnum::Rgb) {
1550     highlight_config->color_format = ColorFormat::RGB;
1551   } else {
1552     highlight_config->color_format = ColorFormat::HEX;
1553   }
1554 
1555   highlight_config->grid_highlight_config =
1556       InspectorOverlayAgent::ToGridHighlightConfig(
1557           config->getGridHighlightConfig(nullptr));
1558 
1559   highlight_config->flex_container_highlight_config =
1560       InspectorOverlayAgent::ToFlexContainerHighlightConfig(
1561           config->getFlexContainerHighlightConfig(nullptr));
1562   return highlight_config;
1563 }
1564 
SetNeedsUnbufferedInput(bool unbuffered)1565 void InspectorOverlayAgent::SetNeedsUnbufferedInput(bool unbuffered) {
1566   LocalFrame* frame = GetFrame();
1567   if (frame) {
1568     frame->GetPage()->GetChromeClient().SetNeedsUnbufferedInputForDebugger(
1569         frame, unbuffered);
1570   }
1571 }
1572 
1573 }  // namespace blink
1574