| Index: third_party/WebKit/Source/devtools/front_end/elements/StylesSectionModel.js
 | 
| diff --git a/third_party/WebKit/Source/devtools/front_end/elements/StylesSectionModel.js b/third_party/WebKit/Source/devtools/front_end/elements/StylesSectionModel.js
 | 
| index 3389f7158824375376414651a1b7f38514ded87a..186fcff1a5b34373f4851b6f924b4708a76cc844 100644
 | 
| --- a/third_party/WebKit/Source/devtools/front_end/elements/StylesSectionModel.js
 | 
| +++ b/third_party/WebKit/Source/devtools/front_end/elements/StylesSectionModel.js
 | 
| @@ -4,45 +4,56 @@
 | 
|  
 | 
|  /**
 | 
|   * @constructor
 | 
| - * @param {!WebInspector.SectionCascade} cascade
 | 
| - * @param {?WebInspector.CSSRule} rule
 | 
| - * @param {!WebInspector.CSSStyleDeclaration} style
 | 
| - * @param {string} customSelectorText
 | 
| - * @param {?WebInspector.DOMNode=} inheritedFromNode
 | 
| + * @param {!WebInspector.CSSStyleModel.MatchedStyleResult} matchedStyles
 | 
| + * @param {!Array<!WebInspector.CSSStyleDeclaration>} styles
 | 
|   */
 | 
| -WebInspector.StylesSectionModel = function(cascade, rule, style, customSelectorText, inheritedFromNode)
 | 
| +WebInspector.SectionCascade = function(matchedStyles, styles)
 | 
|  {
 | 
| -    this._cascade = cascade;
 | 
| -    this._rule = rule;
 | 
| -    this._style = style;
 | 
| -    this._customSelectorText = customSelectorText;
 | 
| -    this._editable = !!(this._style && this._style.styleSheetId);
 | 
| -    this._inheritedFromNode = inheritedFromNode || null;
 | 
| +    this._matchedStyles = matchedStyles;
 | 
| +    this._styles = styles;
 | 
| +    this.resetActiveProperties();
 | 
|  }
 | 
|  
 | 
