OLD | NEW |
| (Empty) |
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 "web/InspectorOverlayAgent.h" | |
30 | |
31 #include <memory> | |
32 | |
33 #include "bindings/core/v8/ScriptController.h" | |
34 #include "bindings/core/v8/ScriptSourceCode.h" | |
35 #include "bindings/core/v8/V8Binding.h" | |
36 #include "bindings/core/v8/V8InspectorOverlayHost.h" | |
37 #include "core/dom/DOMNodeIds.h" | |
38 #include "core/dom/Node.h" | |
39 #include "core/dom/StaticNodeList.h" | |
40 #include "core/dom/TaskRunnerHelper.h" | |
41 #include "core/frame/FrameView.h" | |
42 #include "core/frame/LocalFrame.h" | |
43 #include "core/frame/LocalFrameClient.h" | |
44 #include "core/frame/Settings.h" | |
45 #include "core/frame/VisualViewport.h" | |
46 #include "core/html/HTMLFrameOwnerElement.h" | |
47 #include "core/input/EventHandler.h" | |
48 #include "core/inspector/IdentifiersFactory.h" | |
49 #include "core/inspector/InspectedFrames.h" | |
50 #include "core/inspector/InspectorDOMAgent.h" | |
51 #include "core/inspector/InspectorOverlayHost.h" | |
52 #include "core/layout/api/LayoutViewItem.h" | |
53 #include "core/loader/EmptyClients.h" | |
54 #include "core/loader/FrameLoadRequest.h" | |
55 #include "core/page/ChromeClient.h" | |
56 #include "core/page/Page.h" | |
57 #include "platform/ScriptForbiddenScope.h" | |
58 #include "platform/graphics/Color.h" | |
59 #include "platform/graphics/GraphicsContext.h" | |
60 #include "platform/graphics/paint/CullRect.h" | |
61 #include "platform/wtf/AutoReset.h" | |
62 #include "public/platform/Platform.h" | |
63 #include "public/platform/WebData.h" | |
64 #include "v8/include/v8.h" | |
65 #include "web/ChromeClientImpl.h" | |
66 #include "web/PageOverlay.h" | |
67 #include "web/WebInputEventConversion.h" | |
68 #include "web/WebLocalFrameImpl.h" | |
69 #include "web/WebViewImpl.h" | |
70 | |
71 namespace blink { | |
72 | |
73 using protocol::Maybe; | |
74 using protocol::Response; | |
75 | |
76 namespace { | |
77 | |
78 namespace OverlayAgentState { | |
79 static const char kEnabled[] = "enabled"; | |
80 static const char kShowDebugBorders[] = "showDebugBorders"; | |
81 static const char kShowFPSCounter[] = "showFPSCounter"; | |
82 static const char kShowPaintRects[] = "showPaintRects"; | |
83 static const char kShowScrollBottleneckRects[] = "showScrollBottleneckRects"; | |
84 static const char kShowSizeOnResize[] = "showSizeOnResize"; | |
85 static const char kSuspended[] = "suspended"; | |
86 static const char kPausedInDebuggerMessage[] = "pausedInDebuggerMessage"; | |
87 } | |
88 | |
89 Node* HoveredNodeForPoint(LocalFrame* frame, | |
90 const IntPoint& point_in_root_frame, | |
91 bool ignore_pointer_events_none) { | |
92 HitTestRequest::HitTestRequestType hit_type = | |
93 HitTestRequest::kMove | HitTestRequest::kReadOnly | | |
94 HitTestRequest::kAllowChildFrameContent; | |
95 if (ignore_pointer_events_none) | |
96 hit_type |= HitTestRequest::kIgnorePointerEventsNone; | |
97 HitTestRequest request(hit_type); | |
98 HitTestResult result(request, | |
99 frame->View()->RootFrameToContents(point_in_root_frame)); | |
100 frame->ContentLayoutItem().HitTest(result); | |
101 Node* node = result.InnerPossiblyPseudoNode(); | |
102 while (node && node->getNodeType() == Node::kTextNode) | |
103 node = node->parentNode(); | |
104 return node; | |
105 } | |
106 | |
107 Node* HoveredNodeForEvent(LocalFrame* frame, | |
108 const WebGestureEvent& event, | |
109 bool ignore_pointer_events_none) { | |
110 return HoveredNodeForPoint(frame, | |
111 RoundedIntPoint(event.PositionInRootFrame()), | |
112 ignore_pointer_events_none); | |
113 } | |
114 | |
115 Node* HoveredNodeForEvent(LocalFrame* frame, | |
116 const WebMouseEvent& event, | |
117 bool ignore_pointer_events_none) { | |
118 return HoveredNodeForPoint(frame, | |
119 RoundedIntPoint(event.PositionInRootFrame()), | |
120 ignore_pointer_events_none); | |
121 } | |
122 | |
123 Node* HoveredNodeForEvent(LocalFrame* frame, | |
124 const WebTouchEvent& event, | |
125 bool ignore_pointer_events_none) { | |
126 if (!event.touches_length) | |
127 return nullptr; | |
128 WebTouchPoint transformed_point = event.TouchPointInRootFrame(0); | |
129 return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position), | |
130 ignore_pointer_events_none); | |
131 } | |
132 | |
133 bool ParseQuad(std::unique_ptr<protocol::Array<double>> quad_array, | |
134 FloatQuad* quad) { | |
135 const size_t kCoordinatesInQuad = 8; | |
136 if (!quad_array || quad_array->length() != kCoordinatesInQuad) | |
137 return false; | |
138 quad->SetP1(FloatPoint(quad_array->get(0), quad_array->get(1))); | |
139 quad->SetP2(FloatPoint(quad_array->get(2), quad_array->get(3))); | |
140 quad->SetP3(FloatPoint(quad_array->get(4), quad_array->get(5))); | |
141 quad->SetP4(FloatPoint(quad_array->get(6), quad_array->get(7))); | |
142 return true; | |
143 } | |
144 | |
145 } // namespace | |
146 | |
147 class InspectorOverlayAgent::InspectorPageOverlayDelegate final | |
148 : public PageOverlay::Delegate { | |
149 public: | |
150 explicit InspectorPageOverlayDelegate(InspectorOverlayAgent& overlay) | |
151 : overlay_(&overlay) {} | |
152 | |
153 void PaintPageOverlay(const PageOverlay&, | |
154 GraphicsContext& graphics_context, | |
155 const WebSize& web_view_size) const override { | |
156 if (overlay_->IsEmpty()) | |
157 return; | |
158 | |
159 FrameView* view = overlay_->OverlayMainFrame()->View(); | |
160 DCHECK(!view->NeedsLayout()); | |
161 view->Paint(graphics_context, | |
162 CullRect(IntRect(0, 0, view->Width(), view->Height()))); | |
163 } | |
164 | |
165 private: | |
166 Persistent<InspectorOverlayAgent> overlay_; | |
167 }; | |
168 | |
169 class InspectorOverlayAgent::InspectorOverlayChromeClient final | |
170 : public EmptyChromeClient { | |
171 public: | |
172 static InspectorOverlayChromeClient* Create(ChromeClient& client, | |
173 InspectorOverlayAgent& overlay) { | |
174 return new InspectorOverlayChromeClient(client, overlay); | |
175 } | |
176 | |
177 DEFINE_INLINE_VIRTUAL_TRACE() { | |
178 visitor->Trace(client_); | |
179 visitor->Trace(overlay_); | |
180 EmptyChromeClient::Trace(visitor); | |
181 } | |
182 | |
183 void SetCursor(const Cursor& cursor, LocalFrame* local_root) override { | |
184 ToChromeClientImpl(client_)->SetCursorOverridden(false); | |
185 ToChromeClientImpl(client_)->SetCursor(cursor, | |
186 overlay_->frame_impl_->GetFrame()); | |
187 ToChromeClientImpl(client_)->SetCursorOverridden(false); | |
188 } | |
189 | |
190 void SetToolTip(LocalFrame& frame, | |
191 const String& tooltip, | |
192 TextDirection direction) override { | |
193 DCHECK_EQ(&frame, overlay_->OverlayMainFrame()); | |
194 client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction); | |
195 } | |
196 | |
197 void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); } | |
198 | |
199 void ScheduleAnimation(LocalFrame* frame) override { | |
200 if (overlay_->in_layout_) | |
201 return; | |
202 | |
203 client_->ScheduleAnimation(frame); | |
204 } | |
205 | |
206 private: | |
207 InspectorOverlayChromeClient(ChromeClient& client, | |
208 InspectorOverlayAgent& overlay) | |
209 : client_(&client), overlay_(&overlay) {} | |
210 | |
211 Member<ChromeClient> client_; | |
212 Member<InspectorOverlayAgent> overlay_; | |
213 }; | |
214 | |
215 InspectorOverlayAgent::InspectorOverlayAgent( | |
216 WebLocalFrameImpl* frame_impl, | |
217 InspectedFrames* inspected_frames, | |
218 v8_inspector::V8InspectorSession* v8_session, | |
219 InspectorDOMAgent* dom_agent) | |
220 : frame_impl_(frame_impl), | |
221 inspected_frames_(inspected_frames), | |
222 enabled_(false), | |
223 overlay_host_(new InspectorOverlayHost(this)), | |
224 draw_view_size_(false), | |
225 resize_timer_active_(false), | |
226 omit_tooltip_(false), | |
227 timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer, | |
228 frame_impl->GetFrame()), | |
229 this, | |
230 &InspectorOverlayAgent::OnTimer), | |
231 suspended_(false), | |
232 show_reloading_blanket_(false), | |
233 in_layout_(false), | |
234 needs_update_(false), | |
235 v8_session_(v8_session), | |
236 dom_agent_(dom_agent), | |
237 swallow_next_mouse_up_(false), | |
238 inspect_mode_(kNotSearching), | |
239 backend_node_id_to_inspect_(0) {} | |
240 | |
241 InspectorOverlayAgent::~InspectorOverlayAgent() { | |
242 DCHECK(!overlay_page_); | |
243 } | |
244 | |
245 DEFINE_TRACE(InspectorOverlayAgent) { | |
246 visitor->Trace(frame_impl_); | |
247 visitor->Trace(inspected_frames_); | |
248 visitor->Trace(highlight_node_); | |
249 visitor->Trace(event_target_node_); | |
250 visitor->Trace(overlay_page_); | |
251 visitor->Trace(overlay_chrome_client_); | |
252 visitor->Trace(overlay_host_); | |
253 visitor->Trace(dom_agent_); | |
254 visitor->Trace(hovered_node_for_inspect_mode_); | |
255 InspectorBaseAgent::Trace(visitor); | |
256 } | |
257 | |
258 void InspectorOverlayAgent::Restore() { | |
259 if (state_->booleanProperty(OverlayAgentState::kEnabled, false)) | |
260 enabled_ = true; | |
261 setShowDebugBorders( | |
262 state_->booleanProperty(OverlayAgentState::kShowDebugBorders, false)); | |
263 setShowFPSCounter( | |
264 state_->booleanProperty(OverlayAgentState::kShowFPSCounter, false)); | |
265 setShowPaintRects( | |
266 state_->booleanProperty(OverlayAgentState::kShowPaintRects, false)); | |
267 setShowScrollBottleneckRects(state_->booleanProperty( | |
268 OverlayAgentState::kShowScrollBottleneckRects, false)); | |
269 setShowViewportSizeOnResize( | |
270 state_->booleanProperty(OverlayAgentState::kShowSizeOnResize, false)); | |
271 String message; | |
272 state_->getString(OverlayAgentState::kPausedInDebuggerMessage, &message); | |
273 setPausedInDebuggerMessage(message); | |
274 setSuspended(state_->booleanProperty(OverlayAgentState::kSuspended, false)); | |
275 } | |
276 | |
277 Response InspectorOverlayAgent::enable() { | |
278 if (!dom_agent_->Enabled()) | |
279 return Response::Error("DOM should be enabled first"); | |
280 state_->setBoolean(OverlayAgentState::kEnabled, true); | |
281 enabled_ = true; | |
282 if (backend_node_id_to_inspect_) | |
283 GetFrontend()->inspectNodeRequested(backend_node_id_to_inspect_); | |
284 backend_node_id_to_inspect_ = 0; | |
285 return Response::OK(); | |
286 } | |
287 | |
288 Response InspectorOverlayAgent::disable() { | |
289 state_->setBoolean(OverlayAgentState::kEnabled, false); | |
290 enabled_ = false; | |
291 setShowDebugBorders(false); | |
292 setShowFPSCounter(false); | |
293 setShowPaintRects(false); | |
294 setShowScrollBottleneckRects(false); | |
295 setShowViewportSizeOnResize(false); | |
296 setPausedInDebuggerMessage(String()); | |
297 setSuspended(false); | |
298 SetSearchingForNode(kNotSearching, | |
299 Maybe<protocol::Overlay::HighlightConfig>()); | |
300 return Response::OK(); | |
301 } | |
302 | |
303 Response InspectorOverlayAgent::setShowDebugBorders(bool show) { | |
304 state_->setBoolean(OverlayAgentState::kShowDebugBorders, show); | |
305 if (show) { | |
306 Response response = CompositingEnabled(); | |
307 if (!response.isSuccess()) | |
308 return response; | |
309 } | |
310 frame_impl_->ViewImpl()->SetShowDebugBorders(show); | |
311 return Response::OK(); | |
312 } | |
313 | |
314 Response InspectorOverlayAgent::setShowFPSCounter(bool show) { | |
315 state_->setBoolean(OverlayAgentState::kShowFPSCounter, show); | |
316 if (show) { | |
317 Response response = CompositingEnabled(); | |
318 if (!response.isSuccess()) | |
319 return response; | |
320 } | |
321 frame_impl_->ViewImpl()->SetShowFPSCounter(show); | |
322 return Response::OK(); | |
323 } | |
324 | |
325 Response InspectorOverlayAgent::setShowPaintRects(bool show) { | |
326 state_->setBoolean(OverlayAgentState::kShowPaintRects, show); | |
327 if (show) { | |
328 Response response = CompositingEnabled(); | |
329 if (!response.isSuccess()) | |
330 return response; | |
331 } | |
332 frame_impl_->ViewImpl()->SetShowPaintRects(show); | |
333 if (!show && frame_impl_->GetFrameView()) | |
334 frame_impl_->GetFrameView()->Invalidate(); | |
335 return Response::OK(); | |
336 } | |
337 | |
338 Response InspectorOverlayAgent::setShowScrollBottleneckRects(bool show) { | |
339 state_->setBoolean(OverlayAgentState::kShowScrollBottleneckRects, show); | |
340 if (show) { | |
341 Response response = CompositingEnabled(); | |
342 if (!response.isSuccess()) | |
343 return response; | |
344 } | |
345 frame_impl_->ViewImpl()->SetShowScrollBottleneckRects(show); | |
346 return Response::OK(); | |
347 } | |
348 | |
349 Response InspectorOverlayAgent::setShowViewportSizeOnResize(bool show) { | |
350 state_->setBoolean(OverlayAgentState::kShowSizeOnResize, show); | |
351 draw_view_size_ = show; | |
352 return Response::OK(); | |
353 } | |
354 | |
355 Response InspectorOverlayAgent::setPausedInDebuggerMessage( | |
356 Maybe<String> message) { | |
357 String just_message = message.fromMaybe(String()); | |
358 state_->setString(OverlayAgentState::kPausedInDebuggerMessage, just_message); | |
359 paused_in_debugger_message_ = just_message; | |
360 ScheduleUpdate(); | |
361 return Response::OK(); | |
362 } | |
363 | |
364 Response InspectorOverlayAgent::setSuspended(bool suspended) { | |
365 state_->setBoolean(OverlayAgentState::kSuspended, suspended); | |
366 if (suspended && !suspended_ && !show_reloading_blanket_) | |
367 ClearInternal(); | |
368 suspended_ = suspended; | |
369 return Response::OK(); | |
370 } | |
371 | |
372 Response InspectorOverlayAgent::setInspectMode( | |
373 const String& mode, | |
374 Maybe<protocol::Overlay::HighlightConfig> highlight_config) { | |
375 SearchMode search_mode; | |
376 if (mode == protocol::Overlay::InspectModeEnum::SearchForNode) { | |
377 search_mode = kSearchingForNormal; | |
378 } else if (mode == protocol::Overlay::InspectModeEnum::SearchForUAShadowDOM) { | |
379 search_mode = kSearchingForUAShadow; | |
380 } else if (mode == protocol::Overlay::InspectModeEnum::None) { | |
381 search_mode = kNotSearching; | |
382 } else { | |
383 return Response::Error( | |
384 String("Unknown mode \"" + mode + "\" was provided.")); | |
385 } | |
386 | |
387 if (search_mode != kNotSearching) { | |
388 Response response = dom_agent_->PushDocumentUponHandlelessOperation(); | |
389 if (!response.isSuccess()) | |
390 return response; | |
391 } | |
392 | |
393 return SetSearchingForNode(search_mode, std::move(highlight_config)); | |
394 } | |
395 | |
396 Response InspectorOverlayAgent::highlightRect( | |
397 int x, | |
398 int y, | |
399 int width, | |
400 int height, | |
401 Maybe<protocol::DOM::RGBA> color, | |
402 Maybe<protocol::DOM::RGBA> outline_color) { | |
403 std::unique_ptr<FloatQuad> quad = | |
404 WTF::WrapUnique(new FloatQuad(FloatRect(x, y, width, height))); | |
405 InnerHighlightQuad(std::move(quad), std::move(color), | |
406 std::move(outline_color)); | |
407 return Response::OK(); | |
408 } | |
409 | |
410 Response InspectorOverlayAgent::highlightQuad( | |
411 std::unique_ptr<protocol::Array<double>> quad_array, | |
412 Maybe<protocol::DOM::RGBA> color, | |
413 Maybe<protocol::DOM::RGBA> outline_color) { | |
414 std::unique_ptr<FloatQuad> quad = WTF::MakeUnique<FloatQuad>(); | |
415 if (!ParseQuad(std::move(quad_array), quad.get())) | |
416 return Response::Error("Invalid Quad format"); | |
417 InnerHighlightQuad(std::move(quad), std::move(color), | |
418 std::move(outline_color)); | |
419 return Response::OK(); | |
420 } | |
421 | |
422 Response InspectorOverlayAgent::highlightNode( | |
423 std::unique_ptr<protocol::Overlay::HighlightConfig> | |
424 highlight_inspector_object, | |
425 Maybe<int> node_id, | |
426 Maybe<int> backend_node_id, | |
427 Maybe<String> object_id) { | |
428 Node* node = nullptr; | |
429 Response response; | |
430 if (node_id.isJust()) { | |
431 response = dom_agent_->AssertNode(node_id.fromJust(), node); | |
432 } else if (backend_node_id.isJust()) { | |
433 node = DOMNodeIds::NodeForId(backend_node_id.fromJust()); | |
434 response = !node ? Response::Error("No node found for given backend id") | |
435 : Response::OK(); | |
436 } else if (object_id.isJust()) { | |
437 response = dom_agent_->NodeForRemoteObjectId(object_id.fromJust(), node); | |
438 } else { | |
439 response = Response::Error( | |
440 "Either nodeId, backendNodeId or objectId must be specified"); | |
441 } | |
442 | |
443 if (!response.isSuccess()) | |
444 return response; | |
445 | |
446 std::unique_ptr<InspectorHighlightConfig> highlight_config; | |
447 response = HighlightConfigFromInspectorObject( | |
448 std::move(highlight_inspector_object), &highlight_config); | |
449 if (!response.isSuccess()) | |
450 return response; | |
451 | |
452 InnerHighlightNode(node, nullptr, *highlight_config, false); | |
453 return Response::OK(); | |
454 } | |
455 | |
456 Response InspectorOverlayAgent::highlightFrame( | |
457 const String& frame_id, | |
458 Maybe<protocol::DOM::RGBA> color, | |
459 Maybe<protocol::DOM::RGBA> outline_color) { | |
460 LocalFrame* frame = | |
461 IdentifiersFactory::FrameById(inspected_frames_, frame_id); | |
462 // FIXME: Inspector doesn't currently work cross process. | |
463 if (frame && frame->DeprecatedLocalOwner()) { | |
464 std::unique_ptr<InspectorHighlightConfig> highlight_config = | |
465 WTF::MakeUnique<InspectorHighlightConfig>(); | |
466 highlight_config->show_info = true; // Always show tooltips for frames. | |
467 highlight_config->content = | |
468 InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr)); | |
469 highlight_config->content_outline = | |
470 InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr)); | |
471 InnerHighlightNode(frame->DeprecatedLocalOwner(), nullptr, | |
472 *highlight_config, false); | |
473 } | |
474 return Response::OK(); | |
475 } | |
476 | |
477 Response InspectorOverlayAgent::hideHighlight() { | |
478 InnerHideHighlight(); | |
479 return Response::OK(); | |
480 } | |
481 | |
482 Response InspectorOverlayAgent::getHighlightObjectForTest( | |
483 int node_id, | |
484 std::unique_ptr<protocol::DictionaryValue>* result) { | |
485 Node* node = nullptr; | |
486 Response response = dom_agent_->AssertNode(node_id, node); | |
487 if (!response.isSuccess()) | |
488 return response; | |
489 InspectorHighlight highlight(node, InspectorHighlight::DefaultConfig(), true); | |
490 *result = highlight.AsProtocolValue(); | |
491 return Response::OK(); | |
492 } | |
493 | |
494 void InspectorOverlayAgent::Invalidate() { | |
495 if (!page_overlay_) { | |
496 page_overlay_ = PageOverlay::Create( | |
497 frame_impl_, WTF::WrapUnique(new InspectorPageOverlayDelegate(*this))); | |
498 } | |
499 | |
500 page_overlay_->Update(); | |
501 } | |
502 | |
503 void InspectorOverlayAgent::UpdateAllLifecyclePhases() { | |
504 if (IsEmpty()) | |
505 return; | |
506 | |
507 AutoReset<bool> scoped(&in_layout_, true); | |
508 if (needs_update_) { | |
509 needs_update_ = false; | |
510 RebuildOverlayPage(); | |
511 } | |
512 OverlayMainFrame()->View()->UpdateAllLifecyclePhases(); | |
513 } | |
514 | |
515 bool InspectorOverlayAgent::HandleInputEvent(const WebInputEvent& input_event) { | |
516 bool handled = false; | |
517 | |
518 if (IsEmpty()) | |
519 return false; | |
520 | |
521 if (input_event.GetType() == WebInputEvent::kGestureTap) { | |
522 // We only have a use for gesture tap. | |
523 WebGestureEvent transformed_event = TransformWebGestureEvent( | |
524 frame_impl_->GetFrameView(), | |
525 static_cast<const WebGestureEvent&>(input_event)); | |
526 handled = HandleGestureEvent(transformed_event); | |
527 if (handled) | |
528 return true; | |
529 | |
530 OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event); | |
531 } | |
532 if (WebInputEvent::IsMouseEventType(input_event.GetType())) { | |
533 WebMouseEvent mouse_event = | |
534 TransformWebMouseEvent(frame_impl_->GetFrameView(), | |
535 static_cast<const WebMouseEvent&>(input_event)); | |
536 | |
537 if (mouse_event.GetType() == WebInputEvent::kMouseMove) | |
538 handled = HandleMouseMove(mouse_event); | |
539 else if (mouse_event.GetType() == WebInputEvent::kMouseDown) | |
540 handled = HandleMouseDown(); | |
541 else if (mouse_event.GetType() == WebInputEvent::kMouseUp) | |
542 handled = HandleMouseUp(); | |
543 | |
544 if (handled) | |
545 return true; | |
546 | |
547 if (mouse_event.GetType() == WebInputEvent::kMouseMove) { | |
548 handled = OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent( | |
549 mouse_event, TransformWebMouseEventVector( | |
550 frame_impl_->GetFrameView(), | |
551 std::vector<const WebInputEvent*>())) != | |
552 WebInputEventResult::kNotHandled; | |
553 } | |
554 if (mouse_event.GetType() == WebInputEvent::kMouseDown) { | |
555 handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent( | |
556 mouse_event) != WebInputEventResult::kNotHandled; | |
557 } | |
558 if (mouse_event.GetType() == WebInputEvent::kMouseUp) { | |
559 handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent( | |
560 mouse_event) != WebInputEventResult::kNotHandled; | |
561 } | |
562 } | |
563 | |
564 if (WebInputEvent::IsTouchEventType(input_event.GetType())) { | |
565 WebTouchEvent transformed_event = | |
566 TransformWebTouchEvent(frame_impl_->GetFrameView(), | |
567 static_cast<const WebTouchEvent&>(input_event)); | |
568 handled = HandleTouchEvent(transformed_event); | |
569 if (handled) | |
570 return true; | |
571 OverlayMainFrame()->GetEventHandler().HandleTouchEvent( | |
572 transformed_event, Vector<WebTouchEvent>()); | |
573 } | |
574 if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) { | |
575 OverlayMainFrame()->GetEventHandler().KeyEvent( | |
576 static_cast<const WebKeyboardEvent&>(input_event)); | |
577 } | |
578 | |
579 if (input_event.GetType() == WebInputEvent::kMouseWheel) { | |
580 WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent( | |
581 frame_impl_->GetFrameView(), | |
582 static_cast<const WebMouseWheelEvent&>(input_event)); | |
583 handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent( | |
584 transformed_event) != WebInputEventResult::kNotHandled; | |
585 } | |
586 | |
587 return handled; | |
588 } | |
589 | |
590 void InspectorOverlayAgent::ShowReloadingBlanket() { | |
591 show_reloading_blanket_ = true; | |
592 ScheduleUpdate(); | |
593 } | |
594 | |
595 void InspectorOverlayAgent::HideReloadingBlanket() { | |
596 if (!show_reloading_blanket_) | |
597 return; | |
598 show_reloading_blanket_ = false; | |
599 if (suspended_) | |
600 ClearInternal(); | |
601 else | |
602 ScheduleUpdate(); | |
603 } | |
604 | |
605 void InspectorOverlayAgent::InnerHideHighlight() { | |
606 highlight_node_.Clear(); | |
607 event_target_node_.Clear(); | |
608 highlight_quad_.reset(); | |
609 ScheduleUpdate(); | |
610 } | |
611 | |
612 void InspectorOverlayAgent::InnerHighlightNode( | |
613 Node* node, | |
614 Node* event_target, | |
615 const InspectorHighlightConfig& highlight_config, | |
616 bool omit_tooltip) { | |
617 node_highlight_config_ = highlight_config; | |
618 highlight_node_ = node; | |
619 event_target_node_ = event_target; | |
620 omit_tooltip_ = omit_tooltip; | |
621 ScheduleUpdate(); | |
622 } | |
623 | |
624 void InspectorOverlayAgent::InnerHighlightQuad( | |
625 std::unique_ptr<FloatQuad> quad, | |
626 Maybe<protocol::DOM::RGBA> color, | |
627 Maybe<protocol::DOM::RGBA> outline_color) { | |
628 quad_content_color_ = InspectorDOMAgent::ParseColor(color.fromMaybe(nullptr)); | |
629 quad_content_outline_color_ = | |
630 InspectorDOMAgent::ParseColor(outline_color.fromMaybe(nullptr)); | |
631 highlight_quad_ = std::move(quad); | |
632 omit_tooltip_ = false; | |
633 ScheduleUpdate(); | |
634 } | |
635 | |
636 bool InspectorOverlayAgent::IsEmpty() { | |
637 if (show_reloading_blanket_) | |
638 return false; | |
639 if (suspended_) | |
640 return true; | |
641 bool has_visible_elements = highlight_node_ || event_target_node_ || | |
642 highlight_quad_ || | |
643 (resize_timer_active_ && draw_view_size_) || | |
644 !paused_in_debugger_message_.IsNull(); | |
645 return !has_visible_elements && inspect_mode_ == kNotSearching; | |
646 } | |
647 | |
648 void InspectorOverlayAgent::ScheduleUpdate() { | |
649 if (IsEmpty()) { | |
650 if (page_overlay_) | |
651 page_overlay_.reset(); | |
652 return; | |
653 } | |
654 needs_update_ = true; | |
655 LocalFrame* frame = frame_impl_->GetFrame(); | |
656 if (frame) { | |
657 frame->GetPage()->GetChromeClient().ScheduleAnimation(frame); | |
658 } | |
659 } | |
660 | |
661 void InspectorOverlayAgent::RebuildOverlayPage() { | |
662 FrameView* view = frame_impl_->GetFrameView(); | |
663 LocalFrame* frame = frame_impl_->GetFrame(); | |
664 if (!view || !frame) | |
665 return; | |
666 | |
667 IntRect visible_rect_in_document = | |
668 view->GetScrollableArea()->VisibleContentRect(); | |
669 IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size(); | |
670 OverlayMainFrame()->View()->Resize(viewport_size); | |
671 OverlayPage()->GetVisualViewport().SetSize(viewport_size); | |
672 OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale()); | |
673 | |
674 Reset(viewport_size, visible_rect_in_document.Location()); | |
675 | |
676 if (show_reloading_blanket_) { | |
677 EvaluateInOverlay("showReloadingBlanket", ""); | |
678 return; | |
679 } | |
680 DrawNodeHighlight(); | |
681 DrawQuadHighlight(); | |
682 DrawPausedInDebuggerMessage(); | |
683 DrawViewSize(); | |
684 } | |
685 | |
686 static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize( | |
687 const IntSize& size) { | |
688 std::unique_ptr<protocol::DictionaryValue> result = | |
689 protocol::DictionaryValue::create(); | |
690 result->setInteger("width", size.Width()); | |
691 result->setInteger("height", size.Height()); | |
692 return result; | |
693 } | |
694 | |
695 void InspectorOverlayAgent::DrawNodeHighlight() { | |
696 if (!highlight_node_) | |
697 return; | |
698 | |
699 String selectors = node_highlight_config_.selector_list; | |
700 StaticElementList* elements = nullptr; | |
701 DummyExceptionStateForTesting exception_state; | |
702 ContainerNode* query_base = highlight_node_->ContainingShadowRoot(); | |
703 if (!query_base) | |
704 query_base = highlight_node_->ownerDocument(); | |
705 if (selectors.length()) { | |
706 elements = | |
707 query_base->QuerySelectorAll(AtomicString(selectors), exception_state); | |
708 } | |
709 if (elements && !exception_state.HadException()) { | |
710 for (unsigned i = 0; i < elements->length(); ++i) { | |
711 Element* element = elements->item(i); | |
712 InspectorHighlight highlight(element, node_highlight_config_, false); | |
713 std::unique_ptr<protocol::DictionaryValue> highlight_json = | |
714 highlight.AsProtocolValue(); | |
715 EvaluateInOverlay("drawHighlight", std::move(highlight_json)); | |
716 } | |
717 } | |
718 | |
719 bool append_element_info = | |
720 highlight_node_->IsElementNode() && !omit_tooltip_ && | |
721 node_highlight_config_.show_info && highlight_node_->GetLayoutObject() && | |
722 highlight_node_->GetDocument().GetFrame(); | |
723 InspectorHighlight highlight(highlight_node_.Get(), node_highlight_config_, | |
724 append_element_info); | |
725 if (event_target_node_) { | |
726 highlight.AppendEventTargetQuads(event_target_node_.Get(), | |
727 node_highlight_config_); | |
728 } | |
729 | |
730 std::unique_ptr<protocol::DictionaryValue> highlight_json = | |
731 highlight.AsProtocolValue(); | |
732 EvaluateInOverlay("drawHighlight", std::move(highlight_json)); | |
733 } | |
734 | |
735 void InspectorOverlayAgent::DrawQuadHighlight() { | |
736 if (!highlight_quad_) | |
737 return; | |
738 | |
739 InspectorHighlight highlight(WindowToViewportScale()); | |
740 highlight.AppendQuad(*highlight_quad_, quad_content_color_, | |
741 quad_content_outline_color_); | |
742 EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue()); | |
743 } | |
744 | |
745 void InspectorOverlayAgent::DrawPausedInDebuggerMessage() { | |
746 if (inspect_mode_ == kNotSearching && !paused_in_debugger_message_.IsNull()) { | |
747 EvaluateInOverlay("drawPausedInDebuggerMessage", | |
748 paused_in_debugger_message_); | |
749 } | |
750 } | |
751 | |
752 void InspectorOverlayAgent::DrawViewSize() { | |
753 if (resize_timer_active_ && draw_view_size_) | |
754 EvaluateInOverlay("drawViewSize", ""); | |
755 } | |
756 | |
757 float InspectorOverlayAgent::WindowToViewportScale() const { | |
758 LocalFrame* frame = frame_impl_->GetFrame(); | |
759 if (!frame) | |
760 return 1.0f; | |
761 return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f); | |
762 } | |
763 | |
764 Page* InspectorOverlayAgent::OverlayPage() { | |
765 if (overlay_page_) | |
766 return overlay_page_.Get(); | |
767 | |
768 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
769 | |
770 DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client, | |
771 (EmptyLocalFrameClient::Create())); | |
772 Page::PageClients page_clients; | |
773 FillWithEmptyClients(page_clients); | |
774 DCHECK(!overlay_chrome_client_); | |
775 overlay_chrome_client_ = InspectorOverlayChromeClient::Create( | |
776 frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this); | |
777 page_clients.chrome_client = overlay_chrome_client_.Get(); | |
778 overlay_page_ = Page::Create(page_clients); | |
779 | |
780 Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings(); | |
781 Settings& overlay_settings = overlay_page_->GetSettings(); | |
782 | |
783 overlay_settings.GetGenericFontFamilySettings().UpdateStandard( | |
784 settings.GetGenericFontFamilySettings().Standard()); | |
785 overlay_settings.GetGenericFontFamilySettings().UpdateSerif( | |
786 settings.GetGenericFontFamilySettings().Serif()); | |
787 overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif( | |
788 settings.GetGenericFontFamilySettings().SansSerif()); | |
789 overlay_settings.GetGenericFontFamilySettings().UpdateCursive( | |
790 settings.GetGenericFontFamilySettings().Cursive()); | |
791 overlay_settings.GetGenericFontFamilySettings().UpdateFantasy( | |
792 settings.GetGenericFontFamilySettings().Fantasy()); | |
793 overlay_settings.GetGenericFontFamilySettings().UpdatePictograph( | |
794 settings.GetGenericFontFamilySettings().Pictograph()); | |
795 overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize()); | |
796 overlay_settings.SetMinimumLogicalFontSize( | |
797 settings.GetMinimumLogicalFontSize()); | |
798 overlay_settings.SetScriptEnabled(true); | |
799 overlay_settings.SetPluginsEnabled(false); | |
800 overlay_settings.SetLoadsImagesAutomatically(true); | |
801 // FIXME: http://crbug.com/363843. Inspector should probably create its | |
802 // own graphics layers and attach them to the tree rather than going | |
803 // through some non-composited paint function. | |
804 overlay_settings.SetAcceleratedCompositingEnabled(false); | |
805 | |
806 LocalFrame* frame = | |
807 LocalFrame::Create(&dummy_local_frame_client, *overlay_page_, 0); | |
808 frame->SetView(FrameView::Create(*frame)); | |
809 frame->Init(); | |
810 FrameLoader& loader = frame->Loader(); | |
811 frame->View()->SetCanHaveScrollbars(false); | |
812 frame->View()->SetBaseBackgroundColor(Color::kTransparent); | |
813 | |
814 const WebData& overlay_page_html_resource = | |
815 Platform::Current()->LoadResource("InspectorOverlayPage.html"); | |
816 loader.Load( | |
817 FrameLoadRequest(0, ResourceRequest(BlankURL()), | |
818 SubstituteData(overlay_page_html_resource, "text/html", | |
819 "UTF-8", KURL(), kForceSynchronousLoad))); | |
820 v8::Isolate* isolate = ToIsolate(frame); | |
821 ScriptState* script_state = ToScriptStateForMainWorld(frame); | |
822 DCHECK(script_state); | |
823 ScriptState::Scope scope(script_state); | |
824 v8::Local<v8::Object> global = script_state->GetContext()->Global(); | |
825 v8::Local<v8::Value> overlay_host_obj = | |
826 ToV8(overlay_host_.Get(), global, isolate); | |
827 DCHECK(!overlay_host_obj.IsEmpty()); | |
828 global | |
829 ->Set(script_state->GetContext(), | |
830 V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj) | |
831 .ToChecked(); | |
832 | |
833 #if OS(WIN) | |
834 EvaluateInOverlay("setPlatform", "windows"); | |
835 #elif OS(MACOSX) | |
836 EvaluateInOverlay("setPlatform", "mac"); | |
837 #elif OS(POSIX) | |
838 EvaluateInOverlay("setPlatform", "linux"); | |
839 #endif | |
840 | |
841 return overlay_page_.Get(); | |
842 } | |
843 | |
844 LocalFrame* InspectorOverlayAgent::OverlayMainFrame() { | |
845 return ToLocalFrame(OverlayPage()->MainFrame()); | |
846 } | |
847 | |
848 void InspectorOverlayAgent::Reset(const IntSize& viewport_size, | |
849 const IntPoint& document_scroll_offset) { | |
850 std::unique_ptr<protocol::DictionaryValue> reset_data = | |
851 protocol::DictionaryValue::create(); | |
852 reset_data->setDouble( | |
853 "deviceScaleFactor", | |
854 frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated()); | |
855 reset_data->setDouble( | |
856 "pageScaleFactor", | |
857 frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale()); | |
858 | |
859 IntRect viewport_in_screen = | |
860 frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen( | |
861 IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View()); | |
862 reset_data->setObject("viewportSize", | |
863 BuildObjectForSize(viewport_in_screen.Size())); | |
864 | |
865 // The zoom factor in the overlay frame already has been multiplied by the | |
866 // window to viewport scale (aka device scale factor), so cancel it. | |
867 reset_data->setDouble( | |
868 "pageZoomFactor", | |
869 frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale()); | |
870 | |
871 reset_data->setInteger("scrollX", document_scroll_offset.X()); | |
872 reset_data->setInteger("scrollY", document_scroll_offset.Y()); | |
873 EvaluateInOverlay("reset", std::move(reset_data)); | |
874 } | |
875 | |
876 void InspectorOverlayAgent::EvaluateInOverlay(const String& method, | |
877 const String& argument) { | |
878 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
879 std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create(); | |
880 command->pushValue(protocol::StringValue::create(method)); | |
881 command->pushValue(protocol::StringValue::create(argument)); | |
882 ToLocalFrame(OverlayPage()->MainFrame()) | |
883 ->GetScriptController() | |
884 .ExecuteScriptInMainWorld( | |
885 "dispatch(" + command->serialize() + ")", | |
886 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
887 } | |
888 | |
889 void InspectorOverlayAgent::EvaluateInOverlay( | |
890 const String& method, | |
891 std::unique_ptr<protocol::Value> argument) { | |
892 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
893 std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create(); | |
894 command->pushValue(protocol::StringValue::create(method)); | |
895 command->pushValue(std::move(argument)); | |
896 ToLocalFrame(OverlayPage()->MainFrame()) | |
897 ->GetScriptController() | |
898 .ExecuteScriptInMainWorld( | |
899 "dispatch(" + command->serialize() + ")", | |
900 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
901 } | |
902 | |
903 String InspectorOverlayAgent::EvaluateInOverlayForTest(const String& script) { | |
904 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
905 v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame())); | |
906 v8::Local<v8::Value> string = | |
907 ToLocalFrame(OverlayPage()->MainFrame()) | |
908 ->GetScriptController() | |
909 .ExecuteScriptInMainWorldAndReturnValue( | |
910 ScriptSourceCode(script), | |
911 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
912 return ToCoreStringWithUndefinedOrNullCheck(string); | |
913 } | |
914 | |
915 void InspectorOverlayAgent::OnTimer(TimerBase*) { | |
916 resize_timer_active_ = false; | |
917 ScheduleUpdate(); | |
918 } | |
919 | |
920 void InspectorOverlayAgent::ClearInternal() { | |
921 if (overlay_page_) { | |
922 overlay_page_->WillBeDestroyed(); | |
923 overlay_page_.Clear(); | |
924 overlay_chrome_client_.Clear(); | |
925 } | |
926 resize_timer_active_ = false; | |
927 paused_in_debugger_message_ = String(); | |
928 inspect_mode_ = kNotSearching; | |
929 timer_.Stop(); | |
930 InnerHideHighlight(); | |
931 } | |
932 | |
933 void InspectorOverlayAgent::OverlayResumed() { | |
934 if (v8_session_) | |
935 v8_session_->resume(); | |
936 } | |
937 | |
938 void InspectorOverlayAgent::OverlaySteppedOver() { | |
939 if (v8_session_) | |
940 v8_session_->stepOver(); | |
941 } | |
942 | |
943 void InspectorOverlayAgent::PageLayoutInvalidated(bool resized) { | |
944 if (resized && draw_view_size_) { | |
945 resize_timer_active_ = true; | |
946 timer_.StartOneShot(1, BLINK_FROM_HERE); | |
947 } | |
948 ScheduleUpdate(); | |
949 } | |
950 | |
951 bool InspectorOverlayAgent::HandleMouseMove(const WebMouseEvent& event) { | |
952 if (!ShouldSearchForNode()) | |
953 return false; | |
954 | |
955 LocalFrame* frame = frame_impl_->GetFrame(); | |
956 if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull()) | |
957 return false; | |
958 Node* node = HoveredNodeForEvent( | |
959 frame, event, event.GetModifiers() & WebInputEvent::kShiftKey); | |
960 | |
961 // Do not highlight within user agent shadow root unless requested. | |
962 if (inspect_mode_ != kSearchingForUAShadow) { | |
963 ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node); | |
964 if (shadow_root) | |
965 node = &shadow_root->host(); | |
966 } | |
967 | |
968 // Shadow roots don't have boxes - use host element instead. | |
969 if (node && node->IsShadowRoot()) | |
970 node = node->ParentOrShadowHostNode(); | |
971 | |
972 if (!node) | |
973 return true; | |
974 | |
975 if (node->IsFrameOwnerElement()) { | |
976 HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node); | |
977 if (frame_owner->ContentFrame() && | |
978 !frame_owner->ContentFrame()->IsLocalFrame()) { | |
979 // Do not consume event so that remote frame can handle it. | |
980 InnerHideHighlight(); | |
981 hovered_node_for_inspect_mode_.Clear(); | |
982 return false; | |
983 } | |
984 } | |
985 | |
986 Node* event_target = (event.GetModifiers() & WebInputEvent::kShiftKey) | |
987 ? HoveredNodeForEvent(frame, event, false) | |
988 : nullptr; | |
989 if (event_target == node) | |
990 event_target = nullptr; | |
991 | |
992 if (node && inspect_mode_highlight_config_) { | |
993 hovered_node_for_inspect_mode_ = node; | |
994 NodeHighlightRequested(node); | |
995 bool omit_tooltip = event.GetModifiers() & | |
996 (WebInputEvent::kControlKey | WebInputEvent::kMetaKey); | |
997 InnerHighlightNode(node, event_target, *inspect_mode_highlight_config_, | |
998 omit_tooltip); | |
999 } | |
1000 return true; | |
1001 } | |
1002 | |
1003 bool InspectorOverlayAgent::HandleMouseDown() { | |
1004 swallow_next_mouse_up_ = false; | |
1005 if (!ShouldSearchForNode()) | |
1006 return false; | |
1007 | |
1008 if (hovered_node_for_inspect_mode_) { | |
1009 swallow_next_mouse_up_ = true; | |
1010 Inspect(hovered_node_for_inspect_mode_.Get()); | |
1011 hovered_node_for_inspect_mode_.Clear(); | |
1012 return true; | |
1013 } | |
1014 return false; | |
1015 } | |
1016 | |
1017 bool InspectorOverlayAgent::HandleMouseUp() { | |
1018 if (swallow_next_mouse_up_) { | |
1019 swallow_next_mouse_up_ = false; | |
1020 return true; | |
1021 } | |
1022 return false; | |
1023 } | |
1024 | |
1025 bool InspectorOverlayAgent::HandleGestureEvent(const WebGestureEvent& event) { | |
1026 if (!ShouldSearchForNode() || event.GetType() != WebInputEvent::kGestureTap) | |
1027 return false; | |
1028 Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false); | |
1029 if (node && inspect_mode_highlight_config_) { | |
1030 InnerHighlightNode(node, nullptr, *inspect_mode_highlight_config_, false); | |
1031 Inspect(node); | |
1032 return true; | |
1033 } | |
1034 return false; | |
1035 } | |
1036 | |
1037 bool InspectorOverlayAgent::HandleTouchEvent(const WebTouchEvent& event) { | |
1038 if (!ShouldSearchForNode()) | |
1039 return false; | |
1040 Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false); | |
1041 if (node && inspect_mode_highlight_config_) { | |
1042 InnerHighlightNode(node, nullptr, *inspect_mode_highlight_config_, false); | |
1043 Inspect(node); | |
1044 return true; | |
1045 } | |
1046 return false; | |
1047 } | |
1048 | |
1049 Response InspectorOverlayAgent::CompositingEnabled() { | |
1050 bool main_frame = frame_impl_->ViewImpl() && !frame_impl_->Parent(); | |
1051 if (!main_frame || !frame_impl_->ViewImpl() | |
1052 ->GetPage() | |
1053 ->GetSettings() | |
1054 .GetAcceleratedCompositingEnabled()) | |
1055 return Response::Error("Compositing mode is not supported"); | |
1056 return Response::OK(); | |
1057 } | |
1058 | |
1059 bool InspectorOverlayAgent::ShouldSearchForNode() { | |
1060 return inspect_mode_ != kNotSearching; | |
1061 } | |
1062 | |
1063 void InspectorOverlayAgent::Inspect(Node* inspected_node) { | |
1064 if (!inspected_node) | |
1065 return; | |
1066 | |
1067 Node* node = inspected_node; | |
1068 while (node && !node->IsElementNode() && !node->IsDocumentNode() && | |
1069 !node->IsDocumentFragment()) | |
1070 node = node->ParentOrShadowHostNode(); | |
1071 if (!node) | |
1072 return; | |
1073 | |
1074 int backend_node_id = DOMNodeIds::IdForNode(node); | |
1075 if (!enabled_) { | |
1076 backend_node_id_to_inspect_ = backend_node_id; | |
1077 return; | |
1078 } | |
1079 | |
1080 GetFrontend()->inspectNodeRequested(backend_node_id); | |
1081 } | |
1082 | |
1083 void InspectorOverlayAgent::NodeHighlightRequested(Node* node) { | |
1084 if (!enabled_) | |
1085 return; | |
1086 | |
1087 while (node && !node->IsElementNode() && !node->IsDocumentNode() && | |
1088 !node->IsDocumentFragment()) | |
1089 node = node->ParentOrShadowHostNode(); | |
1090 | |
1091 if (!node) | |
1092 return; | |
1093 | |
1094 int node_id = dom_agent_->PushNodePathToFrontend(node); | |
1095 GetFrontend()->nodeHighlightRequested(node_id); | |
1096 } | |
1097 | |
1098 Response InspectorOverlayAgent::SetSearchingForNode( | |
1099 SearchMode search_mode, | |
1100 Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object) { | |
1101 if (search_mode == kNotSearching) { | |
1102 inspect_mode_ = search_mode; | |
1103 ScheduleUpdate(); | |
1104 hovered_node_for_inspect_mode_.Clear(); | |
1105 InnerHideHighlight(); | |
1106 return Response::OK(); | |
1107 } | |
1108 | |
1109 std::unique_ptr<InspectorHighlightConfig> config; | |
1110 Response response = HighlightConfigFromInspectorObject( | |
1111 std::move(highlight_inspector_object), &config); | |
1112 if (!response.isSuccess()) | |
1113 return response; | |
1114 inspect_mode_ = search_mode; | |
1115 inspect_mode_highlight_config_ = std::move(config); | |
1116 ScheduleUpdate(); | |
1117 return Response::OK(); | |
1118 } | |
1119 | |
1120 Response InspectorOverlayAgent::HighlightConfigFromInspectorObject( | |
1121 Maybe<protocol::Overlay::HighlightConfig> highlight_inspector_object, | |
1122 std::unique_ptr<InspectorHighlightConfig>* out_config) { | |
1123 if (!highlight_inspector_object.isJust()) { | |
1124 return Response::Error( | |
1125 "Internal error: highlight configuration parameter is missing"); | |
1126 } | |
1127 | |
1128 protocol::Overlay::HighlightConfig* config = | |
1129 highlight_inspector_object.fromJust(); | |
1130 std::unique_ptr<InspectorHighlightConfig> highlight_config = | |
1131 WTF::MakeUnique<InspectorHighlightConfig>(); | |
1132 highlight_config->show_info = config->getShowInfo(false); | |
1133 highlight_config->show_rulers = config->getShowRulers(false); | |
1134 highlight_config->show_extension_lines = config->getShowExtensionLines(false); | |
1135 highlight_config->display_as_material = config->getDisplayAsMaterial(false); | |
1136 highlight_config->content = | |
1137 InspectorDOMAgent::ParseColor(config->getContentColor(nullptr)); | |
1138 highlight_config->padding = | |
1139 InspectorDOMAgent::ParseColor(config->getPaddingColor(nullptr)); | |
1140 highlight_config->border = | |
1141 InspectorDOMAgent::ParseColor(config->getBorderColor(nullptr)); | |
1142 highlight_config->margin = | |
1143 InspectorDOMAgent::ParseColor(config->getMarginColor(nullptr)); | |
1144 highlight_config->event_target = | |
1145 InspectorDOMAgent::ParseColor(config->getEventTargetColor(nullptr)); | |
1146 highlight_config->shape = | |
1147 InspectorDOMAgent::ParseColor(config->getShapeColor(nullptr)); | |
1148 highlight_config->shape_margin = | |
1149 InspectorDOMAgent::ParseColor(config->getShapeMarginColor(nullptr)); | |
1150 highlight_config->selector_list = config->getSelectorList(""); | |
1151 | |
1152 *out_config = std::move(highlight_config); | |
1153 return Response::OK(); | |
1154 } | |
1155 | |
1156 } // namespace blink | |
OLD | NEW |