/*
 * Copyright (C) 2010, 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.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. 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 INC. 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.
 */

#include "core/inspector/InspectorCSSAgent.h"

#include "bindings/core/v8/ExceptionState.h"
#include "bindings/core/v8/ExceptionStatePlaceholder.h"
#include "core/CSSPropertyNames.h"
#include "core/StylePropertyShorthand.h"
#include "core/animation/css/CSSAnimationData.h"
#include "core/css/CSSColorValue.h"
#include "core/css/CSSComputedStyleDeclaration.h"
#include "core/css/CSSDefaultStyleSheets.h"
#include "core/css/CSSGradientValue.h"
#include "core/css/CSSImportRule.h"
#include "core/css/CSSKeyframeRule.h"
#include "core/css/CSSMediaRule.h"
#include "core/css/CSSRule.h"
#include "core/css/CSSRuleList.h"
#include "core/css/CSSStyleRule.h"
#include "core/css/CSSStyleSheet.h"
#include "core/css/CSSVariableData.h"
#include "core/css/MediaList.h"
#include "core/css/MediaQuery.h"
#include "core/css/MediaValues.h"
#include "core/css/StylePropertySet.h"
#include "core/css/StyleRule.h"
#include "core/css/StyleSheet.h"
#include "core/css/StyleSheetContents.h"
#include "core/css/StyleSheetList.h"
#include "core/css/parser/CSSParser.h"
#include "core/css/resolver/StyleResolver.h"
#include "core/dom/Node.h"
#include "core/dom/StyleChangeReason.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/Text.h"
#include "core/frame/FrameView.h"
#include "core/frame/LocalFrame.h"
#include "core/html/HTMLFrameOwnerElement.h"
#include "core/html/HTMLHeadElement.h"
#include "core/html/VoidCallback.h"
#include "core/inspector/IdentifiersFactory.h"
#include "core/inspector/InspectedFrames.h"
#include "core/inspector/InspectorHistory.h"
#include "core/inspector/InspectorNetworkAgent.h"
#include "core/inspector/InspectorResourceContainer.h"
#include "core/inspector/InspectorResourceContentLoader.h"
#include "core/layout/HitTestResult.h"
#include "core/layout/LayoutObject.h"
#include "core/layout/LayoutObjectInlines.h"
#include "core/layout/LayoutText.h"
#include "core/layout/api/LayoutViewItem.h"
#include "core/layout/line/InlineTextBox.h"
#include "core/loader/DocumentLoader.h"
#include "core/page/Page.h"
#include "core/style/StyleGeneratedImage.h"
#include "core/style/StyleImage.h"
#include "core/svg/SVGElement.h"
#include "platform/fonts/Font.h"
#include "platform/fonts/FontCache.h"
#include "platform/fonts/GlyphBuffer.h"
#include "platform/fonts/shaping/SimpleShaper.h"
#include "platform/text/TextRun.h"
#include "wtf/CurrentTime.h"
#include "wtf/text/CString.h"
#include "wtf/text/StringConcatenate.h"

namespace {

int s_frontendOperationCounter = 0;

class FrontendOperationScope {
public:
    FrontendOperationScope() { ++s_frontendOperationCounter; }
    ~FrontendOperationScope() { --s_frontendOperationCounter; }
};

using namespace blink;

String createShorthandValue(Document* document, const String& shorthand, const String& oldText, const String& longhand, const String& newValue)
{
    StyleSheetContents* styleSheetContents = StyleSheetContents::create(strictCSSParserContext());
    String text = " div { " + shorthand  + ": " + oldText + "; }";
    CSSParser::parseSheet(CSSParserContext(*document, nullptr), styleSheetContents, text);

    CSSStyleSheet* styleSheet = CSSStyleSheet::create(styleSheetContents);
    CSSStyleRule* rule = toCSSStyleRule(styleSheet->item(0));
    CSSStyleDeclaration* style = rule->style();
    TrackExceptionState exceptionState;
    style->setProperty(longhand, newValue, style->getPropertyPriority(longhand), exceptionState);
    return style->getPropertyValue(shorthand);
}

HeapVector<Member<CSSStyleRule>> filterDuplicateRules(CSSRuleList* ruleList)
{
    HeapVector<Member<CSSStyleRule>> uniqRules;
    HeapHashSet<Member<CSSRule>> uniqRulesSet;
    for (unsigned i = ruleList ? ruleList->length() : 0; i > 0; --i) {
        CSSRule* rule = ruleList->item(i - 1);
        if (!rule || rule->type() != CSSRule::kStyleRule || uniqRulesSet.contains(rule))
            continue;
        uniqRulesSet.add(rule);
        uniqRules.append(toCSSStyleRule(rule));
    }
    uniqRules.reverse();
    return uniqRules;
}

// Get the elements which overlap the given rectangle.
HeapVector<Member<Element>> elementsFromRect(LayoutRect rect, Document& document)
{
    HitTestRequest request(HitTestRequest::ReadOnly | HitTestRequest::Active | HitTestRequest::ListBased | HitTestRequest::PenetratingList | HitTestRequest::IgnoreClipping);

    LayoutPoint center = rect.center();
    unsigned leftPadding, rightPadding, topPadding, bottomPadding;
    leftPadding = rightPadding = (rect.width() / 2).toUnsigned();
    topPadding = bottomPadding = (rect.height() / 2).toUnsigned();
    HitTestResult result(request, center, topPadding, rightPadding, bottomPadding, leftPadding);
    document.frame()->contentLayoutItem().hitTest(result);
    return document.elementsFromHitTestResult(result);
}

// Blends the colors from the given gradient with the existing colors.
void blendWithColorsFromGradient(CSSGradientValue* gradient, Vector<Color>& colors, bool& foundNonTransparentColor, bool& foundOpaqueColor, const LayoutObject& layoutObject)
{
    Vector<Color> stopColors;
    gradient->getStopColors(stopColors, layoutObject);

    if (colors.isEmpty()) {
        colors.appendRange(stopColors.begin(), stopColors.end());
    } else {
        if (colors.size() > 1) {
            // Gradient on gradient is too complicated, bail out
            colors.clear();
            return;
        }

        Color existingColor = colors.first();
        colors.clear();
        for (auto stopColor : stopColors) {
            foundNonTransparentColor = foundNonTransparentColor || (stopColor.alpha() != 0);
            colors.append(existingColor.blend(stopColor));
        }
    }
    foundOpaqueColor = foundOpaqueColor || gradient->knownToBeOpaque(layoutObject);
}

// Gets the colors from an image style, if one exists and it is a gradient.
void addColorsFromImageStyle(const ComputedStyle& style, Vector<Color>& colors, bool& foundOpaqueColor, bool& foundNonTransparentColor, const LayoutObject& layoutObject)
{
    const FillLayer& backgroundLayers = style.backgroundLayers();
    if (!backgroundLayers.hasImage())
        return;

    StyleImage* styleImage = backgroundLayers.image();
    // hasImage() does not always indicate that this is non-null
    if (!styleImage)
        return;

    if (!styleImage->isGeneratedImage()) {
        // Make no assertions about the colors in non-generated images
        colors.clear();
        foundOpaqueColor = false;
        return;
    }

    StyleGeneratedImage* genImage = toStyleGeneratedImage(styleImage);
    CSSValue* imageCSS = genImage->cssValue();
    if (imageCSS->isGradientValue()) {
        CSSGradientValue* gradient = toCSSGradientValue(imageCSS);
        blendWithColorsFromGradient(gradient, colors, foundNonTransparentColor, foundOpaqueColor, layoutObject);
    }
    return;
}

// Get the background colors behind the given rect in the given document, by
// walking up all the elements returned by a hit test (but not going beyond
// |topElement|) covering the area of the rect, and blending their background
// colors.
bool getColorsFromRect(LayoutRect rect, Document& document, Element* topElement, Vector<Color>& colors)
{
    HeapVector<Member<Element>> elementsUnderRect = elementsFromRect(rect, document);

    bool foundOpaqueColor = false;
    bool foundTopElement = false;

    for (auto e = elementsUnderRect.rbegin(); !foundTopElement && e != elementsUnderRect.rend(); ++e) {
        const Element* element = *e;
        if (element == topElement)
            foundTopElement = true;

        const LayoutObject* layoutObject = element->layoutObject();
        if (!layoutObject)
            continue;

        if (isHTMLCanvasElement(element) || isHTMLEmbedElement(element) || isHTMLImageElement(element) || isHTMLObjectElement(element) || isHTMLPictureElement(element) || element->isSVGElement() || isHTMLVideoElement(element)) {
            colors.clear();
            foundOpaqueColor = false;
            continue;
        }

        const ComputedStyle* style = layoutObject->style();
        if (!style)
            continue;

        Color backgroundColor = style->visitedDependentColor(CSSPropertyBackgroundColor);
        bool foundNonTransparentColor = false;
        if (backgroundColor.alpha() != 0) {
            foundNonTransparentColor = true;
            if (colors.isEmpty()) {
                if (!backgroundColor.hasAlpha())
                    foundOpaqueColor = true;
                colors.append(backgroundColor);
            } else {
                if (!backgroundColor.hasAlpha()) {
                    colors.clear();
                    colors.append(backgroundColor);
                    foundOpaqueColor = true;
                } else {
                    for (size_t i = 0; i < colors.size(); i++)
                        colors[i] = colors[i].blend(backgroundColor);
                    foundOpaqueColor = foundOpaqueColor || backgroundColor.hasAlpha();
                }
            }
        }

        addColorsFromImageStyle(*style, colors, foundOpaqueColor, foundNonTransparentColor, *layoutObject);

        bool contains = foundTopElement || element->boundingBox().contains(rect);
        if (!contains && foundNonTransparentColor) {
            // Only return colors if some opaque element covers up this one.
            colors.clear();
            foundOpaqueColor = false;
        }
    }
    return foundOpaqueColor;
}

} // namespace

namespace CSSAgentState {
static const char cssAgentEnabled[] = "cssAgentEnabled";
}

typedef blink::protocol::CSS::Backend::EnableCallback EnableCallback;

