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/InspectorOverlay.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/Node.h" | |
38 #include "core/dom/StaticNodeList.h" | |
39 #include "core/dom/TaskRunnerHelper.h" | |
40 #include "core/frame/FrameView.h" | |
41 #include "core/frame/LocalFrame.h" | |
42 #include "core/frame/LocalFrameClient.h" | |
43 #include "core/frame/Settings.h" | |
44 #include "core/frame/VisualViewport.h" | |
45 #include "core/html/HTMLFrameOwnerElement.h" | |
46 #include "core/input/EventHandler.h" | |
47 #include "core/inspector/InspectorOverlayHost.h" | |
48 #include "core/layout/api/LayoutViewItem.h" | |
49 #include "core/loader/EmptyClients.h" | |
50 #include "core/loader/FrameLoadRequest.h" | |
51 #include "core/page/ChromeClient.h" | |
52 #include "core/page/Page.h" | |
53 #include "platform/ScriptForbiddenScope.h" | |
54 #include "platform/graphics/Color.h" | |
55 #include "platform/graphics/GraphicsContext.h" | |
56 #include "platform/graphics/paint/CullRect.h" | |
57 #include "platform/wtf/AutoReset.h" | |
58 #include "public/platform/Platform.h" | |
59 #include "public/platform/WebData.h" | |
60 #include "v8/include/v8.h" | |
61 #include "web/ChromeClientImpl.h" | |
62 #include "web/PageOverlay.h" | |
63 #include "web/WebInputEventConversion.h" | |
64 #include "web/WebLocalFrameImpl.h" | |
65 | |
66 namespace blink { | |
67 | |
68 namespace { | |
69 | |
70 Node* HoveredNodeForPoint(LocalFrame* frame, | |
71 const IntPoint& point_in_root_frame, | |
72 bool ignore_pointer_events_none) { | |
73 HitTestRequest::HitTestRequestType hit_type = | |
74 HitTestRequest::kMove | HitTestRequest::kReadOnly | | |
75 HitTestRequest::kAllowChildFrameContent; | |
76 if (ignore_pointer_events_none) | |
77 hit_type |= HitTestRequest::kIgnorePointerEventsNone; | |
78 HitTestRequest request(hit_type); | |
79 HitTestResult result(request, | |
80 frame->View()->RootFrameToContents(point_in_root_frame)); | |
81 frame->ContentLayoutItem().HitTest(result); | |
82 Node* node = result.InnerPossiblyPseudoNode(); | |
83 while (node && node->getNodeType() == Node::kTextNode) | |
84 node = node->parentNode(); | |
85 return node; | |
86 } | |
87 | |
88 Node* HoveredNodeForEvent(LocalFrame* frame, | |
89 const WebGestureEvent& event, | |
90 bool ignore_pointer_events_none) { | |
91 return HoveredNodeForPoint(frame, | |
92 RoundedIntPoint(event.PositionInRootFrame()), | |
93 ignore_pointer_events_none); | |
94 } | |
95 | |
96 Node* HoveredNodeForEvent(LocalFrame* frame, | |
97 const WebMouseEvent& event, | |
98 bool ignore_pointer_events_none) { | |
99 return HoveredNodeForPoint(frame, | |
100 RoundedIntPoint(event.PositionInRootFrame()), | |
101 ignore_pointer_events_none); | |
102 } | |
103 | |
104 Node* HoveredNodeForEvent(LocalFrame* frame, | |
105 const WebTouchEvent& event, | |
106 bool ignore_pointer_events_none) { | |
107 if (!event.touches_length) | |
108 return nullptr; | |
109 WebTouchPoint transformed_point = event.TouchPointInRootFrame(0); | |
110 return HoveredNodeForPoint(frame, RoundedIntPoint(transformed_point.position), | |
111 ignore_pointer_events_none); | |
112 } | |
113 } // namespace | |
114 | |
115 class InspectorOverlay::InspectorPageOverlayDelegate final | |
116 : public PageOverlay::Delegate { | |
117 public: | |
118 explicit InspectorPageOverlayDelegate(InspectorOverlay& overlay) | |
119 : overlay_(&overlay) {} | |
120 | |
121 void PaintPageOverlay(const PageOverlay&, | |
122 GraphicsContext& graphics_context, | |
123 const WebSize& web_view_size) const override { | |
124 if (overlay_->IsEmpty()) | |
125 return; | |
126 | |
127 FrameView* view = overlay_->OverlayMainFrame()->View(); | |
128 DCHECK(!view->NeedsLayout()); | |
129 view->Paint(graphics_context, | |
130 CullRect(IntRect(0, 0, view->Width(), view->Height()))); | |
131 } | |
132 | |
133 private: | |
134 Persistent<InspectorOverlay> overlay_; | |
135 }; | |
136 | |
137 class InspectorOverlay::InspectorOverlayChromeClient final | |
138 : public EmptyChromeClient { | |
139 public: | |
140 static InspectorOverlayChromeClient* Create(ChromeClient& client, | |
141 InspectorOverlay& overlay) { | |
142 return new InspectorOverlayChromeClient(client, overlay); | |
143 } | |
144 | |
145 DEFINE_INLINE_VIRTUAL_TRACE() { | |
146 visitor->Trace(client_); | |
147 visitor->Trace(overlay_); | |
148 EmptyChromeClient::Trace(visitor); | |
149 } | |
150 | |
151 void SetCursor(const Cursor& cursor, LocalFrame* local_root) override { | |
152 ToChromeClientImpl(client_)->SetCursorOverridden(false); | |
153 ToChromeClientImpl(client_)->SetCursor(cursor, | |
154 overlay_->frame_impl_->GetFrame()); | |
155 ToChromeClientImpl(client_)->SetCursorOverridden(false); | |
156 } | |
157 | |
158 void SetToolTip(LocalFrame& frame, | |
159 const String& tooltip, | |
160 TextDirection direction) override { | |
161 DCHECK_EQ(&frame, overlay_->OverlayMainFrame()); | |
162 client_->SetToolTip(*overlay_->frame_impl_->GetFrame(), tooltip, direction); | |
163 } | |
164 | |
165 void InvalidateRect(const IntRect&) override { overlay_->Invalidate(); } | |
166 | |
167 void ScheduleAnimation(LocalFrame* frame) override { | |
168 if (overlay_->in_layout_) | |
169 return; | |
170 | |
171 client_->ScheduleAnimation(frame); | |
172 } | |
173 | |
174 private: | |
175 InspectorOverlayChromeClient(ChromeClient& client, InspectorOverlay& overlay) | |
176 : client_(&client), overlay_(&overlay) {} | |
177 | |
178 Member<ChromeClient> client_; | |
179 Member<InspectorOverlay> overlay_; | |
180 }; | |
181 | |
182 InspectorOverlay::InspectorOverlay(WebLocalFrameImpl* frame_impl) | |
183 : frame_impl_(frame_impl), | |
184 overlay_host_(InspectorOverlayHost::Create()), | |
185 draw_view_size_(false), | |
186 resize_timer_active_(false), | |
187 omit_tooltip_(false), | |
188 timer_(TaskRunnerHelper::Get(TaskType::kUnspecedTimer, | |
189 frame_impl->GetFrame()), | |
190 this, | |
191 &InspectorOverlay::OnTimer), | |
192 suspended_(false), | |
193 show_reloading_blanket_(false), | |
194 in_layout_(false), | |
195 needs_update_(false), | |
196 swallow_next_mouse_up_(false), | |
197 inspect_mode_(InspectorDOMAgent::kNotSearching) {} | |
198 | |
199 InspectorOverlay::~InspectorOverlay() { | |
200 DCHECK(!overlay_page_); | |
201 } | |
202 | |
203 DEFINE_TRACE(InspectorOverlay) { | |
204 visitor->Trace(frame_impl_); | |
205 visitor->Trace(highlight_node_); | |
206 visitor->Trace(event_target_node_); | |
207 visitor->Trace(overlay_page_); | |
208 visitor->Trace(overlay_chrome_client_); | |
209 visitor->Trace(overlay_host_); | |
210 visitor->Trace(dom_agent_); | |
211 visitor->Trace(hovered_node_for_inspect_mode_); | |
212 } | |
213 | |
214 void InspectorOverlay::Init(v8_inspector::V8InspectorSession* v8_session, | |
215 InspectorDOMAgent* dom_agent) { | |
216 v8_session_ = v8_session; | |
217 dom_agent_ = dom_agent; | |
218 overlay_host_->SetListener(this); | |
219 } | |
220 | |
221 void InspectorOverlay::Invalidate() { | |
222 if (!page_overlay_) { | |
223 page_overlay_ = PageOverlay::Create( | |
224 frame_impl_, WTF::WrapUnique(new InspectorPageOverlayDelegate(*this))); | |
225 } | |
226 | |
227 page_overlay_->Update(); | |
228 } | |
229 | |
230 void InspectorOverlay::UpdateAllLifecyclePhases() { | |
231 if (IsEmpty()) | |
232 return; | |
233 | |
234 AutoReset<bool> scoped(&in_layout_, true); | |
235 if (needs_update_) { | |
236 needs_update_ = false; | |
237 RebuildOverlayPage(); | |
238 } | |
239 OverlayMainFrame()->View()->UpdateAllLifecyclePhases(); | |
240 } | |
241 | |
242 bool InspectorOverlay::HandleInputEvent(const WebInputEvent& input_event) { | |
243 bool handled = false; | |
244 | |
245 if (IsEmpty()) | |
246 return false; | |
247 | |
248 if (input_event.GetType() == WebInputEvent::kGestureTap) { | |
249 // We only have a use for gesture tap. | |
250 WebGestureEvent transformed_event = TransformWebGestureEvent( | |
251 frame_impl_->GetFrameView(), | |
252 static_cast<const WebGestureEvent&>(input_event)); | |
253 handled = HandleGestureEvent(transformed_event); | |
254 if (handled) | |
255 return true; | |
256 | |
257 OverlayMainFrame()->GetEventHandler().HandleGestureEvent(transformed_event); | |
258 } | |
259 if (WebInputEvent::IsMouseEventType(input_event.GetType())) { | |
260 WebMouseEvent mouse_event = | |
261 TransformWebMouseEvent(frame_impl_->GetFrameView(), | |
262 static_cast<const WebMouseEvent&>(input_event)); | |
263 | |
264 if (mouse_event.GetType() == WebInputEvent::kMouseMove) | |
265 handled = HandleMouseMove(mouse_event); | |
266 else if (mouse_event.GetType() == WebInputEvent::kMouseDown) | |
267 handled = HandleMouseDown(); | |
268 else if (mouse_event.GetType() == WebInputEvent::kMouseUp) | |
269 handled = HandleMouseUp(); | |
270 | |
271 if (handled) | |
272 return true; | |
273 | |
274 if (mouse_event.GetType() == WebInputEvent::kMouseMove) { | |
275 handled = OverlayMainFrame()->GetEventHandler().HandleMouseMoveEvent( | |
276 mouse_event, TransformWebMouseEventVector( | |
277 frame_impl_->GetFrameView(), | |
278 std::vector<const WebInputEvent*>())) != | |
279 WebInputEventResult::kNotHandled; | |
280 } | |
281 if (mouse_event.GetType() == WebInputEvent::kMouseDown) | |
282 handled = OverlayMainFrame()->GetEventHandler().HandleMousePressEvent( | |
283 mouse_event) != WebInputEventResult::kNotHandled; | |
284 if (mouse_event.GetType() == WebInputEvent::kMouseUp) | |
285 handled = OverlayMainFrame()->GetEventHandler().HandleMouseReleaseEvent( | |
286 mouse_event) != WebInputEventResult::kNotHandled; | |
287 } | |
288 | |
289 if (WebInputEvent::IsTouchEventType(input_event.GetType())) { | |
290 WebTouchEvent transformed_event = | |
291 TransformWebTouchEvent(frame_impl_->GetFrameView(), | |
292 static_cast<const WebTouchEvent&>(input_event)); | |
293 handled = HandleTouchEvent(transformed_event); | |
294 if (handled) | |
295 return true; | |
296 OverlayMainFrame()->GetEventHandler().HandleTouchEvent( | |
297 transformed_event, Vector<WebTouchEvent>()); | |
298 } | |
299 if (WebInputEvent::IsKeyboardEventType(input_event.GetType())) { | |
300 OverlayMainFrame()->GetEventHandler().KeyEvent( | |
301 static_cast<const WebKeyboardEvent&>(input_event)); | |
302 } | |
303 | |
304 if (input_event.GetType() == WebInputEvent::kMouseWheel) { | |
305 WebMouseWheelEvent transformed_event = TransformWebMouseWheelEvent( | |
306 frame_impl_->GetFrameView(), | |
307 static_cast<const WebMouseWheelEvent&>(input_event)); | |
308 handled = OverlayMainFrame()->GetEventHandler().HandleWheelEvent( | |
309 transformed_event) != WebInputEventResult::kNotHandled; | |
310 } | |
311 | |
312 return handled; | |
313 } | |
314 | |
315 void InspectorOverlay::SetPausedInDebuggerMessage(const String& message) { | |
316 paused_in_debugger_message_ = message; | |
317 ScheduleUpdate(); | |
318 } | |
319 | |
320 void InspectorOverlay::ShowReloadingBlanket() { | |
321 show_reloading_blanket_ = true; | |
322 ScheduleUpdate(); | |
323 } | |
324 | |
325 void InspectorOverlay::HideReloadingBlanket() { | |
326 if (!show_reloading_blanket_) | |
327 return; | |
328 show_reloading_blanket_ = false; | |
329 if (suspended_) | |
330 ClearInternal(); | |
331 else | |
332 ScheduleUpdate(); | |
333 } | |
334 | |
335 void InspectorOverlay::HideHighlight() { | |
336 highlight_node_.Clear(); | |
337 event_target_node_.Clear(); | |
338 highlight_quad_.reset(); | |
339 ScheduleUpdate(); | |
340 } | |
341 | |
342 void InspectorOverlay::HighlightNode( | |
343 Node* node, | |
344 const InspectorHighlightConfig& highlight_config, | |
345 bool omit_tooltip) { | |
346 HighlightNode(node, nullptr, highlight_config, omit_tooltip); | |
347 } | |
348 | |
349 void InspectorOverlay::HighlightNode( | |
350 Node* node, | |
351 Node* event_target, | |
352 const InspectorHighlightConfig& highlight_config, | |
353 bool omit_tooltip) { | |
354 node_highlight_config_ = highlight_config; | |
355 highlight_node_ = node; | |
356 event_target_node_ = event_target; | |
357 omit_tooltip_ = omit_tooltip; | |
358 ScheduleUpdate(); | |
359 } | |
360 | |
361 void InspectorOverlay::SetInspectMode( | |
362 InspectorDOMAgent::SearchMode search_mode, | |
363 std::unique_ptr<InspectorHighlightConfig> highlight_config) { | |
364 inspect_mode_ = search_mode; | |
365 ScheduleUpdate(); | |
366 | |
367 if (search_mode != InspectorDOMAgent::kNotSearching) { | |
368 inspect_mode_highlight_config_ = std::move(highlight_config); | |
369 } else { | |
370 hovered_node_for_inspect_mode_.Clear(); | |
371 HideHighlight(); | |
372 } | |
373 } | |
374 | |
375 void InspectorOverlay::HighlightQuad( | |
376 std::unique_ptr<FloatQuad> quad, | |
377 const InspectorHighlightConfig& highlight_config) { | |
378 quad_highlight_config_ = highlight_config; | |
379 highlight_quad_ = std::move(quad); | |
380 omit_tooltip_ = false; | |
381 ScheduleUpdate(); | |
382 } | |
383 | |
384 bool InspectorOverlay::IsEmpty() { | |
385 if (show_reloading_blanket_) | |
386 return false; | |
387 if (suspended_) | |
388 return true; | |
389 bool has_visible_elements = highlight_node_ || event_target_node_ || | |
390 highlight_quad_ || | |
391 (resize_timer_active_ && draw_view_size_) || | |
392 !paused_in_debugger_message_.IsNull(); | |
393 return !has_visible_elements && | |
394 inspect_mode_ == InspectorDOMAgent::kNotSearching; | |
395 } | |
396 | |
397 void InspectorOverlay::ScheduleUpdate() { | |
398 if (IsEmpty()) { | |
399 if (page_overlay_) | |
400 page_overlay_.reset(); | |
401 return; | |
402 } | |
403 needs_update_ = true; | |
404 LocalFrame* frame = frame_impl_->GetFrame(); | |
405 if (frame) { | |
406 frame->GetPage()->GetChromeClient().ScheduleAnimation(frame); | |
407 } | |
408 } | |
409 | |
410 void InspectorOverlay::RebuildOverlayPage() { | |
411 FrameView* view = frame_impl_->GetFrameView(); | |
412 LocalFrame* frame = frame_impl_->GetFrame(); | |
413 if (!view || !frame) | |
414 return; | |
415 | |
416 IntRect visible_rect_in_document = | |
417 view->GetScrollableArea()->VisibleContentRect(); | |
418 IntSize viewport_size = frame->GetPage()->GetVisualViewport().Size(); | |
419 OverlayMainFrame()->View()->Resize(viewport_size); | |
420 OverlayPage()->GetVisualViewport().SetSize(viewport_size); | |
421 OverlayMainFrame()->SetPageZoomFactor(WindowToViewportScale()); | |
422 | |
423 Reset(viewport_size, visible_rect_in_document.Location()); | |
424 | |
425 if (show_reloading_blanket_) { | |
426 EvaluateInOverlay("showReloadingBlanket", ""); | |
427 return; | |
428 } | |
429 DrawNodeHighlight(); | |
430 DrawQuadHighlight(); | |
431 DrawPausedInDebuggerMessage(); | |
432 DrawViewSize(); | |
433 } | |
434 | |
435 static std::unique_ptr<protocol::DictionaryValue> BuildObjectForSize( | |
436 const IntSize& size) { | |
437 std::unique_ptr<protocol::DictionaryValue> result = | |
438 protocol::DictionaryValue::create(); | |
439 result->setInteger("width", size.Width()); | |
440 result->setInteger("height", size.Height()); | |
441 return result; | |
442 } | |
443 | |
444 void InspectorOverlay::DrawNodeHighlight() { | |
445 if (!highlight_node_) | |
446 return; | |
447 | |
448 String selectors = node_highlight_config_.selector_list; | |
449 StaticElementList* elements = nullptr; | |
450 DummyExceptionStateForTesting exception_state; | |
451 ContainerNode* query_base = highlight_node_->ContainingShadowRoot(); | |
452 if (!query_base) | |
453 query_base = highlight_node_->ownerDocument(); | |
454 if (selectors.length()) | |
455 elements = | |
456 query_base->QuerySelectorAll(AtomicString(selectors), exception_state); | |
457 if (elements && !exception_state.HadException()) { | |
458 for (unsigned i = 0; i < elements->length(); ++i) { | |
459 Element* element = elements->item(i); | |
460 InspectorHighlight highlight(element, node_highlight_config_, false); | |
461 std::unique_ptr<protocol::DictionaryValue> highlight_json = | |
462 highlight.AsProtocolValue(); | |
463 EvaluateInOverlay("drawHighlight", std::move(highlight_json)); | |
464 } | |
465 } | |
466 | |
467 bool append_element_info = | |
468 highlight_node_->IsElementNode() && !omit_tooltip_ && | |
469 node_highlight_config_.show_info && highlight_node_->GetLayoutObject() && | |
470 highlight_node_->GetDocument().GetFrame(); | |
471 InspectorHighlight highlight(highlight_node_.Get(), node_highlight_config_, | |
472 append_element_info); | |
473 if (event_target_node_) | |
474 highlight.AppendEventTargetQuads(event_target_node_.Get(), | |
475 node_highlight_config_); | |
476 | |
477 std::unique_ptr<protocol::DictionaryValue> highlight_json = | |
478 highlight.AsProtocolValue(); | |
479 EvaluateInOverlay("drawHighlight", std::move(highlight_json)); | |
480 } | |
481 | |
482 void InspectorOverlay::DrawQuadHighlight() { | |
483 if (!highlight_quad_) | |
484 return; | |
485 | |
486 InspectorHighlight highlight(WindowToViewportScale()); | |
487 highlight.AppendQuad(*highlight_quad_, quad_highlight_config_.content, | |
488 quad_highlight_config_.content_outline); | |
489 EvaluateInOverlay("drawHighlight", highlight.AsProtocolValue()); | |
490 } | |
491 | |
492 void InspectorOverlay::DrawPausedInDebuggerMessage() { | |
493 if (inspect_mode_ == InspectorDOMAgent::kNotSearching && | |
494 !paused_in_debugger_message_.IsNull()) | |
495 EvaluateInOverlay("drawPausedInDebuggerMessage", | |
496 paused_in_debugger_message_); | |
497 } | |
498 | |
499 void InspectorOverlay::DrawViewSize() { | |
500 if (resize_timer_active_ && draw_view_size_) | |
501 EvaluateInOverlay("drawViewSize", ""); | |
502 } | |
503 | |
504 float InspectorOverlay::WindowToViewportScale() const { | |
505 LocalFrame* frame = frame_impl_->GetFrame(); | |
506 if (!frame) | |
507 return 1.0f; | |
508 return frame->GetPage()->GetChromeClient().WindowToViewportScalar(1.0f); | |
509 } | |
510 | |
511 Page* InspectorOverlay::OverlayPage() { | |
512 if (overlay_page_) | |
513 return overlay_page_.Get(); | |
514 | |
515 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
516 | |
517 DEFINE_STATIC_LOCAL(LocalFrameClient, dummy_local_frame_client, | |
518 (EmptyLocalFrameClient::Create())); | |
519 Page::PageClients page_clients; | |
520 FillWithEmptyClients(page_clients); | |
521 DCHECK(!overlay_chrome_client_); | |
522 overlay_chrome_client_ = InspectorOverlayChromeClient::Create( | |
523 frame_impl_->GetFrame()->GetPage()->GetChromeClient(), *this); | |
524 page_clients.chrome_client = overlay_chrome_client_.Get(); | |
525 overlay_page_ = Page::Create(page_clients); | |
526 | |
527 Settings& settings = frame_impl_->GetFrame()->GetPage()->GetSettings(); | |
528 Settings& overlay_settings = overlay_page_->GetSettings(); | |
529 | |
530 overlay_settings.GetGenericFontFamilySettings().UpdateStandard( | |
531 settings.GetGenericFontFamilySettings().Standard()); | |
532 overlay_settings.GetGenericFontFamilySettings().UpdateSerif( | |
533 settings.GetGenericFontFamilySettings().Serif()); | |
534 overlay_settings.GetGenericFontFamilySettings().UpdateSansSerif( | |
535 settings.GetGenericFontFamilySettings().SansSerif()); | |
536 overlay_settings.GetGenericFontFamilySettings().UpdateCursive( | |
537 settings.GetGenericFontFamilySettings().Cursive()); | |
538 overlay_settings.GetGenericFontFamilySettings().UpdateFantasy( | |
539 settings.GetGenericFontFamilySettings().Fantasy()); | |
540 overlay_settings.GetGenericFontFamilySettings().UpdatePictograph( | |
541 settings.GetGenericFontFamilySettings().Pictograph()); | |
542 overlay_settings.SetMinimumFontSize(settings.GetMinimumFontSize()); | |
543 overlay_settings.SetMinimumLogicalFontSize( | |
544 settings.GetMinimumLogicalFontSize()); | |
545 overlay_settings.SetScriptEnabled(true); | |
546 overlay_settings.SetPluginsEnabled(false); | |
547 overlay_settings.SetLoadsImagesAutomatically(true); | |
548 // FIXME: http://crbug.com/363843. Inspector should probably create its | |
549 // own graphics layers and attach them to the tree rather than going | |
550 // through some non-composited paint function. | |
551 overlay_settings.SetAcceleratedCompositingEnabled(false); | |
552 | |
553 LocalFrame* frame = | |
554 LocalFrame::Create(&dummy_local_frame_client, *overlay_page_, 0); | |
555 frame->SetView(FrameView::Create(*frame)); | |
556 frame->Init(); | |
557 FrameLoader& loader = frame->Loader(); | |
558 frame->View()->SetCanHaveScrollbars(false); | |
559 frame->View()->SetBaseBackgroundColor(Color::kTransparent); | |
560 | |
561 const WebData& overlay_page_html_resource = | |
562 Platform::Current()->LoadResource("InspectorOverlayPage.html"); | |
563 loader.Load( | |
564 FrameLoadRequest(0, ResourceRequest(BlankURL()), | |
565 SubstituteData(overlay_page_html_resource, "text/html", | |
566 "UTF-8", KURL(), kForceSynchronousLoad))); | |
567 v8::Isolate* isolate = ToIsolate(frame); | |
568 ScriptState* script_state = ToScriptStateForMainWorld(frame); | |
569 DCHECK(script_state); | |
570 ScriptState::Scope scope(script_state); | |
571 v8::Local<v8::Object> global = script_state->GetContext()->Global(); | |
572 v8::Local<v8::Value> overlay_host_obj = | |
573 ToV8(overlay_host_.Get(), global, isolate); | |
574 DCHECK(!overlay_host_obj.IsEmpty()); | |
575 global | |
576 ->Set(script_state->GetContext(), | |
577 V8AtomicString(isolate, "InspectorOverlayHost"), overlay_host_obj) | |
578 .ToChecked(); | |
579 | |
580 #if OS(WIN) | |
581 EvaluateInOverlay("setPlatform", "windows"); | |
582 #elif OS(MACOSX) | |
583 EvaluateInOverlay("setPlatform", "mac"); | |
584 #elif OS(POSIX) | |
585 EvaluateInOverlay("setPlatform", "linux"); | |
586 #endif | |
587 | |
588 return overlay_page_.Get(); | |
589 } | |
590 | |
591 LocalFrame* InspectorOverlay::OverlayMainFrame() { | |
592 return ToLocalFrame(OverlayPage()->MainFrame()); | |
593 } | |
594 | |
595 void InspectorOverlay::Reset(const IntSize& viewport_size, | |
596 const IntPoint& document_scroll_offset) { | |
597 std::unique_ptr<protocol::DictionaryValue> reset_data = | |
598 protocol::DictionaryValue::create(); | |
599 reset_data->setDouble( | |
600 "deviceScaleFactor", | |
601 frame_impl_->GetFrame()->GetPage()->DeviceScaleFactorDeprecated()); | |
602 reset_data->setDouble( | |
603 "pageScaleFactor", | |
604 frame_impl_->GetFrame()->GetPage()->GetVisualViewport().Scale()); | |
605 | |
606 IntRect viewport_in_screen = | |
607 frame_impl_->GetFrame()->GetPage()->GetChromeClient().ViewportToScreen( | |
608 IntRect(IntPoint(), viewport_size), frame_impl_->GetFrame()->View()); | |
609 reset_data->setObject("viewportSize", | |
610 BuildObjectForSize(viewport_in_screen.Size())); | |
611 | |
612 // The zoom factor in the overlay frame already has been multiplied by the | |
613 // window to viewport scale (aka device scale factor), so cancel it. | |
614 reset_data->setDouble( | |
615 "pageZoomFactor", | |
616 frame_impl_->GetFrame()->PageZoomFactor() / WindowToViewportScale()); | |
617 | |
618 reset_data->setInteger("scrollX", document_scroll_offset.X()); | |
619 reset_data->setInteger("scrollY", document_scroll_offset.Y()); | |
620 EvaluateInOverlay("reset", std::move(reset_data)); | |
621 } | |
622 | |
623 void InspectorOverlay::EvaluateInOverlay(const String& method, | |
624 const String& argument) { | |
625 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
626 std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create(); | |
627 command->pushValue(protocol::StringValue::create(method)); | |
628 command->pushValue(protocol::StringValue::create(argument)); | |
629 ToLocalFrame(OverlayPage()->MainFrame()) | |
630 ->GetScriptController() | |
631 .ExecuteScriptInMainWorld( | |
632 "dispatch(" + command->serialize() + ")", | |
633 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
634 } | |
635 | |
636 void InspectorOverlay::EvaluateInOverlay( | |
637 const String& method, | |
638 std::unique_ptr<protocol::Value> argument) { | |
639 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
640 std::unique_ptr<protocol::ListValue> command = protocol::ListValue::create(); | |
641 command->pushValue(protocol::StringValue::create(method)); | |
642 command->pushValue(std::move(argument)); | |
643 ToLocalFrame(OverlayPage()->MainFrame()) | |
644 ->GetScriptController() | |
645 .ExecuteScriptInMainWorld( | |
646 "dispatch(" + command->serialize() + ")", | |
647 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
648 } | |
649 | |
650 String InspectorOverlay::EvaluateInOverlayForTest(const String& script) { | |
651 ScriptForbiddenScope::AllowUserAgentScript allow_script; | |
652 v8::HandleScope handle_scope(ToIsolate(OverlayMainFrame())); | |
653 v8::Local<v8::Value> string = | |
654 ToLocalFrame(OverlayPage()->MainFrame()) | |
655 ->GetScriptController() | |
656 .ExecuteScriptInMainWorldAndReturnValue( | |
657 ScriptSourceCode(script), | |
658 ScriptController::kExecuteScriptWhenScriptsDisabled); | |
659 return ToCoreStringWithUndefinedOrNullCheck(string); | |
660 } | |
661 | |
662 void InspectorOverlay::OnTimer(TimerBase*) { | |
663 resize_timer_active_ = false; | |
664 ScheduleUpdate(); | |
665 } | |
666 | |
667 void InspectorOverlay::ClearInternal() { | |
668 if (overlay_page_) { | |
669 overlay_page_->WillBeDestroyed(); | |
670 overlay_page_.Clear(); | |
671 overlay_chrome_client_.Clear(); | |
672 } | |
673 resize_timer_active_ = false; | |
674 paused_in_debugger_message_ = String(); | |
675 inspect_mode_ = InspectorDOMAgent::kNotSearching; | |
676 timer_.Stop(); | |
677 HideHighlight(); | |
678 } | |
679 | |
680 void InspectorOverlay::Clear() { | |
681 ClearInternal(); | |
682 v8_session_ = nullptr; | |
683 dom_agent_.Clear(); | |
684 overlay_host_->SetListener(nullptr); | |
685 } | |
686 | |
687 void InspectorOverlay::OverlayResumed() { | |
688 if (v8_session_) | |
689 v8_session_->resume(); | |
690 } | |
691 | |
692 void InspectorOverlay::OverlaySteppedOver() { | |
693 if (v8_session_) | |
694 v8_session_->stepOver(); | |
695 } | |
696 | |
697 void InspectorOverlay::Suspend() { | |
698 if (!suspended_) { | |
699 suspended_ = true; | |
700 ClearInternal(); | |
701 } | |
702 } | |
703 | |
704 void InspectorOverlay::Resume() { | |
705 suspended_ = false; | |
706 } | |
707 | |
708 void InspectorOverlay::PageLayoutInvalidated(bool resized) { | |
709 if (resized && draw_view_size_) { | |
710 resize_timer_active_ = true; | |
711 timer_.StartOneShot(1, BLINK_FROM_HERE); | |
712 } | |
713 ScheduleUpdate(); | |
714 } | |
715 | |
716 void InspectorOverlay::SetShowViewportSizeOnResize(bool show) { | |
717 draw_view_size_ = show; | |
718 } | |
719 | |
720 bool InspectorOverlay::HandleMouseMove(const WebMouseEvent& event) { | |
721 if (!ShouldSearchForNode()) | |
722 return false; | |
723 | |
724 LocalFrame* frame = frame_impl_->GetFrame(); | |
725 if (!frame || !frame->View() || frame->ContentLayoutItem().IsNull()) | |
726 return false; | |
727 Node* node = HoveredNodeForEvent( | |
728 frame, event, event.GetModifiers() & WebInputEvent::kShiftKey); | |
729 | |
730 // Do not highlight within user agent shadow root unless requested. | |
731 if (inspect_mode_ != InspectorDOMAgent::kSearchingForUAShadow) { | |
732 ShadowRoot* shadow_root = InspectorDOMAgent::UserAgentShadowRoot(node); | |
733 if (shadow_root) | |
734 node = &shadow_root->host(); | |
735 } | |
736 | |
737 // Shadow roots don't have boxes - use host element instead. | |
738 if (node && node->IsShadowRoot()) | |
739 node = node->ParentOrShadowHostNode(); | |
740 | |
741 if (!node) | |
742 return true; | |
743 | |
744 if (node->IsFrameOwnerElement()) { | |
745 HTMLFrameOwnerElement* frame_owner = ToHTMLFrameOwnerElement(node); | |
746 if (frame_owner->ContentFrame() && | |
747 !frame_owner->ContentFrame()->IsLocalFrame()) { | |
748 // Do not consume event so that remote frame can handle it. | |
749 HideHighlight(); | |
750 hovered_node_for_inspect_mode_.Clear(); | |
751 return false; | |
752 } | |
753 } | |
754 | |
755 Node* event_target = (event.GetModifiers() & WebInputEvent::kShiftKey) | |
756 ? HoveredNodeForEvent(frame, event, false) | |
757 : nullptr; | |
758 if (event_target == node) | |
759 event_target = nullptr; | |
760 | |
761 if (node && inspect_mode_highlight_config_) { | |
762 hovered_node_for_inspect_mode_ = node; | |
763 if (dom_agent_) | |
764 dom_agent_->NodeHighlightedInOverlay(node); | |
765 HighlightNode(node, event_target, *inspect_mode_highlight_config_, | |
766 (event.GetModifiers() & | |
767 (WebInputEvent::kControlKey | WebInputEvent::kMetaKey))); | |
768 } | |
769 return true; | |
770 } | |
771 | |
772 bool InspectorOverlay::HandleMouseDown() { | |
773 swallow_next_mouse_up_ = false; | |
774 if (!ShouldSearchForNode()) | |
775 return false; | |
776 | |
777 if (hovered_node_for_inspect_mode_) { | |
778 swallow_next_mouse_up_ = true; | |
779 Inspect(hovered_node_for_inspect_mode_.Get()); | |
780 hovered_node_for_inspect_mode_.Clear(); | |
781 return true; | |
782 } | |
783 return false; | |
784 } | |
785 | |
786 bool InspectorOverlay::HandleMouseUp() { | |
787 if (swallow_next_mouse_up_) { | |
788 swallow_next_mouse_up_ = false; | |
789 return true; | |
790 } | |
791 return false; | |
792 } | |
793 | |
794 bool InspectorOverlay::HandleGestureEvent(const WebGestureEvent& event) { | |
795 if (!ShouldSearchForNode() || event.GetType() != WebInputEvent::kGestureTap) | |
796 return false; | |
797 Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false); | |
798 if (node && inspect_mode_highlight_config_) { | |
799 HighlightNode(node, *inspect_mode_highlight_config_, false); | |
800 Inspect(node); | |
801 return true; | |
802 } | |
803 return false; | |
804 } | |
805 | |
806 bool InspectorOverlay::HandleTouchEvent(const WebTouchEvent& event) { | |
807 if (!ShouldSearchForNode()) | |
808 return false; | |
809 Node* node = HoveredNodeForEvent(frame_impl_->GetFrame(), event, false); | |
810 if (node && inspect_mode_highlight_config_) { | |
811 HighlightNode(node, *inspect_mode_highlight_config_, false); | |
812 Inspect(node); | |
813 return true; | |
814 } | |
815 return false; | |
816 } | |
817 | |
818 bool InspectorOverlay::ShouldSearchForNode() { | |
819 return inspect_mode_ != InspectorDOMAgent::kNotSearching; | |
820 } | |
821 | |
822 void InspectorOverlay::Inspect(Node* node) { | |
823 if (dom_agent_) | |
824 dom_agent_->Inspect(node); | |
825 } | |
826 | |
827 } // namespace blink | |
OLD | NEW |