| 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(FrameViewBase* frame_view_base) override { | |
| 168 if (overlay_->in_layout_) | |
| 169 return; | |
| 170 | |
| 171 client_->ScheduleAnimation(frame_view_base); | |
| 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 FrameView* view = frame_impl_->GetFrameView(); | |
| 405 LocalFrame* frame = frame_impl_->GetFrame(); | |
| 406 if (view && frame) | |
| 407 frame->GetPage()->GetChromeClient().ScheduleAnimation(view); | |
| 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, 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 |