namespace blink {

enum ForcePseudoClassFlags {
    PseudoNone = 0,
    PseudoHover = 1 << 0,
    PseudoFocus = 1 << 1,
    PseudoActive = 1 << 2,
    PseudoVisited = 1 << 3
};

static unsigned computePseudoClassMask(std::unique_ptr<protocol::Array<String>> pseudoClassArray)
{
    DEFINE_STATIC_LOCAL(String, active, ("active"));
    DEFINE_STATIC_LOCAL(String, hover, ("hover"));
    DEFINE_STATIC_LOCAL(String, focus, ("focus"));
    DEFINE_STATIC_LOCAL(String, visited, ("visited"));
    if (!pseudoClassArray || !pseudoClassArray->length())
        return PseudoNone;

    unsigned result = PseudoNone;
    for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
        String pseudoClass = pseudoClassArray->get(i);
        if (pseudoClass == active)
            result |= PseudoActive;
        else if (pseudoClass == hover)
            result |= PseudoHover;
        else if (pseudoClass == focus)
            result |= PseudoFocus;
        else if (pseudoClass == visited)
            result |= PseudoVisited;
    }

    return result;
}

class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
    WTF_MAKE_NONCOPYABLE(StyleSheetAction);
public:
    StyleSheetAction(const String& name)
        : InspectorHistory::Action(name)
    {
    }

    virtual std::unique_ptr<protocol::CSS::CSSStyle> takeSerializedStyle()
    {
        return nullptr;
    }
};

class InspectorCSSAgent::SetStyleSheetTextAction final : public InspectorCSSAgent::StyleSheetAction {
    WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction);
public:
    SetStyleSheetTextAction(InspectorStyleSheetBase* styleSheet, const String& text)
        : InspectorCSSAgent::StyleSheetAction("SetStyleSheetText")
        , m_styleSheet(styleSheet)
        , m_text(text)
    {
    }

    bool perform(ExceptionState& exceptionState) override
    {
        if (!m_styleSheet->getText(&m_oldText))
            return false;
        return redo(exceptionState);
    }

    bool undo(ExceptionState& exceptionState) override
    {
        return m_styleSheet->setText(m_oldText, exceptionState);
    }

    bool redo(ExceptionState& exceptionState) override
    {
        return m_styleSheet->setText(m_text, exceptionState);
    }

    String mergeId() override
    {
        return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data());
    }

    void merge(Action* action) override
    {
        ASSERT(action->mergeId() == mergeId());

        SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action);
        m_text = other->m_text;
    }

    DEFINE_INLINE_VIRTUAL_TRACE()
    {
        visitor->trace(m_styleSheet);
        InspectorCSSAgent::StyleSheetAction::trace(visitor);
    }

private:
    Member<InspectorStyleSheetBase> m_styleSheet;
    String m_text;
    String m_oldText;
};

class InspectorCSSAgent::ModifyRuleAction final : public InspectorCSSAgent::StyleSheetAction {
    WTF_MAKE_NONCOPYABLE(ModifyRuleAction);
public:
    enum Type {
        SetRuleSelector,
        SetStyleText,
        SetMediaRuleText,
        SetKeyframeKey
    };

    ModifyRuleAction(Type type, InspectorStyleSheet* styleSheet, const SourceRange& range, const String& text)
        : InspectorCSSAgent::StyleSheetAction("ModifyRuleAction")
        , m_styleSheet(styleSheet)
        , m_type(type)
        , m_newText(text)
        , m_oldRange(range)
        , m_cssRule(nullptr)
    {
    }

    bool perform(ExceptionState& exceptionState) override
    {
        return redo(exceptionState);
    }

    bool undo(ExceptionState& exceptionState) override
    {
        switch (m_type) {
        case SetRuleSelector:
            return m_styleSheet->setRuleSelector(m_newRange, m_oldText, nullptr, nullptr, exceptionState);
        case SetStyleText:
            return m_styleSheet->setStyleText(m_newRange, m_oldText, nullptr, nullptr, exceptionState);
        case SetMediaRuleText:
            return m_styleSheet->setMediaRuleText(m_newRange, m_oldText, nullptr, nullptr, exceptionState);
        case SetKeyframeKey:
            return m_styleSheet->setKeyframeKey(m_newRange, m_oldText, nullptr, nullptr, exceptionState);
        default:
            ASSERT_NOT_REACHED();
        }
        return false;
    }

    bool redo(ExceptionState& exceptionState) override
    {
        switch (m_type) {
        case SetRuleSelector:
            m_cssRule = m_styleSheet->setRuleSelector(m_oldRange, m_newText, &m_newRange, &m_oldText, exceptionState);
            break;
        case SetStyleText:
            m_cssRule = m_styleSheet->setStyleText(m_oldRange, m_newText, &m_newRange, &m_oldText, exceptionState);
            break;
        case SetMediaRuleText:
            m_cssRule = m_styleSheet->setMediaRuleText(m_oldRange, m_newText, &m_newRange, &m_oldText, exceptionState);
            break;
        case SetKeyframeKey:
            m_cssRule = m_styleSheet->setKeyframeKey(m_oldRange, m_newText, &m_newRange, &m_oldText, exceptionState);
            break;
        default:
            ASSERT_NOT_REACHED();
        }
        return m_cssRule;
    }

    CSSRule* takeRule()
    {
        CSSRule* result = m_cssRule;
        m_cssRule = nullptr;
        return result;
    }

    std::unique_ptr<protocol::CSS::CSSStyle> takeSerializedStyle() override
    {
        if (m_type != SetStyleText)
            return nullptr;
        CSSRule* rule = takeRule();
        if (rule->type() == CSSRule::kStyleRule)
            return m_styleSheet->buildObjectForStyle(toCSSStyleRule(rule)->style());
        if (rule->type() == CSSRule::kKeyframeRule)
            return m_styleSheet->buildObjectForStyle(toCSSKeyframeRule(rule)->style());
        return nullptr;
    }

    DEFINE_INLINE_VIRTUAL_TRACE()
    {
        visitor->trace(m_styleSheet);
        visitor->trace(m_cssRule);
        InspectorCSSAgent::StyleSheetAction::trace(visitor);
    }

    String mergeId() override
    {
        return String::format("ModifyRuleAction:%d %s:%d", m_type, m_styleSheet->id().utf8().data(), m_oldRange.start);
    }

    bool isNoop() override
    {
        return m_oldText == m_newText;
    }

    void merge(Action* action) override
    {
        ASSERT(action->mergeId() == mergeId());

        ModifyRuleAction* other = static_cast<ModifyRuleAction*>(action);
        m_newText = other->m_newText;
        m_newRange = other->m_newRange;
    }

private:
    Member<InspectorStyleSheet> m_styleSheet;
    Type m_type;
    String m_oldText;
    String m_newText;
    SourceRange m_oldRange;
    SourceRange m_newRange;
    Member<CSSRule> m_cssRule;
};

class InspectorCSSAgent::SetElementStyleAction final : public InspectorCSSAgent::StyleSheetAction {
    WTF_MAKE_NONCOPYABLE(SetElementStyleAction);
public:
    SetElementStyleAction(InspectorStyleSheetForInlineStyle* styleSheet, const String& text)
        : InspectorCSSAgent::StyleSheetAction("SetElementStyleAction")
        , m_styleSheet(styleSheet)
        , m_text(text)
    {
    }

    bool perform(ExceptionState& exceptionState) override
    {
        return redo(exceptionState);
    }

    bool undo(ExceptionState& exceptionState) override
    {
        return m_styleSheet->setText(m_oldText, exceptionState);
    }

    bool redo(ExceptionState& exceptionState) override
    {
        if (!m_styleSheet->getText(&m_oldText))
            return false;
        return m_styleSheet->setText(m_text, exceptionState);
    }

    DEFINE_INLINE_VIRTUAL_TRACE()
    {
        visitor->trace(m_styleSheet);
        InspectorCSSAgent::StyleSheetAction::trace(visitor);
    }

    String mergeId() override
    {
        return String::format("SetElementStyleAction:%s", m_styleSheet->id().utf8().data());
    }

    std::unique_ptr<protocol::CSS::CSSStyle> takeSerializedStyle() override
    {
        return m_styleSheet->buildObjectForStyle(m_styleSheet->inlineStyle());
    }

    void merge(Action* action) override
    {
        ASSERT(action->mergeId() == mergeId());

        SetElementStyleAction* other = static_cast<SetElementStyleAction*>(action);
        m_text = other->m_text;
    }

private:
    Member<InspectorStyleSheetForInlineStyle> m_styleSheet;
    String m_text;
    String m_oldText;
};

class InspectorCSSAgent::AddRuleAction final : public InspectorCSSAgent::StyleSheetAction {
    WTF_MAKE_NONCOPYABLE(AddRuleAction);
public:
    AddRuleAction(InspectorStyleSheet* styleSheet, const String& ruleText, const SourceRange& location)
        : InspectorCSSAgent::StyleSheetAction("AddRule")
        , m_styleSheet(styleSheet)
        , m_ruleText(ruleText)
        , m_location(location)
    {
    }

    bool perform(ExceptionState& exceptionState) override
    {
        return redo(exceptionState);
    }

    bool undo(ExceptionState& exceptionState) override
    {
        return m_styleSheet->deleteRule(m_addedRange, exceptionState);
    }

    bool redo(ExceptionState& exceptionState) override
    {
        m_cssRule = m_styleSheet->addRule(m_ruleText, m_location, &m_addedRange, exceptionState);
        if (exceptionState.hadException())
            return false;
        return true;
    }

    CSSStyleRule* takeRule()
    {
        CSSStyleRule* result = m_cssRule;
        m_cssRule = nullptr;
        return result;
    }

    DEFINE_INLINE_VIRTUAL_TRACE()
    {
        visitor->trace(m_styleSheet);
        visitor->trace(m_cssRule);
        InspectorCSSAgent::StyleSheetAction::trace(visitor);
    }

private:
    Member<InspectorStyleSheet> m_styleSheet;
    Member<CSSStyleRule> m_cssRule;
    String m_ruleText;
    String m_oldText;
    SourceRange m_location;
    SourceRange m_addedRange;
};

