/*
 * 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/css/resolver/StyleRuleUsageTracker.h"
#include "core/dom/DOMException.h"
#include "core/dom/DOMNodeIds.h"
#include "core/dom/Node.h"
#include "core/dom/StyleChangeReason.h"
#include "core/dom/StyleEngine.h"
#include "core/dom/Text.h"
#include "core/dom/shadow/ElementShadow.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/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();
  DummyExceptionStateForTesting 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.front();
    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;
}

std::unique_ptr<protocol::DOM::Rect> buildRectForFloatRect(
    const FloatRect& rect) {
  return protocol::DOM::Rect::create()
      .setX(rect.x())
      .setY(rect.y())
      .setWidth(rect.width())
      .setHeight(rect.height())
      .build();
}

}  // namespace

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

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;
  }
};

struct InspectorCSSAgent::VectorStringHashTraits
    : public WTF::GenericHashTraits<Vector<String>> {
  static unsigned hash(const Vector<String>& vec) {
    unsigned h = DefaultHash<size_t>::Hash::hash(vec.size());
    for (size_t i = 0; i < vec.size(); i++) {
      h = WTF::hashInts(h, DefaultHash<String>::Hash::hash(vec[i]));
    }
    return h;
  }

  static bool equal(const Vector<String>& a, const Vector<String>& b) {
    if (a.size() != b.size())
      return false;
    for (size_t i = 0; i < a.size(); i++) {
      if (a[i] != b[i])
        return false;
    }
    return true;
  }

  static void constructDeletedValue(Vector<String>& vec, bool) {
    vec.clear();
    vec.append(String(WTF::HashTableDeletedValue));
  }

  static bool isDeletedValue(const Vector<String>& vec) {
    return !vec.isEmpty() && vec[0].isHashTableDeletedValue();
  }

  static bool isEmptyValue(const Vector<String>& vec) { return vec.isEmpty(); }

  static const bool emptyValueIsZero = false;
  static const bool safeToCompareToEmptyOrDeleted = false;
  static const bool hasIsEmptyValueFunction = true;
};

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();
  if (m_state->booleanProperty(CSSAgentState::ruleRecordingEnabled, false))
    setUsageTrackerStatus(true);
}

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(
        Response::Error("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),
                WTF::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);
}

Response InspectorCSSAgent::disable() {
  reset();
  m_domAgent->setDOMListener(nullptr);
  m_instrumentingAgents->removeInspectorCSSAgent(this);
  m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
  m_resourceContentLoader->cancel(m_resourceContentLoaderClientId);
  m_state->setBoolean(CSSAgentState::ruleRecordingEnabled, false);
  setUsageTrackerStatus(false);
  return Response::OK();
}

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;
  }
}

Response InspectorCSSAgent::getMediaQueries(
    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());
    }
  }
  return Response::OK();
}

Response InspectorCSSAgent::getMatchedStylesForNode(
    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 = nullptr;
  Response response = m_domAgent->assertElement(nodeId, element);
  if (!response.isSuccess())
    return response;

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

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

  // 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 Response::OK();

  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);
  return Response::OK();
}

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;
}

Response InspectorCSSAgent::getInlineStylesForNode(
    int nodeId,
    Maybe<protocol::CSS::CSSStyle>* inlineStyle,
    Maybe<protocol::CSS::CSSStyle>* attributesStyle) {
  Element* element = nullptr;
  Response response = m_domAgent->assertElement(nodeId, element);
  if (!response.isSuccess())
    return response;

  InspectorStyleSheetForInlineStyle* styleSheet =
      asInspectorStyleSheet(element);
  if (!styleSheet)
    return Response::Error("Element is not a style sheet");

  *inlineStyle = styleSheet->buildObjectForStyle(element->style());
  *attributesStyle = buildObjectForAttributesStyle(element);
  return Response::OK();
}

Response InspectorCSSAgent::getComputedStyleForNode(
    int nodeId,
    std::unique_ptr<protocol::Array<protocol::CSS::CSSComputedStyleProperty>>*
        style) {
  Node* node = nullptr;
  Response response = m_domAgent->assertNode(nodeId, node);
  if (!response.isSuccess())
    return response;

  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());
    }
  }
  return Response::OK();
}

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));
    }
  }
}

Response InspectorCSSAgent::getPlatformFontsForNode(
    int nodeId,
    std::unique_ptr<protocol::Array<protocol::CSS::PlatformFontUsage>>*
        platformFonts) {
  Node* node = nullptr;
  Response response = m_domAgent->assertNode(nodeId, node);
  if (!response.isSuccess())
    return response;

  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());
  }
  return Response::OK();
}

Response InspectorCSSAgent::getStyleSheetText(const String& styleSheetId,
                                              String* result) {
  InspectorStyleSheetBase* inspectorStyleSheet = nullptr;
  Response response = assertStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;

  inspectorStyleSheet->getText(result);
  return Response::OK();
}

Response InspectorCSSAgent::collectClassNames(
    const String& styleSheetId,
    std::unique_ptr<protocol::Array<String>>* classNames) {
  InspectorStyleSheet* inspectorStyleSheet = nullptr;
  Response response =
      assertInspectorStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;
  *classNames = inspectorStyleSheet->collectClassNames();
  return Response::OK();
}

Response InspectorCSSAgent::setStyleSheetText(
    const String& styleSheetId,
    const String& text,
    protocol::Maybe<String>* sourceMapURL) {
  FrontendOperationScope scope;
  InspectorStyleSheetBase* inspectorStyleSheet = nullptr;
  Response response = assertStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;

  DummyExceptionStateForTesting exceptionState;
  m_domAgent->history()->perform(
      new SetStyleSheetTextAction(inspectorStyleSheet, text), exceptionState);
  response = InspectorDOMAgent::toResponse(exceptionState);
  if (!response.isSuccess())
    return response;
  if (!inspectorStyleSheet->sourceMapURL().isEmpty())
    *sourceMapURL = inspectorStyleSheet->sourceMapURL();
  return Response::OK();
}

static Response jsonRangeToSourceRange(
    InspectorStyleSheetBase* inspectorStyleSheet,
    protocol::CSS::SourceRange* range,
    SourceRange* sourceRange) {
  if (range->getStartLine() < 0)
    return Response::Error("range.startLine must be a non-negative integer");
  if (range->getStartColumn() < 0)
    return Response::Error("range.startColumn must be a non-negative integer");
  if (range->getEndLine() < 0)
    return Response::Error("range.endLine must be a non-negative integer");
  if (range->getEndColumn() < 0)
    return Response::Error("range.endColumn must be a non-negative integer");

  unsigned startOffset = 0;
  unsigned endOffset = 0;
  bool success =
      inspectorStyleSheet->lineNumberAndColumnToOffset(
          range->getStartLine(), range->getStartColumn(), &startOffset) &&
      inspectorStyleSheet->lineNumberAndColumnToOffset(
          range->getEndLine(), range->getEndColumn(), &endOffset);
  if (!success)
    return Response::Error("Specified range is out of bounds");

  if (startOffset > endOffset)
    return Response::Error("Range start must not succeed its end");
  sourceRange->start = startOffset;
  sourceRange->end = endOffset;
  return Response::OK();
}

Response InspectorCSSAgent::setRuleSelector(
    const String& styleSheetId,
    std::unique_ptr<protocol::CSS::SourceRange> range,
    const String& selector,
    std::unique_ptr<protocol::CSS::SelectorList>* result) {
  FrontendOperationScope scope;
  InspectorStyleSheet* inspectorStyleSheet = nullptr;
  Response response =
      assertInspectorStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;
  SourceRange selectorRange;
  response =
      jsonRangeToSourceRange(inspectorStyleSheet, range.get(), &selectorRange);
  if (!response.isSuccess())
    return response;

  DummyExceptionStateForTesting 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)
      return Response::Error("Failed to get inspector style sheet for rule.");
    *result = inspectorStyleSheet->buildObjectForSelectorList(rule);
  }
  return InspectorDOMAgent::toResponse(exceptionState);
}

Response InspectorCSSAgent::setKeyframeKey(
    const String& styleSheetId,
    std::unique_ptr<protocol::CSS::SourceRange> range,
    const String& keyText,
    std::unique_ptr<protocol::CSS::Value>* result) {
  FrontendOperationScope scope;
  InspectorStyleSheet* inspectorStyleSheet = nullptr;
  Response response =
      assertInspectorStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;
  SourceRange keyRange;
  response =
      jsonRangeToSourceRange(inspectorStyleSheet, range.get(), &keyRange);
  if (!response.isSuccess())
    return response;

  DummyExceptionStateForTesting 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)
      return Response::Error("Failed to get inspector style sheet for rule.");

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

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

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

    SourceRange range;
    response =
        jsonRangeToSourceRange(inspectorStyleSheet, edit->getRange(), &range);
    if (!response.isSuccess())
      return response;

    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 Response::OK();
}

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

  DummyExceptionStateForTesting 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);
        DummyExceptionStateForTesting undoExceptionState;
        revert->undo(undoExceptionState);
        ASSERT(!undoExceptionState.hadException());
      }
      return Response::Error(
          String::format("Failed applying edit #%d: ", i) +
          InspectorDOMAgent::toResponse(exceptionState).errorMessage());
    }
    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);
  return Response::OK();
}

Response InspectorCSSAgent::setStyleText(
    InspectorStyleSheetBase* inspectorStyleSheet,
    const SourceRange& range,
    const String& text,
    CSSStyleDeclaration*& result) {
  DummyExceptionStateForTesting 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) {
      result = inlineStyleSheet->inlineStyle();
      return Response::OK();
    }
  } 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) {
        result = toCSSStyleRule(rule)->style();
        return Response::OK();
      }
      if (rule->type() == CSSRule::kKeyframeRule) {
        result = toCSSKeyframeRule(rule)->style();
        return Response::OK();
      }
    }
  }
  return InspectorDOMAgent::toResponse(exceptionState);
}

Response InspectorCSSAgent::setMediaText(
    const String& styleSheetId,
    std::unique_ptr<protocol::CSS::SourceRange> range,
    const String& text,
    std::unique_ptr<protocol::CSS::CSSMedia>* result) {
  FrontendOperationScope scope;
  InspectorStyleSheet* inspectorStyleSheet = nullptr;
  Response response =
      assertInspectorStyleSheetForId(styleSheetId, inspectorStyleSheet);
  if (!response.isSuccess())
    return response;
  SourceRange textRange;
  response =
      jsonRangeToSourceRange(inspectorStyleSheet, range.get(), &textRange);
  if (!response.isSuccess())
    return response;

  DummyExceptionStateForTesting 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());
  }
  return InspectorDOMAgent::toResponse(exceptionState);
}

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

  Document* document = frame->document();
  if (!document)
    return Response::Error("Frame does not have a document");

  InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(document);
  if (!inspectorStyleSheet)
    return Response::Error("No target stylesheet found");

  updateActiveStyleSheets(document, ExistingFrontendRefresh);

  *outStyleSheetId = inspectorStyleSheet->id();
  return Response::OK();
}

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

  DummyExceptionStateForTesting exceptionState;
  AddRuleAction* action =
      new AddRuleAction(inspectorStyleSheet, ruleText, ruleLocation);
  bool success = m_domAgent->history()->perform(action, exceptionState);
  if (!success)
    return InspectorDOMAgent::toResponse(exceptionState);

  CSSStyleRule* rule = action->takeRule();
  *result = buildObjectForRule(rule);
  return Response::OK();
}

Response InspectorCSSAgent::forcePseudoState(
    int nodeId,
    std::unique_ptr<protocol::Array<String>> forcedPseudoClasses) {
  Element* element = nullptr;
  Response response = m_domAgent->assertElement(nodeId, element);
  if (!response.isSuccess())
    return response;

  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 Response::OK();

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

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;
}

// static
void InspectorCSSAgent::collectAllDocumentStyleSheets(
    Document* document,
    HeapVector<Member<CSSStyleSheet>>& result) {
  for (const auto& style :
       document->styleEngine().activeStyleSheetsForInspector())
    InspectorCSSAgent::collectStyleSheets(style.first, 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);
}

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

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

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::didAddDocument(Document* document) {
  if (!m_tracker)
    return;

  document->styleEngine().setRuleUsageTracker(m_tracker);
  document->setNeedsStyleRecalc(
      SubtreeStyleChange,
      StyleChangeReasonForTracing::create(StyleChangeReason::Inspector));
}

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();
}

Response InspectorCSSAgent::setEffectivePropertyValueForNode(
    int nodeId,
    const String& propertyName,
    const String& value) {
  Element* element = nullptr;
  Response response = m_domAgent->assertElement(nodeId, element);
  if (!response.isSuccess())
    return response;
  if (element->getPseudoId())
    return Response::Error("Elements is pseudo");

  CSSPropertyID property = cssPropertyID(propertyName);
  if (!property)
    return Response::Error("Invalid property name");

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

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

  bool forceImportant = false;
  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)
    return Response::Error("Can't find a source to edit");

  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;
  return setStyleText(inspectorStyleSheet, bodyRange, styleText, resultStyle);
}

Response InspectorCSSAgent::getBackgroundColors(
    int nodeId,
    Maybe<protocol::Array<String>>* result) {
  Element* element = nullptr;
  Response response = m_domAgent->assertElement(nodeId, element);
  if (!response.isSuccess())
    return response;

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

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

  Vector<Color> colors;
  FrameView* view = element->document().view();
  if (!view)
    return Response::Error("No view.");
  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());
  return Response::OK();
}

Response InspectorCSSAgent::getLayoutTreeAndStyles(
    std::unique_ptr<protocol::Array<String>> styleWhitelist,
    std::unique_ptr<protocol::Array<protocol::CSS::LayoutTreeNode>>*
        layoutTreeNodes,
    std::unique_ptr<protocol::Array<protocol::CSS::ComputedStyle>>*
        computedStyles) {
  m_domAgent->document()->updateStyleAndLayoutTree();

  // Look up the CSSPropertyIDs for each entry in |styleWhitelist|.
  Vector<std::pair<String, CSSPropertyID>> cssPropertyWhitelist;
  for (size_t i = 0; i < styleWhitelist->length(); i++) {
    CSSPropertyID propertyId = cssPropertyID(styleWhitelist->get(i));
    if (propertyId == CSSPropertyInvalid)
      continue;
    cssPropertyWhitelist.append(
        std::make_pair(styleWhitelist->get(i), propertyId));
  }

  *layoutTreeNodes = protocol::Array<protocol::CSS::LayoutTreeNode>::create();
  *computedStyles = protocol::Array<protocol::CSS::ComputedStyle>::create();

  ComputedStylesMap styleToIndexMap;
  visitLayoutTreeNodes(m_domAgent->document(), *layoutTreeNodes->get(),
                       cssPropertyWhitelist, styleToIndexMap,
                       *computedStyles->get());
  return Response::OK();
}

int InspectorCSSAgent::getStyleIndexForNode(
    Node* node,
    const Vector<std::pair<String, CSSPropertyID>>& cssPropertyWhitelist,
    ComputedStylesMap& styleToIndexMap,
    protocol::Array<protocol::CSS::ComputedStyle>& computedStyles) {
  CSSComputedStyleDeclaration* computedStyleInfo =
      CSSComputedStyleDeclaration::create(node, true);

  Vector<String> style;
  bool allPropertiesEmpty = true;
  for (const auto& pair : cssPropertyWhitelist) {
    String value = computedStyleInfo->getPropertyValue(pair.second);
    if (!value.isEmpty())
      allPropertiesEmpty = false;
    style.append(value);
  }

  // -1 means an empty style.
  if (allPropertiesEmpty)
    return -1;

  ComputedStylesMap::iterator it = styleToIndexMap.find(style);
  if (it != styleToIndexMap.end())
    return it->value;

  // It's a distinct style, so append to |computedStyles|.
  std::unique_ptr<protocol::Array<protocol::CSS::CSSComputedStyleProperty>>
      styleProperties =
          protocol::Array<protocol::CSS::CSSComputedStyleProperty>::create();

  for (size_t i = 0; i < style.size(); i++) {
    if (style[i].isEmpty())
      continue;
    styleProperties->addItem(protocol::CSS::CSSComputedStyleProperty::create()
                                 .setName(cssPropertyWhitelist[i].first)
                                 .setValue(style[i])
                                 .build());
  }
  computedStyles.addItem(protocol::CSS::ComputedStyle::create()
                             .setProperties(std::move(styleProperties))
                             .build());

  size_t index = styleToIndexMap.size();
  styleToIndexMap.add(std::move(style), index);
  return index;
}

void InspectorCSSAgent::visitLayoutTreeNodes(
    Node* node,
    protocol::Array<protocol::CSS::LayoutTreeNode>& layoutTreeNodes,
    const Vector<std::pair<String, CSSPropertyID>>& cssPropertyWhitelist,
    ComputedStylesMap& styleToIndexMap,
    protocol::Array<protocol::CSS::ComputedStyle>& computedStyles) {
  for (; node; node = NodeTraversal::next(*node)) {
    // Visit shadow dom nodes.
    if (node->isElementNode()) {
      const Element* element = toElement(node);
      ElementShadow* elementShadow = element->shadow();
      if (elementShadow) {
        visitLayoutTreeNodes(&elementShadow->youngestShadowRoot(),
                             layoutTreeNodes, cssPropertyWhitelist,
                             styleToIndexMap, computedStyles);
      }
    }

    // Pierce iframe boundaries.
    if (node->isFrameOwnerElement()) {
      Document* contentDocument =
          toHTMLFrameOwnerElement(node)->contentDocument();
      contentDocument->updateStyleAndLayoutTree();
      visitLayoutTreeNodes(contentDocument->documentElement(), layoutTreeNodes,
                           cssPropertyWhitelist, styleToIndexMap,
                           computedStyles);
    }

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

    int nodeId = m_domAgent->boundNodeId(node);
    if (!nodeId)
      continue;

    std::unique_ptr<protocol::CSS::LayoutTreeNode> layoutTreeNode =
        protocol::CSS::LayoutTreeNode::create()
            .setNodeId(nodeId)
            .setBoundingBox(buildRectForFloatRect(
                node->isElementNode()
                    ? FloatRect(toElement(node)->boundsInViewport())
                    : layoutObject->absoluteBoundingBoxRect()))
            .build();
    int styleIndex = getStyleIndexForNode(node, cssPropertyWhitelist,
                                          styleToIndexMap, computedStyles);
    if (styleIndex != -1)
      layoutTreeNode->setStyleIndex(styleIndex);

    if (layoutObject->isText()) {
      LayoutText* layoutText = toLayoutText(layoutObject);
      layoutTreeNode->setLayoutText(layoutText->text());
      if (layoutText->hasTextBoxes()) {
        std::unique_ptr<protocol::Array<protocol::CSS::InlineTextBox>>
            inlineTextNodes =
                protocol::Array<protocol::CSS::InlineTextBox>::create();
        for (const InlineTextBox* textBox = layoutText->firstTextBox(); textBox;
             textBox = textBox->nextTextBox()) {
          FloatRect localCoordsTextBoxRect(textBox->frameRect());
          FloatRect absoluteCoordsTextBoxRect =
              layoutObject->localToAbsoluteQuad(localCoordsTextBoxRect)
                  .boundingBox();
          inlineTextNodes->addItem(protocol::CSS::InlineTextBox::create()
                                       .setStartCharacterIndex(textBox->start())
                                       .setNumCharacters(textBox->len())
                                       .setBoundingBox(buildRectForFloatRect(
                                           absoluteCoordsTextBoxRect))
                                       .build());
        }
        layoutTreeNode->setInlineTextNodes(std::move(inlineTextNodes));
      }
    }

    layoutTreeNodes.addItem(std::move(layoutTreeNode));
  }
}

void InspectorCSSAgent::setUsageTrackerStatus(bool enabled) {
  if (enabled) {
    if (!m_tracker)
      m_tracker = new StyleRuleUsageTracker();
  } else {
    m_tracker = nullptr;
  }

  HeapVector<Member<Document>> documents = m_domAgent->documents();
  for (Document* document : documents) {
    document->styleEngine().setRuleUsageTracker(m_tracker);

    document->setNeedsStyleRecalc(
        SubtreeStyleChange,
        StyleChangeReasonForTracing::create(StyleChangeReason::Inspector));
  }
}

Response InspectorCSSAgent::startRuleUsageTracking() {
  m_state->setBoolean(CSSAgentState::ruleRecordingEnabled, true);
  setUsageTrackerStatus(true);
  return Response::OK();
}

std::unique_ptr<protocol::CSS::RuleUsage>
InspectorCSSAgent::buildObjectForRuleUsage(CSSStyleRule* rule, bool used) {
  InspectorStyleSheet* inspectorStyleSheet = inspectorStyleSheetForRule(rule);
  if (!inspectorStyleSheet)
    return nullptr;

  std::unique_ptr<protocol::CSS::RuleUsage> result =
      inspectorStyleSheet->buildObjectForRuleUsage(rule, used);

  return result;
}

Response InspectorCSSAgent::stopRuleUsageTracking(
    std::unique_ptr<protocol::Array<protocol::CSS::RuleUsage>>* result) {
  if (!m_tracker) {
    return Response::Error("CSS rule usage tracking is not enabled");
  }

  *result = protocol::Array<protocol::CSS::RuleUsage>::create();

  HeapVector<Member<Document>> documents = m_domAgent->documents();
  for (Document* document : documents) {
    HeapHashSet<Member<CSSStyleSheet>>* newSheetsVector =
        m_documentToCSSStyleSheets.get(document);

    if (!newSheetsVector)
      continue;

    for (auto sheet : *newSheetsVector) {
      InspectorStyleSheet* styleSheet =
          m_cssStyleSheetToInspectorStyleSheet.get(sheet);
      const CSSRuleVector ruleVector = styleSheet->flatRules();
      for (auto rule : ruleVector) {
        if (rule->type() != CSSRule::kStyleRule)
          continue;

        CSSStyleRule* cssRule = static_cast<CSSStyleRule*>(rule.get());

        StyleRule* styleRule = cssRule->styleRule();

        std::unique_ptr<protocol::CSS::RuleUsage> protocolRule =
            buildObjectForRuleUsage(cssRule, m_tracker->contains(styleRule));
        if (!protocolRule)
          continue;

        result->get()->addItem(std::move(protocolRule));
      }
    }
  }

  setUsageTrackerStatus(false);

  return Response::OK();
}

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);
  visitor->trace(m_tracker);
  InspectorBaseAgent::trace(visitor);
}

}  // namespace blink
