/* * Copyright (C) 2009, 2015-2016 Apple Inc. All rights reserved. * Copyright (C) 2011 Google Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #pragma once #include "EventTarget.h" #include "InspectorWebAgentBase.h" #include #include #include #include #include #include #include #include namespace Inspector { class InjectedScriptManager; } namespace JSC { class ExecState; class JSValue; } namespace WebCore { class AccessibilityObject; class CharacterData; class DOMEditor; class Document; class Element; class Event; class Exception; class FloatQuad; class Frame; class InspectorHistory; class InspectorOverlay; class InspectorPageAgent; class HitTestResult; class Node; class PseudoElement; class RevalidateStyleAttributeTask; class ShadowRoot; struct HighlightConfig; typedef String ErrorString; typedef int BackendNodeId; struct EventListenerInfo { EventListenerInfo(Node* node, const AtomicString& eventType, EventListenerVector&& eventListenerVector) : node(node) , eventType(eventType) , eventListenerVector(WTFMove(eventListenerVector)) { } Node* node; const AtomicString eventType; const EventListenerVector eventListenerVector; }; class InspectorDOMAgent final : public InspectorAgentBase, public Inspector::DOMBackendDispatcherHandler { WTF_MAKE_NONCOPYABLE(InspectorDOMAgent); WTF_MAKE_FAST_ALLOCATED; public: struct DOMListener { virtual ~DOMListener() = default; virtual void didRemoveDOMNode(Node&, int nodeId) = 0; virtual void didModifyDOMAttr(Element&) = 0; }; InspectorDOMAgent(WebAgentContext&, InspectorPageAgent*, InspectorOverlay*); virtual ~InspectorDOMAgent(); static String toErrorString(ExceptionCode); static String toErrorString(Exception&&); void didCreateFrontendAndBackend(Inspector::FrontendRouter*, Inspector::BackendDispatcher*) override; void willDestroyFrontendAndBackend(Inspector::DisconnectReason) override; Vector documents(); void reset(); // Methods called from the frontend for DOM nodes inspection. void querySelector(ErrorString&, int nodeId, const String& selectors, int* elementId) override; void querySelectorAll(ErrorString&, int nodeId, const String& selectors, RefPtr>& result) override; void getDocument(ErrorString&, RefPtr& root) override; void requestChildNodes(ErrorString&, int nodeId, const int* const depth) override; void setAttributeValue(ErrorString&, int elementId, const String& name, const String& value) override; void setAttributesAsText(ErrorString&, int elementId, const String& text, const String* const name) override; void removeAttribute(ErrorString&, int elementId, const String& name) override; void removeNode(ErrorString&, int nodeId) override; void setNodeName(ErrorString&, int nodeId, const String& name, int* newId) override; void getOuterHTML(ErrorString&, int nodeId, WTF::String* outerHTML) override; void setOuterHTML(ErrorString&, int nodeId, const String& outerHTML) override; void insertAdjacentHTML(ErrorString&, int nodeId, const String& position, const String& html) override; void setNodeValue(ErrorString&, int nodeId, const String& value) override; void getEventListenersForNode(ErrorString&, int nodeId, const WTF::String* const objectGroup, RefPtr>& listenersArray) override; void setEventListenerDisabled(ErrorString&, int eventListenerId, bool disabled) override; void getAccessibilityPropertiesForNode(ErrorString&, int nodeId, RefPtr& axProperties) override; void performSearch(ErrorString&, const String& whitespaceTrimmedQuery, const Inspector::InspectorArray* nodeIds, String* searchId, int* resultCount) override; void getSearchResults(ErrorString&, const String& searchId, int fromIndex, int toIndex, RefPtr>&) override; void discardSearchResults(ErrorString&, const String& searchId) override; void resolveNode(ErrorString&, int nodeId, const String* const objectGroup, RefPtr& result) override; void getAttributes(ErrorString&, int nodeId, RefPtr>& result) override; void setInspectModeEnabled(ErrorString&, bool enabled, const Inspector::InspectorObject* highlightConfig) override; void requestNode(ErrorString&, const String& objectId, int* nodeId) override; void pushNodeByPathToFrontend(ErrorString&, const String& path, int* nodeId) override; void pushNodeByBackendIdToFrontend(ErrorString&, BackendNodeId, int* nodeId) override; void releaseBackendNodeIds(ErrorString&, const String& nodeGroup) override; void hideHighlight(ErrorString&) override; void highlightRect(ErrorString&, int x, int y, int width, int height, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor, const bool* const usePageCoordinates) override; void highlightQuad(ErrorString&, const Inspector::InspectorArray& quad, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor, const bool* const usePageCoordinates) override; void highlightSelector(ErrorString&, const Inspector::InspectorObject& highlightConfig, const String& selectorString, const String* const frameId) override; void highlightNode(ErrorString&, const Inspector::InspectorObject& highlightConfig, const int* const nodeId, const String* const objectId) override; void highlightNodeList(ErrorString&, const Inspector::InspectorArray& nodeIds, const Inspector::InspectorObject& highlightConfig) override; void highlightFrame(ErrorString&, const String& frameId, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor) override; void moveTo(ErrorString&, int nodeId, int targetNodeId, const int* const anchorNodeId, int* newNodeId) override; void undo(ErrorString&) override; void redo(ErrorString&) override; void markUndoableState(ErrorString&) override; void focus(ErrorString&, int nodeId) override; void setInspectedNode(ErrorString&, int nodeId) override; void getEventListeners(Node*, Vector& listenersArray, bool includeAncestors); // InspectorInstrumentation void didInsertDOMNode(Node&); void didRemoveDOMNode(Node&); void willModifyDOMAttr(Element&, const AtomicString& oldValue, const AtomicString& newValue); void didModifyDOMAttr(Element&, const AtomicString& name, const AtomicString& value); void didRemoveDOMAttr(Element&, const AtomicString& name); void characterDataModified(CharacterData&); void didInvalidateStyleAttr(Node&); void didPushShadowRoot(Element& host, ShadowRoot&); void willPopShadowRoot(Element& host, ShadowRoot&); void didChangeCustomElementState(Element&); bool handleTouchEvent(Node&); void didCommitLoad(Document*); void frameDocumentUpdated(Frame&); void pseudoElementCreated(PseudoElement&); void pseudoElementDestroyed(PseudoElement&); void didAddEventListener(EventTarget&); void willRemoveEventListener(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); bool isEventListenerDisabled(EventTarget&, const AtomicString& eventType, EventListener&, bool capture); // Callbacks that don't directly correspond to an instrumentation entry point. void setDocument(Document*); void releaseDanglingNodes(); void mainFrameDOMContentLoaded(); void styleAttributeInvalidated(const Vector& elements); int pushNodeToFrontend(ErrorString&, int documentNodeId, Node*); Node* nodeForId(int nodeId); int boundNodeId(const Node*); void setDOMListener(DOMListener*); BackendNodeId backendNodeIdForNode(Node*, const String& nodeGroup); static String documentURLString(Document*); RefPtr resolveNode(Node*, const String& objectGroup); bool handleMousePress(); void mouseDidMoveOverElement(const HitTestResult&, unsigned modifierFlags); void inspect(Node*); void focusNode(); InspectorHistory* history() { return m_history.get(); } // We represent embedded doms as a part of the same hierarchy. Hence we treat children of frame owners differently. // We also skip whitespace text nodes conditionally. Following methods encapsulate these specifics. static Node* innerFirstChild(Node*); static Node* innerNextSibling(Node*); static Node* innerPreviousSibling(Node*); static unsigned innerChildNodeCount(Node*); static Node* innerParentNode(Node*); static bool isWhitespace(Node*); Node* assertNode(ErrorString&, int nodeId); Element* assertElement(ErrorString&, int nodeId); Document* assertDocument(ErrorString&, int nodeId); static Node* scriptValueAsNode(JSC::JSValue); static JSC::JSValue nodeAsScriptValue(JSC::ExecState&, Node*); // Methods called from other agents. InspectorPageAgent* pageAgent() { return m_pageAgent; } private: void highlightMousedOverNode(); void setSearchingForNode(ErrorString&, bool enabled, const Inspector::InspectorObject* highlightConfig); std::unique_ptr highlightConfigFromInspectorObject(ErrorString&, const Inspector::InspectorObject* highlightInspectorObject); // Node-related methods. typedef HashMap, int> NodeToIdMap; int bind(Node*, NodeToIdMap*); void unbind(Node*, NodeToIdMap*); Node* assertEditableNode(ErrorString&, int nodeId); Element* assertEditableElement(ErrorString&, int nodeId); int pushNodePathToFrontend(Node*); void pushChildNodesToFrontend(int nodeId, int depth = 1); Ref buildObjectForNode(Node*, int depth, NodeToIdMap*); Ref> buildArrayForElementAttributes(Element*); Ref> buildArrayForContainerChildren(Node* container, int depth, NodeToIdMap* nodesMap); RefPtr> buildArrayForPseudoElements(const Element&, NodeToIdMap* nodesMap); Ref buildObjectForEventListener(const RegisteredEventListener&, int identifier, const AtomicString& eventType, Node*, const String* objectGroupId, bool disabled = false); RefPtr buildObjectForAccessibilityProperties(Node*); void processAccessibilityChildren(RefPtr&&, RefPtr>&&); Node* nodeForPath(const String& path); Node* nodeForObjectId(const String& objectId); void discardBindings(); void innerHighlightQuad(std::unique_ptr, const Inspector::InspectorObject* color, const Inspector::InspectorObject* outlineColor, const bool* usePageCoordinates); Inspector::InjectedScriptManager& m_injectedScriptManager; std::unique_ptr m_frontendDispatcher; RefPtr m_backendDispatcher; InspectorPageAgent* m_pageAgent { nullptr }; InspectorOverlay* m_overlay { nullptr }; DOMListener* m_domListener { nullptr }; NodeToIdMap m_documentNodeToIdMap; typedef HashMap, BackendNodeId> NodeToBackendIdMap; HashMap m_nodeGroupToBackendIdMap; // Owns node mappings for dangling nodes. Vector> m_danglingNodeToIdMaps; HashMap m_idToNode; HashMap m_idToNodesMap; HashSet m_childrenRequested; HashMap> m_backendIdToNode; int m_lastNodeId { 1 }; BackendNodeId m_lastBackendNodeId { -1 }; RefPtr m_document; typedef HashMap>> SearchResults; SearchResults m_searchResults; std::unique_ptr m_revalidateStyleAttrTask; RefPtr m_nodeToFocus; RefPtr m_mousedOverNode; std::unique_ptr m_inspectModeHighlightConfig; std::unique_ptr m_history; std::unique_ptr m_domEditor; bool m_searchingForNode { false }; bool m_suppressAttributeModifiedEvent { false }; bool m_documentRequested { false }; struct InspectorEventListener { int identifier { 1 }; RefPtr eventTarget; AtomicString eventType; bool useCapture { false }; bool disabled { false }; InspectorEventListener() { } InspectorEventListener(int identifier, EventTarget& eventTarget, const AtomicString& eventType, bool useCapture) : identifier(identifier) , eventTarget(&eventTarget) , eventType(eventType) , useCapture(useCapture) { } }; HashMap m_eventListenerEntries; int m_lastEventListenerId { 1 }; }; } // namespace WebCore