// static
CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
{
    if (!rule || rule->type() != CSSRule::kStyleRule)
        return nullptr;
    return toCSSStyleRule(rule);
}

// static
CSSMediaRule* InspectorCSSAgent::asCSSMediaRule(CSSRule* rule)
{
    if (!rule || rule->type() != CSSRule::kMediaRule)
        return nullptr;
    return toCSSMediaRule(rule);
}

InspectorCSSAgent::InspectorCSSAgent(InspectorDOMAgent* domAgent, InspectedFrames* inspectedFrames, InspectorNetworkAgent* networkAgent, InspectorResourceContentLoader* resourceContentLoader, InspectorResourceContainer* resourceContainer)
    : m_domAgent(domAgent)
    , m_inspectedFrames(inspectedFrames)
    , m_networkAgent(networkAgent)
    , m_resourceContentLoader(resourceContentLoader)
    , m_resourceContainer(resourceContainer)
    , m_resourceContentLoaderClientId(resourceContentLoader->createClientId())
{
}

InspectorCSSAgent::~InspectorCSSAgent()
{
}

void InspectorCSSAgent::restore()
{
    if (m_state->booleanProperty(CSSAgentState::cssAgentEnabled, false))
        wasEnabled();
}

void InspectorCSSAgent::flushPendingProtocolNotifications()
{
    if (!m_invalidatedDocuments.size())
        return;
    HeapHashSet<Member<Document>> invalidatedDocuments;
    m_invalidatedDocuments.swap(invalidatedDocuments);
    for (Document* document: invalidatedDocuments)
        updateActiveStyleSheets(document, ExistingFrontendRefresh);
}

void InspectorCSSAgent::reset()
{
    m_idToInspectorStyleSheet.clear();
    m_idToInspectorStyleSheetForInlineStyle.clear();
    m_cssStyleSheetToInspectorStyleSheet.clear();
    m_documentToCSSStyleSheets.clear();
    m_invalidatedDocuments.clear();
    m_nodeToInspectorStyleSheet.clear();
    resetNonPersistentData();
}

void InspectorCSSAgent::resetNonPersistentData()
{
    resetPseudoStates();
}

void InspectorCSSAgent::enable(std::unique_ptr<EnableCallback> prpCallback)
{
    if (!m_domAgent->enabled()) {
        prpCallback->sendFailure("DOM agent needs to be enabled first.");
        return;
    }
    m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
    m_resourceContentLoader->ensureResourcesContentLoaded(m_resourceContentLoaderClientId, WTF::bind(&InspectorCSSAgent::resourceContentLoaded, wrapPersistent(this), passed(std::move(prpCallback))));
}

void InspectorCSSAgent::resourceContentLoaded(std::unique_ptr<EnableCallback> callback)
{
    wasEnabled();
    callback->sendSuccess();
}

void InspectorCSSAgent::wasEnabled()
{
    if (!m_state->booleanProperty(CSSAgentState::cssAgentEnabled, false)) {
        // We were disabled while fetching resources.
        return;
    }

    m_instrumentingAgents->addInspectorCSSAgent(this);
    m_domAgent->setDOMListener(this);
    HeapVector<Member<Document>> documents = m_domAgent->documents();
    for (Document* document : documents)
        updateActiveStyleSheets(document, InitialFrontendLoad);
}

void InspectorCSSAgent::disable(ErrorString*)
{
    reset();
    m_domAgent->setDOMListener(nullptr);
    m_instrumentingAgents->removeInspectorCSSAgent(this);
    m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
    m_resourceContentLoader->cancel(m_resourceContentLoaderClientId);
}

void InspectorCSSAgent::didCommitLoadForLocalFrame(LocalFrame* frame)
{
    if (frame == m_inspectedFrames->root())
        reset();
}

void InspectorCSSAgent::mediaQueryResultChanged()
{
    flushPendingProtocolNotifications();
    frontend()->mediaQueryResultChanged();
}

void InspectorCSSAgent::fontsUpdated()
{
    flushPendingProtocolNotifications();
    frontend()->fontsUpdated();
}

void InspectorCSSAgent::activeStyleSheetsUpdated(Document* document)
{
    m_invalidatedDocuments.add(document);
}

void InspectorCSSAgent::updateActiveStyleSheets(Document* document, StyleSheetsUpdateType styleSheetsUpdateType)
{
    HeapVector<Member<CSSStyleSheet>> newSheetsVector;
    InspectorCSSAgent::collectAllDocumentStyleSheets(document, newSheetsVector);
    setActiveStyleSheets(document, newSheetsVector, styleSheetsUpdateType);
}

void InspectorCSSAgent::setActiveStyleSheets(Document* document, const HeapVector<Member<CSSStyleSheet>>& allSheetsVector, StyleSheetsUpdateType styleSheetsUpdateType)
{
    bool isInitialFrontendLoad = styleSheetsUpdateType == InitialFrontendLoad;

    HeapHashSet<Member<CSSStyleSheet>>* documentCSSStyleSheets = m_documentToCSSStyleSheets.get(document);
    if (!documentCSSStyleSheets) {
        documentCSSStyleSheets = new HeapHashSet<Member<CSSStyleSheet>>();
        m_documentToCSSStyleSheets.set(document, documentCSSStyleSheets);
    }

    HeapHashSet<Member<CSSStyleSheet>> removedSheets(*documentCSSStyleSheets);
    HeapVector<Member<CSSStyleSheet>> addedSheets;
    for (CSSStyleSheet* cssStyleSheet : allSheetsVector) {
        if (removedSheets.contains(cssStyleSheet)) {
            removedSheets.remove(cssStyleSheet);
            if (isInitialFrontendLoad)
                addedSheets.append(cssStyleSheet);
        } else {
            addedSheets.append(cssStyleSheet);
        }
    }

    for (CSSStyleSheet* cssStyleSheet : removedSheets) {
        InspectorStyleSheet* inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(cssStyleSheet);
        ASSERT(inspectorStyleSheet);

        documentCSSStyleSheets->remove(cssStyleSheet);
        if (m_idToInspectorStyleSheet.contains(inspectorStyleSheet->id())) {
            String id = unbindStyleSheet(inspectorStyleSheet);
            if (frontend() && !isInitialFrontendLoad)
                frontend()->styleSheetRemoved(id);
        }
    }

    for (CSSStyleSheet* cssStyleSheet : addedSheets) {
        bool isNew = isInitialFrontendLoad || !m_cssStyleSheetToInspectorStyleSheet.contains(cssStyleSheet);
        if (isNew) {
            InspectorStyleSheet* newStyleSheet = bindStyleSheet(cssStyleSheet);
            documentCSSStyleSheets->add(cssStyleSheet);
            if (frontend())
                frontend()->styleSheetAdded(newStyleSheet->buildObjectForStyleSheetInfo());
        }
    }

    if (documentCSSStyleSheets->isEmpty())
        m_documentToCSSStyleSheets.remove(document);
}

void InspectorCSSAgent::documentDetached(Document* document)
{
    m_invalidatedDocuments.remove(document);
    setActiveStyleSheets(document, HeapVector<Member<CSSStyleSheet>>(), ExistingFrontendRefresh);
}

bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
{
    if (m_nodeIdToForcedPseudoState.isEmpty())
        return false;

    int nodeId = m_domAgent->boundNodeId(element);
    if (!nodeId)
        return false;

    NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
    if (it == m_nodeIdToForcedPseudoState.end())
        return false;

    unsigned forcedPseudoState = it->value;
    switch (pseudoType) {
    case CSSSelector::PseudoActive:
        return forcedPseudoState & PseudoActive;
    case CSSSelector::PseudoFocus:
        return forcedPseudoState & PseudoFocus;
    case CSSSelector::PseudoHover:
        return forcedPseudoState & PseudoHover;
    case CSSSelector::PseudoVisited:
        return forcedPseudoState & PseudoVisited;
    default:
        return false;
    }
}

void InspectorCSSAgent::getMediaQueries(ErrorString* errorString, std::unique_ptr<protocol::Array<protocol::CSS::CSSMedia>>* medias)
{
    *medias = protocol::Array<protocol::CSS::CSSMedia>::create();
    for (auto& style : m_idToInspectorStyleSheet) {
        InspectorStyleSheet* styleSheet = style.value;
        collectMediaQueriesFromStyleSheet(styleSheet->pageStyleSheet(), medias->get());
        const CSSRuleVector& flatRules = styleSheet->flatRules();
        for (unsigned i = 0; i < flatRules.size(); ++i) {
            CSSRule* rule = flatRules.at(i).get();
            if (rule->type() == CSSRule::kMediaRule || rule->type() == CSSRule::kImportRule)
                collectMediaQueriesFromRule(rule, medias->get());
        }
    }
}