| -WebInspector.StylesSectionModel.prototype = {
 | 
| -    /**
 | 
| -     * @return {!WebInspector.SectionCascade}
 | 
| -     */
 | 
| -    cascade: function()
 | 
| -    {
 | 
| -        return this._cascade;
 | 
| -    },
 | 
| +/**
 | 
| + * @param {!WebInspector.CSSStyleModel.MatchedStyleResult} matchedStyles
 | 
| + * @return {!{matched: !WebInspector.SectionCascade, pseudo: !Map.<number, !WebInspector.SectionCascade>}}
 | 
| + */
 | 
| +WebInspector.SectionCascade.fromMatchedStyles = function(matchedStyles)
 | 
| +{
 | 
| +    var matched = new WebInspector.SectionCascade(matchedStyles, matchedStyles.nodeStyles());
 | 
| +    var pseudo = new Map();
 | 
| +
 | 
| +    var pseudoStyles = matchedStyles.pseudoStyles();
 | 
| +    var pseudoElements = pseudoStyles.keysArray();
 | 
| +    for (var i = 0; i < pseudoElements.length; ++i) {
 | 
| +        var pseudoElement = pseudoElements[i];
 | 
| +        var pseudoCascade = new WebInspector.SectionCascade(matchedStyles, /** @type {!Array<!WebInspector.CSSStyleDeclaration>} */(pseudoStyles.get(pseudoElement)));
 | 
| +        pseudo.set(pseudoElement, pseudoCascade);
 | 
| +    }
 | 
| +
 | 
| +    return {
 | 
| +        matched: matched,
 | 
| +        pseudo: pseudo
 | 
| +    };
 | 
| +}
 | 
|  
 | 
| +WebInspector.SectionCascade.prototype = {
 | 
|      /**
 | 
| +     * @param {!WebInspector.CSSStyleDeclaration} style
 | 
|       * @return {boolean}
 | 
|       */
 | 
| -    hasMatchingSelectors: function()
 | 
| +    hasMatchingSelectors: function(style)
 | 
|      {
 | 
| -        return this.rule() ? this.rule().matchingSelectors.length > 0 && this.mediaMatches() : true;
 | 
| +        return style.parentRule ? style.parentRule.matchingSelectors && style.parentRule.matchingSelectors.length > 0 && this.mediaMatches(style) : true;
 | 
|      },
 | 
|  
 | 
|      /**
 | 
| +     * @param {!WebInspector.CSSStyleDeclaration} style
 | 
|       * @return {boolean}
 | 
|       */
 | 
| -    mediaMatches: function()
 | 
| +    mediaMatches: function(style)
 | 
|      {
 | 
| -        var media = this.media();
 | 
| +        var media = style.parentRule ? style.parentRule.media : [];
 | 
|          for (var i = 0; media && i < media.length; ++i) {
 | 
|              if (!media[i].active())
 | 
|                  return false;
 | 
| @@ -51,132 +62,45 @@ WebInspector.StylesSectionModel.prototype = {
 | 
|      },
 | 
|  
 | 
|      /**
 | 
| -     * @return {boolean}
 | 
| -     */
 | 
| -    inherited: function()
 | 
| -    {
 | 
| -        return !!this._inheritedFromNode;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| +     * @param {!WebInspector.CSSStyleDeclaration} style
 | 
|       * @return {?WebInspector.DOMNode}
 | 
|       */
 | 
| -    parentNode: function()
 | 
| +    nodeForStyle: function(style)
 | 
|      {
 | 
| -        return this._inheritedFromNode;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @return {string}
 | 
| -     */
 | 
| -    selectorText: function()
 | 
| -    {
 | 
| -        if (this._customSelectorText)
 | 
| -            return this._customSelectorText;
 | 
| -        return this.rule() ? this.rule().selectorText() : "";
 | 
| +        return this._matchedStyles.nodeForStyle(style);
 | 
|      },
 | 
|  
 | 
|      /**
 | 
| +     * @param {!WebInspector.CSSStyleDeclaration} style
 | 
|       * @return {boolean}
 | 
|       */
 | 
| -    editable: function()
 | 
| +    isInherited: function(style)
 | 
|      {
 | 
| -        return this._editable;
 | 
| +        return this._matchedStyles.isInherited(style);
 | 
|      },
 | 
|  
 | 
|      /**
 | 
| -     * @param {boolean} editable
 | 
| +     * @return {!Array.<!WebInspector.CSSStyleDeclaration>}
 | 
|       */
 | 
| -    setEditable: function(editable)
 | 
| +    styles: function()
 | 
|      {
 | 
| -        this._editable = editable;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @return {!WebInspector.CSSStyleDeclaration}
 | 
| -     */
 | 
| -    style: function()
 | 
| -    {
 | 
| -        return this._style;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @return {?WebInspector.CSSRule}
 | 
| -     */
 | 
| -    rule: function()
 | 
| -    {
 | 
| -        return this._rule;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @return {?Array.<!WebInspector.CSSMedia>}
 | 
| -     */
 | 
| -    media: function()
 | 
| -    {
 | 
| -        return this.rule() ? this.rule().media : null;
 | 
| -    },
 | 
| -
 | 
| -    resetCachedData: function()
 | 
| -    {
 | 
| -        this._cascade._resetUsedProperties();
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * @constructor
 | 
| - */
 | 
| -WebInspector.SectionCascade = function()
 | 
| -{
 | 
| -    this._models = [];
 | 
| -    this._resetUsedProperties();
 | 
| -}
 | 
| -
 | 
| -WebInspector.SectionCascade.prototype = {
 | 
| -    /**
 | 
| -     * @return {!Array.<!WebInspector.StylesSectionModel>}
 | 
| -     */
 | 
| -    sectionModels: function()
 | 
| -    {
 | 
| -        return this._models;
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @param {!WebInspector.CSSRule} rule
 | 
| -     * @param {!WebInspector.StylesSectionModel} insertAfterStyleRule
 | 
| -     * @return {!WebInspector.StylesSectionModel}
 | 
| -     */
 | 
| -    insertModelFromRule: function(rule, insertAfterStyleRule)
 | 
| -    {
 | 
| -        return this._insertModel(new WebInspector.StylesSectionModel(this, rule, rule.style, "", null), insertAfterStyleRule);
 | 
| +        return this._styles;
 | 
|      },
 | 
|  
 | 
|      /**
 | 
|       * @param {!WebInspector.CSSStyleDeclaration} style
 | 
| -     * @param {string} selectorText
 | 
| -     * @param {?WebInspector.DOMNode=} inheritedFromNode
 | 
| -     * @return {!WebInspector.StylesSectionModel}
 | 
| -     */
 | 
| -    appendModelFromStyle: function(style, selectorText, inheritedFromNode)
 | 
| -    {
 | 
| -        return this._insertModel(new WebInspector.StylesSectionModel(this, style.parentRule, style, selectorText, inheritedFromNode));
 | 
| -    },
 | 
| -
 | 
| -    /**
 | 
| -     * @param {!WebInspector.StylesSectionModel} model
 | 
| -     * @param {!WebInspector.StylesSectionModel=} insertAfter
 | 
| -     * @return {!WebInspector.StylesSectionModel}
 | 
| +     * @param {!WebInspector.CSSStyleDeclaration=} insertAfter
 | 
|       */
 | 
| -    _insertModel: function(model, insertAfter)
 | 
| +    insertStyle: function(style, insertAfter)
 | 
|      {
 | 
|          if (insertAfter) {
 | 
| -            var index = this._models.indexOf(insertAfter);
 | 
| +            var index = this._styles.indexOf(insertAfter);
 | 
|              console.assert(index !== -1, "The insertAfter anchor could not be found in cascade");
 | 
| -            this._models.splice(index + 1, 0, model);
 | 
| +            this._styles.splice(index + 1, 0, style);
 | 
|          } else {
 | 
| -            this._models.push(model);
 | 
| +            this._styles.push(style);
 | 
|          }
 | 
| -        this._resetUsedProperties();
 | 
| -        return model;
 | 
| +        this.resetActiveProperties();
 | 
|      },
 | 
|  
 | 
|      /**
 | 
| @@ -186,110 +110,109 @@ WebInspector.SectionCascade.prototype = {
 | 
|      propertyState: function(property)
 | 
|      {
 | 
|          if (this._propertiesState.size === 0)
 | 
| -            this._propertiesState = WebInspector.SectionCascade._computeUsedProperties(this._models);
 | 
| +            this._propertiesState = this._computeActiveProperties();
 | 
|          return this._propertiesState.get(property) || null;
 | 
|      },
 | 
|  
 | 
| -    _resetUsedProperties: function()
 | 
| +    resetActiveProperties: function()
 | 
|      {
 | 
|          /** @type {!Map<!WebInspector.CSSProperty, !WebInspector.SectionCascade.PropertyState>} */
 | 
|          this._propertiesState = new Map();
 | 
| -    }
 | 
| -}
 | 
| -
 | 
| -/**
 | 
| - * @param {!Array.<!WebInspector.StylesSectionModel>} styleRules
 | 
| - * @return {!Map<!WebInspector.CSSProperty, !WebInspector.SectionCascade.PropertyState>}
 | 
| - */
 | 
| -WebInspector.SectionCascade._computeUsedProperties = function(styleRules)
 | 
| -{
 | 
| -    /** @type {!Set.<string>} */
 | 
| -    var foundImportantProperties = new Set();
 | 
| -    /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */
 | 
| -    var propertyToEffectiveRule = new Map();
 | 
| -    /** @type {!Map.<string, !WebInspector.DOMNode>} */
 | 
| -    var inheritedPropertyToNode = new Map();
 | 
| -    /** @type {!Set<string>} */
 | 
| -    var allUsedProperties = new Set();
 | 
| -    var result = new Map();
 | 
| -    for (var i = 0; i < styleRules.length; ++i) {
 | 
| -        var styleRule = styleRules[i];
 | 
| -        if (!styleRule.hasMatchingSelectors())
 | 
| -            continue;
 | 
| -
 | 
| -        /** @type {!Map<string, !WebInspector.CSSProperty>} */
 | 
| -        var styleActiveProperties = new Map();
 | 
| -        var style = styleRule.style();
 | 
| -        var allProperties = style.allProperties;
 | 
| -        for (var j = 0; j < allProperties.length; ++j) {
 | 
| -            var property = allProperties[j];
 | 
| +    },
 | 
|  
 | 
| -            // Do not pick non-inherited properties from inherited styles.
 | 
| -            if (styleRule.inherited() && !WebInspector.CSSMetadata.isPropertyInherited(property.name))
 | 
| +    /**
 | 
| +     * @return {!Map<!WebInspector.CSSProperty, !WebInspector.SectionCascade.PropertyState>}
 | 
| +     */
 | 
| +    _computeActiveProperties: function()
 | 
| +    {
 | 
| +        /** @type {!Set.<string>} */
 | 
| +        var foundImportantProperties = new Set();
 | 
| +        /** @type {!Map.<string, !Map<string, !WebInspector.CSSProperty>>} */
 | 
| +        var propertyToEffectiveRule = new Map();
 | 
| +        /** @type {!Map.<string, !WebInspector.DOMNode>} */
 | 
| +        var inheritedPropertyToNode = new Map();
 | 
| +        /** @type {!Set<string>} */
 | 
| +        var allUsedProperties = new Set();
 | 
| +        var result = new Map();
 | 
| +        for (var i = 0; i < this._styles.length; ++i) {
 | 
| +            var style = this._styles[i];
 | 
| +            if (!this.hasMatchingSelectors(style))
 | 
|                  continue;
 | 
|  
 | 
| -            if (!property.activeInStyle()) {
 | 
| -                result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| -                continue;
 | 
| -            }
 | 
| +            /** @type {!Map<string, !WebInspector.CSSProperty>} */
 | 
| +            var styleActiveProperties = new Map();
 | 
| +            var allProperties = style.allProperties;
 | 
| +            for (var j = 0; j < allProperties.length; ++j) {
 | 
| +                var property = allProperties[j];
 | 
|  
 | 
| -            var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(property.name);
 | 
| -            if (foundImportantProperties.has(canonicalName)) {
 | 
| -                result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| -                continue;
 | 
| -            }
 | 
| +                // Do not pick non-inherited properties from inherited styles.
 | 
| +                var inherited = this._matchedStyles.isInherited(style);
 | 
| +                if (inherited && !WebInspector.CSSMetadata.isPropertyInherited(property.name))
 | 
| +                    continue;
 | 
|  
 | 
| -            if (!property.important && allUsedProperties.has(canonicalName)) {
 | 
| -                result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| -                continue;
 | 
| -            }
 | 
| +                if (!property.activeInStyle()) {
 | 
| +                    result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| +                    continue;
 | 
| +                }
 | 
|  
 | 
| -            var isKnownProperty = propertyToEffectiveRule.has(canonicalName);
 | 
| -            var parentNode = styleRule.parentNode();
 | 
| -            if (!isKnownProperty && parentNode && !inheritedPropertyToNode.has(canonicalName))
 | 
| -                inheritedPropertyToNode.set(canonicalName, parentNode);
 | 
| +                var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(property.name);
 | 
| +                if (foundImportantProperties.has(canonicalName)) {
 | 
| +                    result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| +                    continue;
 | 
| +                }
 | 
|  
 | 
| -            if (property.important) {
 | 
| -                if (styleRule.inherited() && isKnownProperty && styleRule.parentNode() !== inheritedPropertyToNode.get(canonicalName)) {
 | 
| +                if (!property.important && allUsedProperties.has(canonicalName)) {
 | 
|                      result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
|                      continue;
 | 
|                  }
 | 
|  
 | 
| -                foundImportantProperties.add(canonicalName);
 | 
| -                if (isKnownProperty) {
 | 
| -                    var overloaded = propertyToEffectiveRule.get(canonicalName).get(canonicalName);
 | 
| -                    result.set(overloaded, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| -                    propertyToEffectiveRule.get(canonicalName).delete(canonicalName);
 | 
| +                var isKnownProperty = propertyToEffectiveRule.has(canonicalName);
 | 
| +                var inheritedFromNode = inherited ? this._matchedStyles.nodeForStyle(style) : null;
 | 
| +                if (!isKnownProperty && inheritedFromNode && !inheritedPropertyToNode.has(canonicalName))
 | 
| +                    inheritedPropertyToNode.set(canonicalName, inheritedFromNode);
 | 
| +
 | 
| +                if (property.important) {
 | 
| +                    if (inherited && isKnownProperty && inheritedFromNode !== inheritedPropertyToNode.get(canonicalName)) {
 | 
| +                        result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| +                        continue;
 | 
| +                    }
 | 
| +
 | 
| +                    foundImportantProperties.add(canonicalName);
 | 
| +                    if (isKnownProperty) {
 | 
| +                        var overloaded = propertyToEffectiveRule.get(canonicalName).get(canonicalName);
 | 
| +                        result.set(overloaded, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
| +                        propertyToEffectiveRule.get(canonicalName).delete(canonicalName);
 | 
| +                    }
 | 
|                  }
 | 
| -            }
 | 
|  
 | 
| -            styleActiveProperties.set(canonicalName, property);
 | 
| -            allUsedProperties.add(canonicalName);
 | 
| -            propertyToEffectiveRule.set(canonicalName, styleActiveProperties);
 | 
| -            result.set(property, WebInspector.SectionCascade.PropertyState.Active);
 | 
| -        }
 | 
| +                styleActiveProperties.set(canonicalName, property);
 | 
| +                allUsedProperties.add(canonicalName);
 | 
| +                propertyToEffectiveRule.set(canonicalName, styleActiveProperties);
 | 
| +                result.set(property, WebInspector.SectionCascade.PropertyState.Active);
 | 
| +            }
 | 
|  
 | 
| -        // If every longhand of the shorthand is not active, then the shorthand is not active too.
 | 
| -        for (var property of style.leadingProperties()) {
 | 
| -            var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(property.name);
 | 
| -            if (!styleActiveProperties.has(canonicalName))
 | 
| -                continue;
 | 
| -            var longhands = style.longhandProperties(property.name);
 | 
| -            if (!longhands.length)
 | 
| -                continue;
 | 
| -            var notUsed = true;
 | 
| -            for (var longhand of longhands) {
 | 
| -                var longhandCanonicalName = WebInspector.CSSMetadata.canonicalPropertyName(longhand.name);
 | 
| -                notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName);
 | 
| +            // If every longhand of the shorthand is not active, then the shorthand is not active too.
 | 
| +            for (var property of style.leadingProperties()) {
 | 
| +                var canonicalName = WebInspector.CSSMetadata.canonicalPropertyName(property.name);
 | 
| +                if (!styleActiveProperties.has(canonicalName))
 | 
| +                    continue;
 | 
| +                var longhands = style.longhandProperties(property.name);
 | 
| +                if (!longhands.length)
 | 
| +                    continue;
 | 
| +                var notUsed = true;
 | 
| +                for (var longhand of longhands) {
 | 
| +                    var longhandCanonicalName = WebInspector.CSSMetadata.canonicalPropertyName(longhand.name);
 | 
| +                    notUsed = notUsed && !styleActiveProperties.has(longhandCanonicalName);
 | 
| +                }
 | 
| +                if (!notUsed)
 | 
| +                    continue;
 | 
| +                styleActiveProperties.delete(canonicalName);
 | 
| +                allUsedProperties.delete(canonicalName);
 | 
| +                result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
|              }
 | 
| -            if (!notUsed)
 | 
| -                continue;
 | 
| -            styleActiveProperties.delete(canonicalName);
 | 
| -            allUsedProperties.delete(canonicalName);
 | 
| -            result.set(property, WebInspector.SectionCascade.PropertyState.Overloaded);
 | 
|          }
 | 
| +        return result;
 | 
|      }
 | 
| -    return result;
 | 
|  }
 | 
|  
 | 
|  /** @enum {string} */
 | 
| 
 |