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