void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, Maybe<protocol::CSS::CSSStyle>* inlineStyle, Maybe<protocol::CSS::CSSStyle>* attributesStyle, Maybe<protocol::Array<protocol::CSS::RuleMatch>>* matchedCSSRules, Maybe<protocol::Array<protocol::CSS::PseudoElementMatches>>* pseudoIdMatches, Maybe<protocol::Array<protocol::CSS::InheritedStyleEntry>>* inheritedEntries, Maybe<protocol::Array<protocol::CSS::CSSKeyframesRule>>* cssKeyframesRules)
{
    Element* element = elementForId(errorString, nodeId);
    if (!element) {
        *errorString = "Node not found";
        return;
    }

    Element* originalElement = element;
    PseudoId elementPseudoId = element->getPseudoId();
    if (elementPseudoId) {
        element = element->parentOrShadowHostElement();
        if (!element) {
            *errorString = "Pseudo element has no parent";
            return;
        }
    }

    Document* ownerDocument = element->ownerDocument();
    // A non-active document has no styles.
    if (!ownerDocument->isActive()) {
        *errorString = "Document is not active";
        return;
    }

    // FIXME: It's really gross for the inspector to reach in and access StyleResolver
    // directly here. We need to provide the Inspector better APIs to get this information
    // without grabbing at internal style classes!

    // Matched rules.
    StyleResolver& styleResolver = ownerDocument->ensureStyleResolver();

    element->updateDistribution();
    CSSRuleList* matchedRules = styleResolver.pseudoCSSRulesForElement(element, elementPseudoId, StyleResolver::AllCSSRules);
    *matchedCSSRules = buildArrayForMatchedRuleList(matchedRules, originalElement, PseudoIdNone);

    // Pseudo elements.
    if (elementPseudoId)
        return;

    InspectorStyleSheetForInlineStyle* inlineStyleSheet = asInspectorStyleSheet(element);
    if (inlineStyleSheet) {
        *inlineStyle = inlineStyleSheet->buildObjectForStyle(element->style());
        *attributesStyle = buildObjectForAttributesStyle(element);
    }

    *pseudoIdMatches = protocol::Array<protocol::CSS::PseudoElementMatches>::create();
    for (PseudoId pseudoId = FirstPublicPseudoId; pseudoId < AfterLastInternalPseudoId; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
        CSSRuleList* matchedRules = styleResolver.pseudoCSSRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
        protocol::DOM::PseudoType pseudoType;
        if (matchedRules && matchedRules->length() && m_domAgent->getPseudoElementType(pseudoId, &pseudoType)) {
            pseudoIdMatches->fromJust()->addItem(protocol::CSS::PseudoElementMatches::create()
                .setPseudoType(pseudoType)
                .setMatches(buildArrayForMatchedRuleList(matchedRules, element, pseudoId)).build());
        }
    }

    // Inherited styles.
    *inheritedEntries = protocol::Array<protocol::CSS::InheritedStyleEntry>::create();
    Element* parentElement = element->parentOrShadowHostElement();
    while (parentElement) {
        StyleResolver& parentStyleResolver = parentElement->ownerDocument()->ensureStyleResolver();
        CSSRuleList* parentMatchedRules = parentStyleResolver.cssRulesForElement(parentElement, StyleResolver::AllCSSRules);
        std::unique_ptr<protocol::CSS::InheritedStyleEntry> entry = protocol::CSS::InheritedStyleEntry::create()
            .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules, parentElement, PseudoIdNone)).build();
        if (parentElement->style() && parentElement->style()->length()) {
            InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
            if (styleSheet)
                entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->inlineStyle()));
        }

        inheritedEntries->fromJust()->addItem(std::move(entry));
        parentElement = parentElement->parentOrShadowHostElement();
    }

    *cssKeyframesRules = animationsForNode(element);
}

template<class CSSRuleCollection>
static CSSKeyframesRule* findKeyframesRule(CSSRuleCollection* cssRules, StyleRuleKeyframes* keyframesRule)
{
    CSSKeyframesRule* result = 0;
    for (unsigned j = 0; cssRules && j < cssRules->length() && !result; ++j) {
        CSSRule* cssRule = cssRules->item(j);
        if (cssRule->type() == CSSRule::kKeyframesRule) {
            CSSKeyframesRule* cssStyleRule = toCSSKeyframesRule(cssRule);
            if (cssStyleRule->keyframes() == keyframesRule)
                result = cssStyleRule;
        } else if (cssRule->type() == CSSRule::kImportRule) {
            CSSImportRule* cssImportRule = toCSSImportRule(cssRule);
            result = findKeyframesRule(cssImportRule->styleSheet(), keyframesRule);
        } else {
            result = findKeyframesRule(cssRule->cssRules(), keyframesRule);
        }
    }
    return result;
}

std::unique_ptr<protocol::Array<protocol::CSS::CSSKeyframesRule>> InspectorCSSAgent::animationsForNode(Element* element)
{
    std::unique_ptr<protocol::Array<protocol::CSS::CSSKeyframesRule>> cssKeyframesRules = protocol::Array<protocol::CSS::CSSKeyframesRule>::create();
    Document* ownerDocument = element->ownerDocument();

    StyleResolver& styleResolver = ownerDocument->ensureStyleResolver();
    RefPtr<ComputedStyle> style = styleResolver.styleForElement(element);
    if (!style)
        return cssKeyframesRules;
    const CSSAnimationData* animationData = style->animations();
    for (size_t i = 0; animationData && i < animationData->nameList().size(); ++i) {
        AtomicString animationName(animationData->nameList()[i]);
        if (animationName == CSSAnimationData::initialName())
            continue;
        StyleRuleKeyframes* keyframesRule = styleResolver.findKeyframesRule(element, animationName);
        if (!keyframesRule)
            continue;

        // Find CSSOM wrapper.
        CSSKeyframesRule* cssKeyframesRule = nullptr;
        for (CSSStyleSheet* styleSheet : *m_documentToCSSStyleSheets.get(ownerDocument)) {
            cssKeyframesRule = findKeyframesRule(styleSheet, keyframesRule);
            if (cssKeyframesRule)
                break;
        }
        if (!cssKeyframesRule)
            continue;

        std::unique_ptr<protocol::Array<protocol::CSS::CSSKeyframeRule>> keyframes = protocol::Array<protocol::CSS::CSSKeyframeRule>::create();
        for (unsigned j = 0; j < cssKeyframesRule->length(); ++j) {
            InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(cssKeyframesRule->parentStyleSheet());
            keyframes->addItem(inspectorStyleSheet->buildObjectForKeyframeRule(cssKeyframesRule->item(j)));
        }

        InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(cssKeyframesRule->parentStyleSheet());
        CSSRuleSourceData* sourceData = inspectorStyleSheet->sourceDataForRule(cssKeyframesRule);
        std::unique_ptr<protocol::CSS::Value> name = protocol::CSS::Value::create().setText(cssKeyframesRule->name()).build();
        if (sourceData)
            name->setRange(inspectorStyleSheet->buildSourceRangeObject(sourceData->ruleHeaderRange));
        cssKeyframesRules->addItem(protocol::CSS::CSSKeyframesRule::create()
            .setAnimationName(std::move(name))
            .setKeyframes(std::move(keyframes)).build());
    }
    return cssKeyframesRules;
}

void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, Maybe<protocol::CSS::CSSStyle>* inlineStyle, Maybe<protocol::CSS::CSSStyle>* attributesStyle)
{
    Element* element = elementForId(errorString, nodeId);
    if (!element)
        return;

    InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
    if (!styleSheet)
        return;

    *inlineStyle = styleSheet->buildObjectForStyle(element->style());
    *attributesStyle = buildObjectForAttributesStyle(element);
}

void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, std::unique_ptr<protocol::Array<protocol::CSS::CSSComputedStyleProperty>>* style)
{
    Node* node = m_domAgent->assertNode(errorString, nodeId);
    if (!node)
        return;

    CSSComputedStyleDeclaration* computedStyleInfo = CSSComputedStyleDeclaration::create(node, true);
    *style = protocol::Array<protocol::CSS::CSSComputedStyleProperty>::create();
    for (int id = firstCSSProperty; id <= lastCSSProperty; ++id) {
        CSSPropertyID propertyId = static_cast<CSSPropertyID>(id);
        if (!CSSPropertyMetadata::isEnabledProperty(propertyId) || isShorthandProperty(propertyId) || CSSPropertyMetadata::isDescriptorOnly(propertyId))
            continue;
        (*style)->addItem(protocol::CSS::CSSComputedStyleProperty::create()
            .setName(getPropertyNameString(propertyId))
            .setValue(computedStyleInfo->getPropertyValue(propertyId)).build());
    }

    std::unique_ptr<HashMap<AtomicString, RefPtr<CSSVariableData>>> variables = computedStyleInfo->getVariables();

    if (variables && !variables->isEmpty()) {
        for (const auto& it : *variables) {
            if (!it.value)
                continue;
            (*style)->addItem(protocol::CSS::CSSComputedStyleProperty::create()
                .setName(it.key)
                .setValue(it.value->tokenRange().serialize()).build());
        }
    }
}

void InspectorCSSAgent::collectPlatformFontsForLayoutObject(LayoutObject* layoutObject, HashCountedSet<std::pair<int, String>>* fontStats)
{
    if (!layoutObject->isText())
        return;

    FontCachePurgePreventer preventer;
    LayoutText* layoutText = toLayoutText(layoutObject);
    for (InlineTextBox* box = layoutText->firstTextBox(); box; box = box->nextTextBox()) {
        const ComputedStyle& style = layoutText->styleRef(box->isFirstLineStyle());
        const Font& font = style.font();
        TextRun run = box->constructTextRunForInspector(style);
        TextRunPaintInfo paintInfo(run);
        GlyphBuffer glyphBuffer;
        font.buildGlyphBuffer(paintInfo, glyphBuffer);
        for (unsigned i = 0; i < glyphBuffer.size(); ++i) {
            const SimpleFontData* simpleFontData = glyphBuffer.fontDataAt(i);
            String familyName = simpleFontData->platformData().fontFamilyName();
            if (familyName.isNull())
                familyName = "";
            fontStats->add(std::make_pair(simpleFontData->isCustomFont() ? 1 : 0, familyName));
        }
    }
}

void InspectorCSSAgent::getPlatformFontsForNode(ErrorString* errorString, int nodeId,
    std::unique_ptr<protocol::Array<protocol::CSS::PlatformFontUsage>>* platformFonts)
{
    Node* node = m_domAgent->assertNode(errorString, nodeId);
    if (!node)
        return;

    HashCountedSet<std::pair<int, String>> fontStats;
    LayoutObject* root = node->layoutObject();
    if (root) {
        collectPlatformFontsForLayoutObject(root, &fontStats);
        // Iterate upto two layers deep.
        for (LayoutObject* child = root->slowFirstChild(); child; child = child->nextSibling()) {
            collectPlatformFontsForLayoutObject(child, &fontStats);
            for (LayoutObject* child2 = child->slowFirstChild(); child2; child2 = child2->nextSibling())
                collectPlatformFontsForLayoutObject(child2, &fontStats);
        }
    }
    *platformFonts = protocol::Array<protocol::CSS::PlatformFontUsage>::create();
    for (auto& font : fontStats) {
        std::pair<int, String>& fontDescription = font.key;
        bool isCustomFont = fontDescription.first == 1;
        String fontName = fontDescription.second;
        (*platformFonts)->addItem(protocol::CSS::PlatformFontUsage::create()
            .setFamilyName(fontName)
            .setIsCustomFont(isCustomFont)
            .setGlyphCount(font.value).build());
    }
}

