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