void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
{
    InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet)
        return;

    inspectorStyleSheet->getText(result);
}

void InspectorCSSAgent::collectClassNames(ErrorString* errorString, const String& styleSheetId, std::unique_ptr<protocol::Array<String>>* classNames)
{
    IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
    if (it == m_idToInspectorStyleSheet.end()) {
        *errorString = "No style sheet with given id found";
        return;
    }
    *classNames = it->value.get()->collectClassNames();
}

void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text, protocol::Maybe<String>* sourceMapURL)
{
    FrontendOperationScope scope;
    InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet) {
        *errorString = "Style sheet with id " + styleSheetId + " not found";
        return;
    }

    TrackExceptionState exceptionState;
    m_domAgent->history()->perform(new SetStyleSheetTextAction(inspectorStyleSheet, text), exceptionState);
    *errorString = InspectorDOMAgent::toErrorString(exceptionState);
    if (!inspectorStyleSheet->sourceMapURL().isEmpty())
        *sourceMapURL = inspectorStyleSheet->sourceMapURL();
}

static bool verifyRangeComponent(ErrorString* errorString, bool valid, const String& component)
{
    if (!valid)
        *errorString = "range." + component + " must be a non-negative integer";
    return valid;
}

static bool jsonRangeToSourceRange(ErrorString* errorString, InspectorStyleSheetBase* inspectorStyleSheet, protocol::CSS::SourceRange* range, SourceRange* sourceRange)
{
    if (!verifyRangeComponent(errorString, range->getStartLine() >= 0, "startLine")
        || !verifyRangeComponent(errorString, range->getStartColumn() >= 0, "startColumn")
        || !verifyRangeComponent(errorString, range->getEndLine() >= 0, "endLine")
        || !verifyRangeComponent(errorString, range->getEndColumn() >= 0, "endColumn"))
        return false;

    unsigned startOffset = 0;
    unsigned endOffset = 0;
    bool success = inspectorStyleSheet->lineNumberAndColumnToOffset(range->getStartLine(), range->getStartColumn(), &startOffset)
        && inspectorStyleSheet->lineNumberAndColumnToOffset(range->getEndLine(), range->getEndColumn(), &endOffset);
    if (!success) {
        *errorString = "Specified range is out of bounds";
        return false;
    }

    if (startOffset > endOffset) {
        *errorString = "Range start must not succeed its end";
        return false;
    }
    sourceRange->start = startOffset;
    sourceRange->end = endOffset;
    return true;
}

void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const String& styleSheetId, std::unique_ptr<protocol::CSS::SourceRange> range, const String& selector, std::unique_ptr<protocol::CSS::SelectorList>* result)
{
    FrontendOperationScope scope;
    InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet) {
        *errorString = "Stylesheet not found";
        return;
    }
    SourceRange selectorRange;
    if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, range.get(), &selectorRange))
        return;

    TrackExceptionState exceptionState;
    ModifyRuleAction* action = new ModifyRuleAction(ModifyRuleAction::SetRuleSelector, inspectorStyleSheet, selectorRange, selector);
    bool success = m_domAgent->history()->perform(action, exceptionState);
    if (success) {
        CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(action->takeRule());
        InspectorStyleSheet* inspectorStyleSheet = inspectorStyleSheetForRule(rule);
        if (!inspectorStyleSheet) {
            *errorString = "Failed to get inspector style sheet for rule.";
            return;
        }
        *result = inspectorStyleSheet->buildObjectForSelectorList(rule);
    }
    *errorString = InspectorDOMAgent::toErrorString(exceptionState);
}

void InspectorCSSAgent::setKeyframeKey(ErrorString* errorString, const String& styleSheetId, std::unique_ptr<protocol::CSS::SourceRange> range, const String& keyText, std::unique_ptr<protocol::CSS::Value>* result)
{
    FrontendOperationScope scope;
    InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet) {
        *errorString = "Stylesheet not found";
        return;
    }
    SourceRange keyRange;
    if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, range.get(), &keyRange))
        return;

    TrackExceptionState exceptionState;
    ModifyRuleAction* action = new ModifyRuleAction(ModifyRuleAction::SetKeyframeKey, inspectorStyleSheet, keyRange, keyText);
    bool success = m_domAgent->history()->perform(action, exceptionState);
    if (success) {
        CSSKeyframeRule* rule = toCSSKeyframeRule(action->takeRule());
        InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
        if (!inspectorStyleSheet) {
            *errorString = "Failed to get inspector style sheet for rule.";
            return;
        }

        CSSRuleSourceData* sourceData = inspectorStyleSheet->sourceDataForRule(rule);
        *result = protocol::CSS::Value::create()
            .setText(rule->keyText())
            .setRange(inspectorStyleSheet->buildSourceRangeObject(sourceData->ruleHeaderRange))
            .build();
    }
    *errorString = InspectorDOMAgent::toErrorString(exceptionState);
}


bool InspectorCSSAgent::multipleStyleTextsActions(ErrorString* errorString, std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>> edits, HeapVector<Member<StyleSheetAction>>* actions)
{
    int n = edits->length();
    if (n == 0) {
        *errorString = "Edits should not be empty";
        return false;
    }

    for (int i = 0; i < n; ++i) {
        protocol::CSS::StyleDeclarationEdit* edit = edits->get(i);
        InspectorStyleSheetBase* inspectorStyleSheet = assertStyleSheetForId(errorString, edit->getStyleSheetId());
        if (!inspectorStyleSheet) {
            *errorString = String::format("StyleSheet not found for edit #%d of %d", i + 1 , n);
            return false;
        }

        SourceRange range;
        if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, edit->getRange(), &range))
            return false;

        if (inspectorStyleSheet->isInlineStyle()) {
            InspectorStyleSheetForInlineStyle* inlineStyleSheet = static_cast<InspectorStyleSheetForInlineStyle*>(inspectorStyleSheet);
            SetElementStyleAction* action = new SetElementStyleAction(inlineStyleSheet, edit->getText());
            actions->append(action);
        } else {
            ModifyRuleAction* action = new ModifyRuleAction(ModifyRuleAction::SetStyleText, static_cast<InspectorStyleSheet*>(inspectorStyleSheet), range, edit->getText());
            actions->append(action);
        }
    }
    return true;
}

void InspectorCSSAgent::setStyleTexts(ErrorString* errorString, std::unique_ptr<protocol::Array<protocol::CSS::StyleDeclarationEdit>> edits, std::unique_ptr<protocol::Array<protocol::CSS::CSSStyle>>* result)
{
    FrontendOperationScope scope;
    HeapVector<Member<StyleSheetAction>> actions;
    if (!multipleStyleTextsActions(errorString, std::move(edits), &actions))
        return;

    TrackExceptionState exceptionState;

    int n = actions.size();
    std::unique_ptr<protocol::Array<protocol::CSS::CSSStyle>> serializedStyles = protocol::Array<protocol::CSS::CSSStyle>::create();
    for (int i = 0; i < n; ++i) {
        Member<StyleSheetAction> action = actions.at(i);
        bool success = action->perform(exceptionState);
        if (!success) {
            for (int j = i - 1; j >= 0; --j) {
                Member<StyleSheetAction> revert = actions.at(j);
                TrackExceptionState undoExceptionState;
                revert->undo(undoExceptionState);
                ASSERT(!undoExceptionState.hadException());
            }
            *errorString = String::format("Failed applying edit #%d: %s", i, InspectorDOMAgent::toErrorString(exceptionState).utf8().data());
            return;
        }
        serializedStyles->addItem(action->takeSerializedStyle());
    }

    for (int i = 0; i < n; ++i) {
        Member<StyleSheetAction> action = actions.at(i);
        m_domAgent->history()->appendPerformedAction(action);
    }
    *result = std::move(serializedStyles);
}

CSSStyleDeclaration* InspectorCSSAgent::setStyleText(ErrorString* errorString, InspectorStyleSheetBase* inspectorStyleSheet, const SourceRange& range, const String& text)
{
    TrackExceptionState exceptionState;
    if (inspectorStyleSheet->isInlineStyle()) {
        InspectorStyleSheetForInlineStyle* inlineStyleSheet = static_cast<InspectorStyleSheetForInlineStyle*>(inspectorStyleSheet);
        SetElementStyleAction* action = new SetElementStyleAction(inlineStyleSheet, text);
        bool success = m_domAgent->history()->perform(action, exceptionState);
        if (success)
            return inlineStyleSheet->inlineStyle();
    } else {
        ModifyRuleAction* action = new ModifyRuleAction(ModifyRuleAction::SetStyleText, static_cast<InspectorStyleSheet*>(inspectorStyleSheet), range, text);
        bool success = m_domAgent->history()->perform(action, exceptionState);
        if (success) {
            CSSRule* rule = action->takeRule();
            if (rule->type() == CSSRule::kStyleRule)
                return toCSSStyleRule(rule)->style();
            if (rule->type() == CSSRule::kKeyframeRule)
                return toCSSKeyframeRule(rule)->style();
        }
    }
    *errorString = InspectorDOMAgent::toErrorString(exceptionState);
    return nullptr;
}

void InspectorCSSAgent::setMediaText(ErrorString* errorString, const String& styleSheetId, std::unique_ptr<protocol::CSS::SourceRange> range, const String& text, std::unique_ptr<protocol::CSS::CSSMedia>* result)
{
    FrontendOperationScope scope;
    InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet) {
        *errorString = "Stylesheet not found";
        return;
    }
    SourceRange textRange;
    if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, range.get(), &textRange))
        return;

    TrackExceptionState exceptionState;
    ModifyRuleAction* action = new ModifyRuleAction(ModifyRuleAction::SetMediaRuleText, inspectorStyleSheet, textRange, text);
    bool success = m_domAgent->history()->perform(action, exceptionState);
    if (success) {
        CSSMediaRule* rule = InspectorCSSAgent::asCSSMediaRule(action->takeRule());
        String sourceURL = rule->parentStyleSheet()->contents()->baseURL();
        if (sourceURL.isEmpty())
            sourceURL = InspectorDOMAgent::documentURLString(rule->parentStyleSheet()->ownerDocument());
        *result = buildMediaObject(rule->media(), MediaListSourceMediaRule, sourceURL, rule->parentStyleSheet());
    }
    *errorString = InspectorDOMAgent::toErrorString(exceptionState);
}

void InspectorCSSAgent::createStyleSheet(ErrorString* errorString, const String& frameId, protocol::CSS::StyleSheetId* outStyleSheetId)
{
    LocalFrame* frame = IdentifiersFactory::frameById(m_inspectedFrames, frameId);
    if (!frame) {
        *errorString = "Frame not found";
        return;
    }

    Document* document = frame->document();
    if (!document) {
        *errorString = "Frame does not have a document";
        return;
    }

    InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(document);
    if (!inspectorStyleSheet) {
        *errorString = "No target stylesheet found";
        return;
    }

    updateActiveStyleSheets(document, ExistingFrontendRefresh);

    *outStyleSheetId = inspectorStyleSheet->id();
}

void InspectorCSSAgent::addRule(ErrorString* errorString, const String& styleSheetId, const String& ruleText, std::unique_ptr<protocol::CSS::SourceRange> location, std::unique_ptr<protocol::CSS::CSSRule>* result)
{
    FrontendOperationScope scope;
    InspectorStyleSheet* inspectorStyleSheet = assertInspectorStyleSheetForId(errorString, styleSheetId);
    if (!inspectorStyleSheet)
        return;
    SourceRange ruleLocation;
    if (!jsonRangeToSourceRange(errorString, inspectorStyleSheet, location.get(), &ruleLocation))
        return;

    TrackExceptionState exceptionState;
    AddRuleAction* action = new AddRuleAction(inspectorStyleSheet, ruleText, ruleLocation);
    bool success = m_domAgent->history()->perform(action, exceptionState);
    if (!success) {
        *errorString = InspectorDOMAgent::toErrorString(exceptionState);
        return;
    }

    CSSStyleRule* rule = action->takeRule();
    *result = buildObjectForRule(rule);
}

void InspectorCSSAgent::forcePseudoState(ErrorString* errorString, int nodeId, std::unique_ptr<protocol::Array<String>> forcedPseudoClasses)
{
    Element* element = m_domAgent->assertElement(errorString, nodeId);
    if (!element)
        return;

    unsigned forcedPseudoState = computePseudoClassMask(std::move(forcedPseudoClasses));
    NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
    unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->value;
    bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState;
    if (!needStyleRecalc)
        return;

    if (forcedPseudoState)
        m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState);
    else
        m_nodeIdToForcedPseudoState.remove(nodeId);
    element->ownerDocument()->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Inspector));
}

std::unique_ptr<protocol::CSS::CSSMedia> InspectorCSSAgent::buildMediaObject(const MediaList* media, MediaListSource mediaListSource, const String& sourceURL, CSSStyleSheet* parentStyleSheet)
{
    // Make certain compilers happy by initializing |source| up-front.
    String source = protocol::CSS::CSSMedia::SourceEnum::InlineSheet;
    switch (mediaListSource) {
    case MediaListSourceMediaRule:
        source = protocol::CSS::CSSMedia::SourceEnum::MediaRule;
        break;
    case MediaListSourceImportRule:
        source = protocol::CSS::CSSMedia::SourceEnum::ImportRule;
        break;
    case MediaListSourceLinkedSheet:
        source = protocol::CSS::CSSMedia::SourceEnum::LinkedSheet;
        break;
    case MediaListSourceInlineSheet:
        source = protocol::CSS::CSSMedia::SourceEnum::InlineSheet;
        break;
    }

    const MediaQuerySet* queries = media->queries();
    const HeapVector<Member<MediaQuery>>& queryVector = queries->queryVector();
    LocalFrame* frame = nullptr;
    if (parentStyleSheet) {
        if (Document* document = parentStyleSheet->ownerDocument())
            frame = document->frame();
    }
    MediaQueryEvaluator* mediaEvaluator = new MediaQueryEvaluator(frame);

    InspectorStyleSheet* inspectorStyleSheet = parentStyleSheet ? m_cssStyleSheetToInspectorStyleSheet.get(parentStyleSheet) : nullptr;
    std::unique_ptr<protocol::Array<protocol::CSS::MediaQuery>> mediaListArray = protocol::Array<protocol::CSS::MediaQuery>::create();
    MediaValues* mediaValues = MediaValues::createDynamicIfFrameExists(frame);
    bool hasMediaQueryItems = false;
    for (size_t i = 0; i < queryVector.size(); ++i) {
        MediaQuery* query = queryVector.at(i).get();
        const ExpressionHeapVector& expressions = query->expressions();
        std::unique_ptr<protocol::Array<protocol::CSS::MediaQueryExpression>> expressionArray = protocol::Array<protocol::CSS::MediaQueryExpression>::create();
        bool hasExpressionItems = false;
        for (size_t j = 0; j < expressions.size(); ++j) {
            MediaQueryExp* mediaQueryExp = expressions.at(j).get();
            MediaQueryExpValue expValue = mediaQueryExp->expValue();
            if (!expValue.isValue)
                continue;
            const char* valueName = CSSPrimitiveValue::unitTypeToString(expValue.unit);
            std::unique_ptr<protocol::CSS::MediaQueryExpression> mediaQueryExpression = protocol::CSS::MediaQueryExpression::create()
                .setValue(expValue.value)
                .setUnit(String(valueName))
                .setFeature(mediaQueryExp->mediaFeature()).build();

            if (inspectorStyleSheet && media->parentRule())
                mediaQueryExpression->setValueRange(inspectorStyleSheet->mediaQueryExpValueSourceRange(media->parentRule(), i, j));

            int computedLength;
            if (mediaValues->computeLength(expValue.value, expValue.unit, computedLength))
                mediaQueryExpression->setComputedLength(computedLength);

            expressionArray->addItem(std::move(mediaQueryExpression));
            hasExpressionItems = true;
        }
        if (!hasExpressionItems)
            continue;
        std::unique_ptr<protocol::CSS::MediaQuery> mediaQuery = protocol::CSS::MediaQuery::create()
            .setActive(mediaEvaluator->eval(query, nullptr))
            .setExpressions(std::move(expressionArray)).build();
        mediaListArray->addItem(std::move(mediaQuery));
        hasMediaQueryItems = true;
    }

    std::unique_ptr<protocol::CSS::CSSMedia> mediaObject = protocol::CSS::CSSMedia::create()
        .setText(media->mediaText())
        .setSource(source).build();
    if (hasMediaQueryItems)
        mediaObject->setMediaList(std::move(mediaListArray));

    if (inspectorStyleSheet && mediaListSource != MediaListSourceLinkedSheet)
        mediaObject->setStyleSheetId(inspectorStyleSheet->id());

    if (!sourceURL.isEmpty()) {
        mediaObject->setSourceURL(sourceURL);

        CSSRule* parentRule = media->parentRule();
        if (!parentRule)
            return mediaObject;
        InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(parentRule->parentStyleSheet());
        mediaObject->setRange(inspectorStyleSheet->ruleHeaderSourceRange(parentRule));
    }
    return mediaObject;
}

void InspectorCSSAgent::collectMediaQueriesFromStyleSheet(CSSStyleSheet* styleSheet, protocol::Array<protocol::CSS::CSSMedia>* mediaArray)
{
    MediaList* mediaList = styleSheet->media();
    String sourceURL;
    if (mediaList && mediaList->length()) {
        Document* doc = styleSheet->ownerDocument();
        if (doc)
            sourceURL = doc->url();
        else if (!styleSheet->contents()->baseURL().isEmpty())
            sourceURL = styleSheet->contents()->baseURL();
        else
            sourceURL = "";
        mediaArray->addItem(buildMediaObject(mediaList, styleSheet->ownerNode() ? MediaListSourceLinkedSheet : MediaListSourceInlineSheet, sourceURL, styleSheet));
    }
}

void InspectorCSSAgent::collectMediaQueriesFromRule(CSSRule* rule, protocol::Array<protocol::CSS::CSSMedia>* mediaArray)
{
    MediaList* mediaList;
    String sourceURL;
    CSSStyleSheet* parentStyleSheet = nullptr;
    bool isMediaRule = true;
    if (rule->type() == CSSRule::kMediaRule) {
        CSSMediaRule* mediaRule = toCSSMediaRule(rule);
        mediaList = mediaRule->media();
        parentStyleSheet = mediaRule->parentStyleSheet();
    } else if (rule->type() == CSSRule::kImportRule) {
        CSSImportRule* importRule = toCSSImportRule(rule);
        mediaList = importRule->media();
        parentStyleSheet = importRule->parentStyleSheet();
        isMediaRule = false;
    } else {
        mediaList = nullptr;
    }

    if (parentStyleSheet) {
        sourceURL = parentStyleSheet->contents()->baseURL();
        if (sourceURL.isEmpty())
            sourceURL = InspectorDOMAgent::documentURLString(parentStyleSheet->ownerDocument());
    } else {
        sourceURL = "";
    }

    if (mediaList && mediaList->length())
        mediaArray->addItem(buildMediaObject(mediaList, isMediaRule ? MediaListSourceMediaRule : MediaListSourceImportRule, sourceURL, parentStyleSheet));
}

std::unique_ptr<protocol::Array<protocol::CSS::CSSMedia>> InspectorCSSAgent::buildMediaListChain(CSSRule* rule)
{
    if (!rule)
        return nullptr;
    std::unique_ptr<protocol::Array<protocol::CSS::CSSMedia>> mediaArray = protocol::Array<protocol::CSS::CSSMedia>::create();
    CSSRule* parentRule = rule;
    while (parentRule) {
        collectMediaQueriesFromRule(parentRule, mediaArray.get());
        if (parentRule->parentRule()) {
            parentRule = parentRule->parentRule();
        } else {
            CSSStyleSheet* styleSheet = parentRule->parentStyleSheet();
            while (styleSheet) {
                collectMediaQueriesFromStyleSheet(styleSheet, mediaArray.get());
                parentRule = styleSheet->ownerRule();
                if (parentRule)
                    break;
                styleSheet = styleSheet->parentStyleSheet();
            }
        }
    }
    return mediaArray;
}

InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
{
    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
    if (it != m_nodeToInspectorStyleSheet.end())
        return it->value.get();

    CSSStyleDeclaration* style = element->style();
    if (!style)
        return nullptr;

    InspectorStyleSheetForInlineStyle* inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(element, this);
    m_idToInspectorStyleSheetForInlineStyle.set(inspectorStyleSheet->id(), inspectorStyleSheet);
    m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
    return inspectorStyleSheet;
}

Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
{
    Node* node = m_domAgent->nodeForId(nodeId);
    if (!node) {
        *errorString = "No node with given id found";
        return nullptr;
    }
    if (!node->isElementNode()) {
        *errorString = "Not an element node";
        return nullptr;
    }
    return toElement(node);
}

// static
void InspectorCSSAgent::collectAllDocumentStyleSheets(Document* document, HeapVector<Member<CSSStyleSheet>>& result)
{
    const HeapVector<Member<CSSStyleSheet>> activeStyleSheets = document->styleEngine().activeStyleSheetsForInspector();
    for (const auto& style : activeStyleSheets) {
        CSSStyleSheet* styleSheet = style.get();
        InspectorCSSAgent::collectStyleSheets(styleSheet, result);
    }
}

// static
void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, HeapVector<Member<CSSStyleSheet>>& result)
{
    result.append(styleSheet);
    for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
        CSSRule* rule = styleSheet->item(i);
        if (rule->type() == CSSRule::kImportRule) {
            CSSStyleSheet* importedStyleSheet = toCSSImportRule(rule)->styleSheet();
            if (importedStyleSheet)
                InspectorCSSAgent::collectStyleSheets(importedStyleSheet, result);
        }
    }
}

InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
{
    InspectorStyleSheet* inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
    if (!inspectorStyleSheet) {
        Document* document = styleSheet->ownerDocument();
        inspectorStyleSheet = InspectorStyleSheet::create(m_networkAgent, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this, m_resourceContainer);
        m_idToInspectorStyleSheet.set(inspectorStyleSheet->id(), inspectorStyleSheet);
        m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
    }
    return inspectorStyleSheet;
}

String InspectorCSSAgent::styleSheetId(CSSStyleSheet* styleSheet)
{
    return bindStyleSheet(styleSheet)->id();
}

String InspectorCSSAgent::unbindStyleSheet(InspectorStyleSheet* inspectorStyleSheet)
{
    String id = inspectorStyleSheet->id();
    m_idToInspectorStyleSheet.remove(id);
    if (inspectorStyleSheet->pageStyleSheet())
        m_cssStyleSheetToInspectorStyleSheet.remove(inspectorStyleSheet->pageStyleSheet());
    return id;
}

InspectorStyleSheet* InspectorCSSAgent::inspectorStyleSheetForRule(CSSStyleRule* rule)
{
    if (!rule)
        return nullptr;

    // CSSRules returned by StyleResolver::pseudoCSSRulesForElement lack parent pointers if they are coming from
    // user agent stylesheets. To work around this issue, we use CSSOM wrapper created by inspector.
    if (!rule->parentStyleSheet()) {
        if (!m_inspectorUserAgentStyleSheet)
            m_inspectorUserAgentStyleSheet = CSSStyleSheet::create(CSSDefaultStyleSheets::instance().defaultStyleSheet());
        rule->setParentStyleSheet(m_inspectorUserAgentStyleSheet.get());
    }
    return bindStyleSheet(rule->parentStyleSheet());
}

InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document)
{
    if (!document)
        return nullptr;

    if (!document->isHTMLDocument() && !document->isSVGDocument())
        return nullptr;

    CSSStyleSheet& inspectorSheet = document->styleEngine().ensureInspectorStyleSheet();

    flushPendingProtocolNotifications();

    return m_cssStyleSheetToInspectorStyleSheet.get(&inspectorSheet);
}

InspectorStyleSheet* InspectorCSSAgent::assertInspectorStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
{
    IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
    if (it == m_idToInspectorStyleSheet.end()) {
        *errorString = "No style sheet with given id found";
        return nullptr;
    }
    return it->value.get();
}

InspectorStyleSheetBase* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
{
    ErrorString placeholder;
    InspectorStyleSheetBase* result = assertInspectorStyleSheetForId(&placeholder, styleSheetId);
    if (result)
        return result;
    IdToInspectorStyleSheetForInlineStyle::iterator it = m_idToInspectorStyleSheetForInlineStyle.find(styleSheetId);
    if (it == m_idToInspectorStyleSheetForInlineStyle.end()) {
        *errorString = "No style sheet with given id found";
        return nullptr;
    }
    return it->value.get();
}

protocol::CSS::StyleSheetOrigin InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
{
    DCHECK(pageStyleSheet);

    if (!pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
        return protocol::CSS::StyleSheetOriginEnum::UserAgent;

    if (pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->isDocumentNode()) {
        if (pageStyleSheet == ownerDocument->styleEngine().inspectorStyleSheet())
            return protocol::CSS::StyleSheetOriginEnum::Inspector;
        return protocol::CSS::StyleSheetOriginEnum::Injected;
    }
    return protocol::CSS::StyleSheetOriginEnum::Regular;
}

std::unique_ptr<protocol::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule)
{
    InspectorStyleSheet* inspectorStyleSheet = inspectorStyleSheetForRule(rule);
    if (!inspectorStyleSheet)
        return nullptr;

    std::unique_ptr<protocol::CSS::CSSRule> result = inspectorStyleSheet->buildObjectForRuleWithoutMedia(rule);
    result->setMedia(buildMediaListChain(rule));
    return result;
}

static inline bool matchesPseudoElement(const CSSSelector* selector, PseudoId elementPseudoId)
{
    // According to http://www.w3.org/TR/css3-selectors/#pseudo-elements, "Only one pseudo-element may appear per selector."
    // As such, check the last selector in the tag history.
    for (; !selector->isLastInTagHistory(); ++selector) { }
    PseudoId selectorPseudoId = CSSSelector::pseudoId(selector->getPseudoType());

    // FIXME: This only covers the case of matching pseudo-element selectors against PseudoElements.
    // We should come up with a solution for matching pseudo-element selectors against ordinary Elements, too.
    return selectorPseudoId == elementPseudoId;
}

std::unique_ptr<protocol::Array<protocol::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(CSSRuleList* ruleList, Element* element, PseudoId matchesForPseudoId)
{
    std::unique_ptr<protocol::Array<protocol::CSS::RuleMatch>> result = protocol::Array<protocol::CSS::RuleMatch>::create();
    if (!ruleList)
        return result;

    HeapVector<Member<CSSStyleRule>> uniqRules = filterDuplicateRules(ruleList);
    for (unsigned i = 0; i < uniqRules.size(); ++i) {
        CSSStyleRule* rule = uniqRules.at(i).get();
        std::unique_ptr<protocol::CSS::CSSRule> ruleObject = buildObjectForRule(rule);
        if (!ruleObject)
            continue;
        std::unique_ptr<protocol::Array<int>> matchingSelectors = protocol::Array<int>::create();
        const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
        long index = 0;
        PseudoId elementPseudoId = matchesForPseudoId ? matchesForPseudoId : element->getPseudoId();
        for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(*selector)) {
            const CSSSelector* firstTagHistorySelector = selector;
            bool matched = false;
            if (elementPseudoId)
                matched = matchesPseudoElement(selector, elementPseudoId); // Modifies |selector|.
            else
                matched = element->matches(firstTagHistorySelector->selectorText(), IGNORE_EXCEPTION);
            if (matched)
                matchingSelectors->addItem(index);
            ++index;
        }
        result->addItem(protocol::CSS::RuleMatch::create()
            .setRule(std::move(ruleObject))
            .setMatchingSelectors(std::move(matchingSelectors))
            .build());
    }

    return result;
}

std::unique_ptr<protocol::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element)
{
    if (!element->isStyledElement())
        return nullptr;

    // FIXME: Ugliness below.
    StylePropertySet* attributeStyle = const_cast<StylePropertySet*>(element->presentationAttributeStyle());
    if (!attributeStyle)
        return nullptr;

    MutableStylePropertySet* mutableAttributeStyle = toMutableStylePropertySet(attributeStyle);

    InspectorStyle* inspectorStyle = InspectorStyle::create(mutableAttributeStyle->ensureCSSStyleDeclaration(), nullptr, nullptr);
    return inspectorStyle->buildObjectForStyle();
}

void InspectorCSSAgent::didRemoveDocument(Document* document)
{
}

void InspectorCSSAgent::didRemoveDOMNode(Node* node)
{
    if (!node)
        return;

    int nodeId = m_domAgent->boundNodeId(node);
    if (nodeId)
        m_nodeIdToForcedPseudoState.remove(nodeId);

    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
    if (it == m_nodeToInspectorStyleSheet.end())
        return;

    m_idToInspectorStyleSheetForInlineStyle.remove(it->value->id());
    m_nodeToInspectorStyleSheet.remove(node);
}

void InspectorCSSAgent::didModifyDOMAttr(Element* element)
{
    if (!element)
        return;

    NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
    if (it == m_nodeToInspectorStyleSheet.end())
        return;

    it->value->didModifyElementAttribute();
}

void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheetBase* styleSheet)
{
    if (s_frontendOperationCounter)
        return;
    flushPendingProtocolNotifications();
    frontend()->styleSheetChanged(styleSheet->id());
}

void InspectorCSSAgent::resetPseudoStates()
{
    HeapHashSet<Member<Document>> documentsToChange;
    for (auto& state : m_nodeIdToForcedPseudoState) {
        Element* element = toElement(m_domAgent->nodeForId(state.key));
        if (element && element->ownerDocument())
            documentsToChange.add(element->ownerDocument());
    }

    m_nodeIdToForcedPseudoState.clear();
    for (auto& document : documentsToChange)
        document->setNeedsStyleRecalc(SubtreeStyleChange, StyleChangeReasonForTracing::create(StyleChangeReason::Inspector));
}

HeapVector<Member<CSSStyleDeclaration>> InspectorCSSAgent::matchingStyles(Element* element)
{
    PseudoId pseudoId = element->getPseudoId();
    if (pseudoId)
        element = element->parentElement();
    StyleResolver& styleResolver = element->ownerDocument()->ensureStyleResolver();
    element->updateDistribution();

    HeapVector<Member<CSSStyleRule>> rules = filterDuplicateRules(styleResolver.pseudoCSSRulesForElement(element, pseudoId, StyleResolver::AllCSSRules));
    HeapVector<Member<CSSStyleDeclaration>> styles;
    if (!pseudoId && element->style())
        styles.append(element->style());
    for (unsigned i = rules.size(); i > 0; --i) {
        CSSStyleSheet* parentStyleSheet = rules.at(i - 1)->parentStyleSheet();
        if (!parentStyleSheet || !parentStyleSheet->ownerNode())
            continue; // User agent.
        styles.append(rules.at(i - 1)->style());
    }
    return styles;
}

CSSStyleDeclaration* InspectorCSSAgent::findEffectiveDeclaration(CSSPropertyID propertyId, const HeapVector<Member<CSSStyleDeclaration>>& styles)
{
    if (!styles.size())
        return nullptr;

    String longhand = getPropertyNameString(propertyId);
    CSSStyleDeclaration* foundStyle = nullptr;

    for (unsigned i = 0; i < styles.size(); ++i) {
        CSSStyleDeclaration* style = styles.at(i).get();
        if (style->getPropertyValue(longhand).isEmpty())
            continue;
        if (style->getPropertyPriority(longhand) == "important")
            return style;
        if (!foundStyle)
            foundStyle = style;
    }

    return foundStyle ? foundStyle : styles.at(0).get();
}

void InspectorCSSAgent::setLayoutEditorValue(ErrorString* errorString, Element* element, CSSStyleDeclaration* style, CSSPropertyID propertyId, const String& value, bool forceImportant)
{
    InspectorStyleSheetBase* inspectorStyleSheet =  nullptr;
    RefPtr<CSSRuleSourceData> sourceData;
    // An absence of the parent rule means that given style is an inline style.
    if (style->parentRule()) {
        InspectorStyleSheet* styleSheet = bindStyleSheet(style->parentStyleSheet());
        inspectorStyleSheet = styleSheet;
        sourceData = styleSheet->sourceDataForRule(style->parentRule());
    } else {
        InspectorStyleSheetForInlineStyle* inlineStyleSheet = asInspectorStyleSheet(element);
        inspectorStyleSheet = inlineStyleSheet;
        sourceData = inlineStyleSheet->ruleSourceData();
    }

    if (!sourceData) {
        *errorString = "Can't find a source to edit";
        return;
    }

    Vector<StylePropertyShorthand, 4> shorthands;
    getMatchingShorthandsForLonghand(propertyId, &shorthands);

    String shorthand =  shorthands.size() > 0 ? getPropertyNameString(shorthands[0].id()) : String();
    String longhand = getPropertyNameString(propertyId);

    int foundIndex = -1;
    Vector<CSSPropertySourceData> properties = sourceData->styleSourceData->propertyData;
    for (unsigned i = 0; i < properties.size(); ++i) {
        CSSPropertySourceData property = properties[properties.size() - i - 1];
        String name = property.name;
        if (property.disabled)
            continue;

        if (name != shorthand && name != longhand)
            continue;

        if (property.important || foundIndex == -1)
            foundIndex = properties.size() - i - 1;

        if (property.important)
            break;
    }

    SourceRange bodyRange = sourceData->ruleBodyRange;
    String styleSheetText;
    inspectorStyleSheet->getText(&styleSheetText);
    String styleText = styleSheetText.substring(bodyRange.start, bodyRange.length());
    SourceRange changeRange;
    if (foundIndex == -1) {
        String newPropertyText = "\n" + longhand + ": " + value + (forceImportant ? " !important" : "") + ";";
        if (!styleText.isEmpty() && !styleText.stripWhiteSpace().endsWith(';'))
            newPropertyText = ";" + newPropertyText;
        styleText.append(newPropertyText);
        changeRange.start = bodyRange.end;
        changeRange.end = bodyRange.end + newPropertyText.length();
    } else {
        CSSPropertySourceData declaration = properties[foundIndex];
        String newValueText;
        if (declaration.name == shorthand)
            newValueText = createShorthandValue(element->ownerDocument(), shorthand, declaration.value, longhand, value);
        else
            newValueText = value;

        String newPropertyText = declaration.name + ": " + newValueText + (declaration.important || forceImportant ? " !important" : "") + ";";
        styleText.replace(declaration.range.start - bodyRange.start, declaration.range.length(), newPropertyText);
        changeRange.start = declaration.range.start;
        changeRange.end = changeRange.start + newPropertyText.length();
    }
    CSSStyleDeclaration* resultStyle = setStyleText(errorString, inspectorStyleSheet, bodyRange, styleText);
    if (resultStyle)
        frontend()->layoutEditorChange(inspectorStyleSheet->id(), inspectorStyleSheet->buildSourceRangeObject(changeRange));
}

void InspectorCSSAgent::layoutEditorItemSelected(Element* element, CSSStyleDeclaration* style)
{
    InspectorStyleSheetBase* inspectorStyleSheet =  nullptr;
    RefPtr<CSSRuleSourceData> sourceData;
    if (style->parentRule()) {
        InspectorStyleSheet* styleSheet = bindStyleSheet(style->parentStyleSheet());
        inspectorStyleSheet = styleSheet;
        sourceData = styleSheet->sourceDataForRule(style->parentRule());
    } else {
        InspectorStyleSheetForInlineStyle* inlineStyleSheet = asInspectorStyleSheet(element);
        inspectorStyleSheet = inlineStyleSheet;
        sourceData = inlineStyleSheet->ruleSourceData();
    }

    if (sourceData)
        frontend()->layoutEditorChange(inspectorStyleSheet->id(), inspectorStyleSheet->buildSourceRangeObject(sourceData->ruleHeaderRange));
}

void InspectorCSSAgent::setEffectivePropertyValueForNode(ErrorString* errorString, int nodeId, const String& propertyName, const String& value)
{
    // TODO: move testing from CSSAgent to layout editor.
    Element* element = elementForId(errorString, nodeId);
    if (!element || element->getPseudoId())
        return;

    CSSPropertyID property = cssPropertyID(propertyName);
    if (!property) {
        *errorString = "Invalid property name";
        return;
    }

    Document* ownerDocument = element->ownerDocument();
    if (!ownerDocument->isActive()) {
        *errorString = "Can't edit a node from a non-active document";
        return;
    }

    CSSPropertyID propertyId = cssPropertyID(propertyName);
    CSSStyleDeclaration* style = findEffectiveDeclaration(propertyId, matchingStyles(element));
    if (!style) {
        *errorString = "Can't find a style to edit";
        return;
    }

    setLayoutEditorValue(errorString, element, style, propertyId, value);
}

void InspectorCSSAgent::getBackgroundColors(ErrorString* errorString, int nodeId, Maybe<protocol::Array<String>>* result)
{
    Element* element = elementForId(errorString, nodeId);
    if (!element) {
        *errorString = "Node not found";
        return;
    }

    LayoutRect textBounds;
    LayoutObject* elementLayout = element->layoutObject();
    if (!elementLayout)
        return;

    for (const LayoutObject* child = elementLayout->slowFirstChild(); child; child = child->nextSibling()) {
        if (!child->isText())
            continue;
        textBounds.unite(LayoutRect(child->absoluteBoundingBoxRect()));
    }
    if (textBounds.size().isEmpty())
        return;

    Vector<Color> colors;
    FrameView* view = element->document().view();
    if (!view) {
        *errorString = "No view.";
        return;
    }
    Document& document = element->document();
    bool isMainFrame = document.isInMainFrame();
    bool foundOpaqueColor = false;
    if (isMainFrame && !view->isTransparent()) {
        // Start with the "default" page color (typically white).
        Color baseBackgroundColor = view->baseBackgroundColor();
        colors.append(view->baseBackgroundColor());
        foundOpaqueColor = !baseBackgroundColor.hasAlpha();
    }

    foundOpaqueColor = getColorsFromRect(textBounds, element->document(), element, colors);

    if (!foundOpaqueColor && !isMainFrame) {
        for (HTMLFrameOwnerElement* ownerElement = document.localOwner();
            !foundOpaqueColor && ownerElement;
            ownerElement = ownerElement->document().localOwner()) {
            foundOpaqueColor = getColorsFromRect(textBounds, ownerElement->document(), nullptr, colors);
        }
    }

    *result = protocol::Array<String>::create();
    for (auto color : colors)
        result->fromJust()->addItem(color.serializedAsCSSComponentValue());
}

DEFINE_TRACE(InspectorCSSAgent)
{
    visitor->trace(m_domAgent);
    visitor->trace(m_inspectedFrames);
    visitor->trace(m_networkAgent);
    visitor->trace(m_resourceContentLoader);
    visitor->trace(m_resourceContainer);
    visitor->trace(m_idToInspectorStyleSheet);
    visitor->trace(m_idToInspectorStyleSheetForInlineStyle);
    visitor->trace(m_cssStyleSheetToInspectorStyleSheet);
    visitor->trace(m_documentToCSSStyleSheets);
    visitor->trace(m_invalidatedDocuments);
    visitor->trace(m_nodeToInspectorStyleSheet);
    visitor->trace(m_inspectorUserAgentStyleSheet);
    InspectorBaseAgent::trace(visitor);
}

} // namespace blink
