[SCM] WebKit Debian packaging branch, debian/experimental, updated. upstream/1.3.3-9427-gc2be6fc

apavlov at chromium.org apavlov at chromium.org
Wed Dec 22 14:51:39 UTC 2010


The following commit has been merged in the debian/experimental branch:
commit fc8a58cd50c8355ff13f3724612c95b65ab658ae
Author: apavlov at chromium.org <apavlov at chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Date:   Fri Oct 22 15:04:52 2010 +0000

    2010-10-22  Alexander Pavlov  <apavlov at chromium.org>
    
            Reviewed by Pavel Feldman.
    
            Web Inspector: Implement property toggling in InspectorCSSAgent
    
            This change implements enablement/disablement and setting of style properties.
            Disabled properties are persisted in the (top-level) scope of InspectorStyleSheet.
            https://bugs.webkit.org/show_bug.cgi?id=47339
    
            Drive-by: fixes for the Web Inspector Protocol format.
    
            * inspector/InspectorCSSAgent.cpp:
            (WebCore::InspectorCSSAgent::getComputedStyleForNode2):
            (WebCore::InspectorCSSAgent::getInheritedStylesForNode2):
            (WebCore::InspectorCSSAgent::setPropertyText2):
            (WebCore::InspectorCSSAgent::toggleProperty2):
            (WebCore::InspectorCSSAgent::setRuleSelector2):
            (WebCore::InspectorCSSAgent::buildObjectForAttributeStyles):
            * inspector/InspectorCSSAgent.h:
            * inspector/InspectorStyleSheet.cpp:
            (WebCore::InspectorStyle::buildObjectForStyle):
            (WebCore::InspectorStyle::setPropertyText):
            (WebCore::InspectorStyle::toggleProperty):
            (WebCore::InspectorStyle::disabledIndexByOrdinal):
            (WebCore::InspectorStyle::styleText):
            (WebCore::InspectorStyle::disableProperty):
            (WebCore::InspectorStyle::enableProperty):
            (WebCore::InspectorStyle::populateAllProperties):
            (WebCore::InspectorStyle::populateObjectWithStyleProperties):
            (WebCore::InspectorStyle::shiftDisabledProperties):
            (WebCore::InspectorStyle::replacePropertyInStyleText):
            (WebCore::InspectorStyle::shorthandValue):
            (WebCore::InspectorStyle::shorthandPriority):
            (WebCore::InspectorStyle::longhandProperties):
            (WebCore::InspectorStyleSheet::setText):
            (WebCore::InspectorStyleSheet::setRuleSelector):
            (WebCore::InspectorStyleSheet::addRule):
            (WebCore::InspectorStyleSheet::ruleForId):
            (WebCore::InspectorStyleSheet::buildObjectForStyleSheet):
            (WebCore::InspectorStyleSheet::buildObjectForRule):
            (WebCore::InspectorStyleSheet::buildObjectForStyle):
            (WebCore::InspectorStyleSheet::setPropertyText):
            (WebCore::InspectorStyleSheet::toggleProperty):
            (WebCore::InspectorStyleSheet::styleForId):
            (WebCore::InspectorStyleSheet::inspectorStyleForId):
            (WebCore::InspectorStyleSheet::rememberInspectorStyle):
            (WebCore::InspectorStyleSheet::forgetInspectorStyle):
            (WebCore::InspectorStyleSheet::ruleOrStyleId):
            (WebCore::InspectorStyleSheet::ensureText):
            (WebCore::InspectorStyleSheet::setStyleText):
            (WebCore::InspectorStyleSheet::styleSheetTextWithChangedStyle):
            (WebCore::InspectorStyleSheet::ruleId):
            (WebCore::InspectorStyleSheet::revalidateStyle):
            (WebCore::InspectorStyleSheet::originalStyleSheetText):
            (WebCore::InspectorStyleSheet::resourceStyleSheetText):
            (WebCore::InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle):
            (WebCore::InspectorStyleSheetForInlineStyle::setStyleText):
            (WebCore::InspectorStyleSheetForInlineStyle::inspectorStyleForId):
            * inspector/InspectorStyleSheet.h:
            (WebCore::InspectorCSSId::createFromParts):
            (WebCore::InspectorCSSId::InspectorCSSId):
            (WebCore::InspectorCSSId::styleSheetId):
            (WebCore::InspectorCSSId::ordinal):
            (WebCore::InspectorCSSId::isEmpty):
            (WebCore::InspectorCSSId::asString):
            (WebCore::InspectorStyleProperty::InspectorStyleProperty):
            (WebCore::InspectorStyle::create):
            (WebCore::InspectorStyle::InspectorStyle):
            (WebCore::InspectorStyle::cssStyle):
            (WebCore::InspectorStyle::hasDisabledProperties):
            (WebCore::InspectorStyleSheet::styleId):
            (WebCore::InspectorStyleSheetForInlineStyle::styleForId):
            (WebCore::InspectorStyleSheetForInlineStyle::ruleSourceDataFor):
            (WebCore::InspectorStyleSheetForInlineStyle::rememberInspectorStyle):
            (WebCore::InspectorStyleSheetForInlineStyle::forgetInspectorStyle):
    
    
    git-svn-id: http://svn.webkit.org/repository/webkit/trunk@70306 268f45cc-cd09-0410-ab3c-d52691b4dbfc

diff --git a/WebCore/ChangeLog b/WebCore/ChangeLog
index 515d2f0..e7336fe 100644
--- a/WebCore/ChangeLog
+++ b/WebCore/ChangeLog
@@ -1,3 +1,80 @@
+2010-10-22  Alexander Pavlov  <apavlov at chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: Implement property toggling in InspectorCSSAgent
+
+        This change implements enablement/disablement and setting of style properties.
+        Disabled properties are persisted in the (top-level) scope of InspectorStyleSheet.
+        https://bugs.webkit.org/show_bug.cgi?id=47339
+
+        Drive-by: fixes for the Web Inspector Protocol format.
+
+        * inspector/InspectorCSSAgent.cpp:
+        (WebCore::InspectorCSSAgent::getComputedStyleForNode2):
+        (WebCore::InspectorCSSAgent::getInheritedStylesForNode2):
+        (WebCore::InspectorCSSAgent::setPropertyText2):
+        (WebCore::InspectorCSSAgent::toggleProperty2):
+        (WebCore::InspectorCSSAgent::setRuleSelector2):
+        (WebCore::InspectorCSSAgent::buildObjectForAttributeStyles):
+        * inspector/InspectorCSSAgent.h:
+        * inspector/InspectorStyleSheet.cpp:
+        (WebCore::InspectorStyle::buildObjectForStyle):
+        (WebCore::InspectorStyle::setPropertyText):
+        (WebCore::InspectorStyle::toggleProperty):
+        (WebCore::InspectorStyle::disabledIndexByOrdinal):
+        (WebCore::InspectorStyle::styleText):
+        (WebCore::InspectorStyle::disableProperty):
+        (WebCore::InspectorStyle::enableProperty):
+        (WebCore::InspectorStyle::populateAllProperties):
+        (WebCore::InspectorStyle::populateObjectWithStyleProperties):
+        (WebCore::InspectorStyle::shiftDisabledProperties):
+        (WebCore::InspectorStyle::replacePropertyInStyleText):
+        (WebCore::InspectorStyle::shorthandValue):
+        (WebCore::InspectorStyle::shorthandPriority):
+        (WebCore::InspectorStyle::longhandProperties):
+        (WebCore::InspectorStyleSheet::setText):
+        (WebCore::InspectorStyleSheet::setRuleSelector):
+        (WebCore::InspectorStyleSheet::addRule):
+        (WebCore::InspectorStyleSheet::ruleForId):
+        (WebCore::InspectorStyleSheet::buildObjectForStyleSheet):
+        (WebCore::InspectorStyleSheet::buildObjectForRule):
+        (WebCore::InspectorStyleSheet::buildObjectForStyle):
+        (WebCore::InspectorStyleSheet::setPropertyText):
+        (WebCore::InspectorStyleSheet::toggleProperty):
+        (WebCore::InspectorStyleSheet::styleForId):
+        (WebCore::InspectorStyleSheet::inspectorStyleForId):
+        (WebCore::InspectorStyleSheet::rememberInspectorStyle):
+        (WebCore::InspectorStyleSheet::forgetInspectorStyle):
+        (WebCore::InspectorStyleSheet::ruleOrStyleId):
+        (WebCore::InspectorStyleSheet::ensureText):
+        (WebCore::InspectorStyleSheet::setStyleText):
+        (WebCore::InspectorStyleSheet::styleSheetTextWithChangedStyle):
+        (WebCore::InspectorStyleSheet::ruleId):
+        (WebCore::InspectorStyleSheet::revalidateStyle):
+        (WebCore::InspectorStyleSheet::originalStyleSheetText):
+        (WebCore::InspectorStyleSheet::resourceStyleSheetText):
+        (WebCore::InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle):
+        (WebCore::InspectorStyleSheetForInlineStyle::setStyleText):
+        (WebCore::InspectorStyleSheetForInlineStyle::inspectorStyleForId):
+        * inspector/InspectorStyleSheet.h:
+        (WebCore::InspectorCSSId::createFromParts):
+        (WebCore::InspectorCSSId::InspectorCSSId):
+        (WebCore::InspectorCSSId::styleSheetId):
+        (WebCore::InspectorCSSId::ordinal):
+        (WebCore::InspectorCSSId::isEmpty):
+        (WebCore::InspectorCSSId::asString):
+        (WebCore::InspectorStyleProperty::InspectorStyleProperty):
+        (WebCore::InspectorStyle::create):
+        (WebCore::InspectorStyle::InspectorStyle):
+        (WebCore::InspectorStyle::cssStyle):
+        (WebCore::InspectorStyle::hasDisabledProperties):
+        (WebCore::InspectorStyleSheet::styleId):
+        (WebCore::InspectorStyleSheetForInlineStyle::styleForId):
+        (WebCore::InspectorStyleSheetForInlineStyle::ruleSourceDataFor):
+        (WebCore::InspectorStyleSheetForInlineStyle::rememberInspectorStyle):
+        (WebCore::InspectorStyleSheetForInlineStyle::forgetInspectorStyle):
+
 2010-10-22  Pavel Feldman  <pfeldman at chromium.org>
 
         Reviewed by Yury Semikhatsky.
diff --git a/WebCore/inspector/InspectorCSSAgent.cpp b/WebCore/inspector/InspectorCSSAgent.cpp
index e0fab85..d1f7412 100644
--- a/WebCore/inspector/InspectorCSSAgent.cpp
+++ b/WebCore/inspector/InspectorCSSAgent.cpp
@@ -49,7 +49,8 @@
 #include <wtf/Vector.h>
 #include <wtf/text/CString.h>
 
-
+// Currently implemented model:
+//
 // cssProperty = {
 //    name          : <string>,
 //    value         : <string>,
@@ -62,85 +63,57 @@
 //    endOffset     : <number>, // Optional - property text end offset in enclosing style declaration. Absent for computed styles and such.
 // }
 //
+// name + value + priority : present when the property is enabled
+// text                    : present when the property is disabled
+//
+// For disabled properties, startOffset === endOffset === insertion point for the property.
+//
 // status:
 // "disabled" == property disabled by user
 // "active" == property participates in the computed style calculation
 // "inactive" == property does no participate in the computed style calculation (i.e. overridden by a subsequent property with the same name)
 // "style" == property is active and originates from the WebCore CSSStyleDeclaration rather than CSS source code (e.g. implicit longhand properties)
 //
-//
 // cssStyle = {
-//    styleId         : <number>, // Optional
-//    styleSheetId    : <number>, // Parent: -1 for inline styles (<foo style="..">)
-//    cssProperties   : [
+//    styleId            : <string>, // Optional
+//    cssProperties      : [
 //                          #cssProperty,
 //                          ...
 //                          #cssProperty
-//                    ],
-//    shorthandValues : {
+//                         ],
+//    shorthandValues    : {
 //                          shorthandName1 : shorthandValue1,
 //                          shorthandName2 : shorthandValue2
-//                      },
-//    cssText         : <string>, // declaration text
-//    properties      : { } // ???
+//                         },
+//    cssText            : <string>, // Optional - declaration text
+//    properties         : { width, height }
 // }
 //
-// // TODO:
-// // - convert disabledProperties to enabled flag.
-// // - convert width, height to properties
-//
 // cssRule = {
-//    ruleId       : <number>,
-//    selectorText : <string>
-//    sourceURL    : <string>
-//    sourceLine   : <string>
-//    styleSheetId : <number> // also found in style
-//    origin       : <string> // "" || "user-agent" || "user" || "inspector"
+//    ruleId       : <string>, // Optional
+//    selectorText : <string>,
+//    sourceURL    : <string>,
+//    sourceLine   : <string>,
+//    origin       : <string>, // "" || "user-agent" || "user" || "inspector"
 //    style        : #cssStyle
 // }
 //
-// // TODO:
-// // - fix origin
-// // - add sourceURL
-// // - fix parentStyleSheetId
-//
 // cssStyleSheet = {
 //    styleSheetId   : <number>
-//    href           : <string>
+//    sourceURL      : <string>
 //    title          : <string>
 //    disabled       : <boolean>
-//    documentNodeId : <number>
 //    rules          : [
 //                         #cssRule,
 //                         ...
 //                         #cssRule
 //                     ]
+//    text           : <string> // Optional - whenever the text is available for a text-based stylesheet
 // }
 
 namespace WebCore {
 
 // static
-PassRefPtr<InspectorObject> InspectorCSSAgent::buildObjectForStyle(CSSStyleDeclaration* style, const String& fullStyleId, CSSStyleSourceData* sourceData)
-{
-    RefPtr<InspectorObject> result = InspectorObject::create();
-    if (!fullStyleId.isEmpty())
-        result->setString("id", fullStyleId);
-
-    result->setString("width", style->getPropertyValue("width"));
-    result->setString("height", style->getPropertyValue("height"));
-    Vector<CSSPropertySourceData>* propertyData = 0;
-
-    if (sourceData) {
-        result->setNumber("startOffset", sourceData->styleBodyRange.start);
-        result->setNumber("endOffset", sourceData->styleBodyRange.end);
-        propertyData = &sourceData->propertyData;
-    }
-    populateObjectWithStyleProperties(style, result.get(), propertyData);
-
-    return result.release();
-}
-
-// static
 CSSStyleSheet* InspectorCSSAgent::parentStyleSheet(StyleBase* styleBase)
 {
     if (!styleBase)
@@ -164,7 +137,6 @@ CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(StyleBase* styleBase)
     return static_cast<CSSStyleRule*>(rule);
 }
 
-
 InspectorCSSAgent::InspectorCSSAgent(InspectorDOMAgent* domAgent, InspectorFrontend* frontend)
     : m_domAgent(domAgent)
     , m_frontend(frontend)
@@ -246,7 +218,10 @@ void InspectorCSSAgent::getComputedStyleForNode2(long nodeId, RefPtr<InspectorVa
     if (!defaultView)
         return;
 
-    *style = buildObjectForStyle(defaultView->getComputedStyle(element, "").get(), "");
+    RefPtr<CSSStyleDeclaration> computedStyle = defaultView->getComputedStyle(element, "");
+    Vector<InspectorStyleProperty> properties;
+    RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyle.get(), 0);
+    *style = inspectorStyle->buildObjectForStyle();
 }
 
 void InspectorCSSAgent::getInheritedStylesForNode2(long nodeId, RefPtr<InspectorArray>* style)
@@ -263,7 +238,7 @@ void InspectorCSSAgent::getInheritedStylesForNode2(long nodeId, RefPtr<Inspector
         if (parentElement->style() && parentElement->style()->length()) {
             InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
             if (styleSheet)
-                parentStyle->setObject("inlineStyle", styleSheet->buildObjectForStyle(styleSheet->styleForId("0")));
+                parentStyle->setObject("inlineStyle", styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId::createFromParts(styleSheet->id(), "0"))));
         }
 
         CSSStyleSelector* parentSelector = parentElement->ownerDocument()->styleSelector();
@@ -308,43 +283,48 @@ void InspectorCSSAgent::setStyleSheetText2(const String& styleSheetId, const Str
     inspectorStyleSheet->setText(text);
 }
 
-void InspectorCSSAgent::setStyleText2(const String& fullStyleId, const String& text, RefPtr<InspectorValue>* result)
+void InspectorCSSAgent::setPropertyText2(const String& fullStyleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result)
 {
-    Vector<String> idParts;
-    fullStyleId.split(':', idParts);
-    ASSERT(idParts.size() == 2);
+    InspectorCSSId compoundId(fullStyleId);
+    ASSERT(!compoundId.isEmpty());
 
-    InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(idParts.at(0));
+    InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(compoundId.styleSheetId());
     if (!inspectorStyleSheet)
         return;
 
-    if (!inspectorStyleSheet->setStyleText(idParts.at(1), text))
-        return;
-
-    *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(idParts.at(1)));
+    bool success = inspectorStyleSheet->setPropertyText(compoundId, propertyIndex, text, overwrite);
+    if (success)
+        *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
 }
 
-void InspectorCSSAgent::toggleProperty2(const String&, long, bool)
+void InspectorCSSAgent::toggleProperty2(const String& fullStyleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result)
 {
-    // FIXME(apavlov): implement
+    InspectorCSSId compoundId(fullStyleId);
+    ASSERT(!compoundId.isEmpty());
+
+    InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(compoundId.styleSheetId());
+    if (!inspectorStyleSheet)
+        return;
+
+    bool success = inspectorStyleSheet->toggleProperty(compoundId, propertyIndex, disable);
+    if (success)
+        *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
 }
 
 void InspectorCSSAgent::setRuleSelector2(const String& fullRuleId, const String& selector, RefPtr<InspectorValue>* result)
 {
-    Vector<String> idParts;
-    fullRuleId.split(':', idParts);
-    ASSERT(idParts.size() == 2);
+    InspectorCSSId compoundId(fullRuleId);
+    ASSERT(!compoundId.isEmpty());
 
-    InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(idParts.at(0));
+    InspectorStyleSheet* inspectorStyleSheet = styleSheetForId(compoundId.styleSheetId());
     if (!inspectorStyleSheet)
         return;
 
-    const String& ruleId = idParts.at(1);
-    bool success = inspectorStyleSheet->setRuleSelector(ruleId, selector);
+    bool success = inspectorStyleSheet->setRuleSelector(compoundId, selector);
     if (!success)
         return;
 
-    *result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(ruleId));
+    *result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
 }
 
 void InspectorCSSAgent::addRule2(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result)
@@ -379,130 +359,6 @@ Element* InspectorCSSAgent::inlineStyleElement(CSSStyleDeclaration* style)
     return static_cast<Element*>(node);
 }
 
-// static
-void InspectorCSSAgent::populateObjectWithStyleProperties(CSSStyleDeclaration* style, InspectorObject* result, Vector<CSSPropertySourceData>* propertyData)
-{
-    RefPtr<InspectorArray> properties = InspectorArray::create();
-    RefPtr<InspectorObject> shorthandValues = InspectorObject::create();
-    HashMap<String, RefPtr<InspectorObject> > propertyNameToPreviousActiveProperty;
-    HashSet<String> foundShorthands;
-    HashSet<String> sourcePropertyNames;
-    if (propertyData) {
-        for (Vector<CSSPropertySourceData>::const_iterator it = propertyData->begin(); it != propertyData->end(); ++it) {
-            const CSSPropertySourceData& propertyEntry = *it;
-            RefPtr<InspectorObject> property = InspectorObject::create();
-            properties->pushObject(property);
-            const String& name = propertyEntry.name;
-            sourcePropertyNames.add(name);
-            property->setString("name", name);
-            property->setString("value", propertyEntry.value);
-            property->setString("priority", propertyEntry.important ? "important" : "");
-            property->setString("status", "active");
-            property->setBoolean("parsedOk", propertyEntry.parsedOk);
-            property->setNumber("startOffset", propertyEntry.range.start);
-            property->setNumber("endOffset", propertyEntry.range.end);
-            if (propertyEntry.parsedOk) {
-                property->setBoolean("implicit", false);
-                String shorthand = style->getPropertyShorthand(name);
-                property->setString("shorthandName", shorthand);
-                if (!shorthand.isEmpty() && !foundShorthands.contains(shorthand)) {
-                    foundShorthands.add(shorthand);
-                    shorthandValues->setString(shorthand, shorthandValue(style, shorthand));
-                }
-            } else {
-                property->setBoolean("implicit", false);
-                property->setString("shorthandName", "");
-            }
-            HashMap<String, RefPtr<InspectorObject> >::iterator activeIt = propertyNameToPreviousActiveProperty.find(name);
-            if (activeIt != propertyNameToPreviousActiveProperty.end()) {
-                activeIt->second->setString("status", "inactive");
-                activeIt->second->setString("shorthandName", "");
-            }
-            propertyNameToPreviousActiveProperty.set(name, property);
-        }
-    }
-
-    for (int i = 0, size = style->length(); i < size; ++i) {
-        String name = style->item(i);
-        if (sourcePropertyNames.contains(name))
-            continue;
-
-        sourcePropertyNames.add(name);
-        RefPtr<InspectorObject> property = InspectorObject::create();
-        properties->pushObject(property);
-        property->setString("name", name);
-        property->setString("value", style->getPropertyValue(name));
-        property->setString("priority", style->getPropertyPriority("name"));
-        property->setBoolean("implicit", style->isPropertyImplicit(name));
-        property->setBoolean("parsedOk", true);
-        property->setString("status", "style");
-        String shorthand = style->getPropertyShorthand(name);
-        property->setString("shorthandName", shorthand);
-        if (!shorthand.isEmpty() && !foundShorthands.contains(shorthand)) {
-            foundShorthands.add(shorthand);
-            shorthandValues->setString(shorthand, shorthandValue(style, shorthand));
-        }
-    }
-
-    result->setArray("properties", properties);
-    result->setObject("shorthandValues", shorthandValues);
-}
-
-// static
-String InspectorCSSAgent::shorthandValue(CSSStyleDeclaration* style, const String& shorthandProperty)
-{
-    String value = style->getPropertyValue(shorthandProperty);
-    if (value.isEmpty()) {
-        for (unsigned i = 0; i < style->length(); ++i) {
-            String individualProperty = style->item(i);
-            if (style->getPropertyShorthand(individualProperty) != shorthandProperty)
-                continue;
-            if (style->isPropertyImplicit(individualProperty))
-                continue;
-            String individualValue = style->getPropertyValue(individualProperty);
-            if (individualValue == "initial")
-                continue;
-            if (value.length())
-                value.append(" ");
-            value.append(individualValue);
-        }
-    }
-    return value;
-}
-
-// static
-String InspectorCSSAgent::shorthandPriority(CSSStyleDeclaration* style, const String& shorthandProperty)
-{
-    String priority = style->getPropertyPriority(shorthandProperty);
-    if (priority.isEmpty()) {
-        for (unsigned i = 0; i < style->length(); ++i) {
-            String individualProperty = style->item(i);
-            if (style->getPropertyShorthand(individualProperty) != shorthandProperty)
-                continue;
-            priority = style->getPropertyPriority(individualProperty);
-            break;
-        }
-    }
-    return priority;
-}
-
-
-// static
-Vector<String> InspectorCSSAgent::longhandProperties(CSSStyleDeclaration* style, const String& shorthandProperty)
-{
-    Vector<String> properties;
-    HashSet<String> foundProperties;
-    for (unsigned i = 0; i < style->length(); ++i) {
-        String individualProperty = style->item(i);
-        if (foundProperties.contains(individualProperty) || style->getPropertyShorthand(individualProperty) != shorthandProperty)
-            continue;
-
-        foundProperties.add(individualProperty);
-        properties.append(individualProperty);
-    }
-    return properties;
-}
-
 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
 {
     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
@@ -622,7 +478,8 @@ PassRefPtr<InspectorObject> InspectorCSSAgent::buildObjectForAttributeStyles(Ele
         Attribute* attribute = attributes->attributeItem(i);
         if (attribute->style()) {
             String attributeName = attribute->localName();
-            styleAttributes->setObject(attributeName.utf8().data(), buildObjectForStyle(attribute->style(), ""));
+            RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), attribute->style(), 0);
+            styleAttributes->setObject(attributeName.utf8().data(), inspectorStyle->buildObjectForStyle());
         }
     }
 
diff --git a/WebCore/inspector/InspectorCSSAgent.h b/WebCore/inspector/InspectorCSSAgent.h
index eb6013b..341d09a 100644
--- a/WebCore/inspector/InspectorCSSAgent.h
+++ b/WebCore/inspector/InspectorCSSAgent.h
@@ -56,7 +56,6 @@ public:
         return adoptRef(new InspectorCSSAgent(domAgent, frontend));
     }
 
-    static PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*, const String& fullStyleId, CSSStyleSourceData* = 0);
     static CSSStyleSheet* parentStyleSheet(StyleBase*);
     static CSSStyleRule* asCSSStyleRule(StyleBase*);
 
@@ -73,8 +72,8 @@ public:
     void getAllStyles2(RefPtr<InspectorArray>* styles);
     void getStyleSheet2(const String& styleSheetId, RefPtr<InspectorValue>* result);
     void setStyleSheetText2(const String& styleSheetId, const String& text);
-    void setStyleText2(const String& styleId, const String& text, RefPtr<InspectorValue>* result);
-    void toggleProperty2(const String& styleId, long propertyOrdinal, bool disabled);
+    void setPropertyText2(const String& styleId, long propertyIndex, const String& text, bool overwrite, RefPtr<InspectorValue>* result);
+    void toggleProperty2(const String& styleId, long propertyIndex, bool disable, RefPtr<InspectorValue>* result);
     void setRuleSelector2(const String& ruleId, const String& selector, RefPtr<InspectorValue>* result);
     void addRule2(const long contextNodeId, const String& selector, RefPtr<InspectorValue>* result);
     void getSupportedCSSProperties(RefPtr<InspectorArray>* result);
@@ -82,21 +81,17 @@ public:
 private:
     typedef HashMap<String, RefPtr<InspectorStyleSheet> > IdToInspectorStyleSheet;
     typedef HashMap<CSSStyleSheet*, RefPtr<InspectorStyleSheet> > CSSStyleSheetToInspectorStyleSheet;
-    typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // for bogus "stylesheets" with inline node styles
+    typedef HashMap<Node*, RefPtr<InspectorStyleSheetForInlineStyle> > NodeToInspectorStyleSheet; // bogus "stylesheets" with elements' inline styles
     typedef HashMap<RefPtr<Document>, RefPtr<InspectorStyleSheet> > DocumentToViaInspectorStyleSheet; // "via inspector" stylesheets
 
     static Element* inlineStyleElement(CSSStyleDeclaration*);
-    static void populateObjectWithStyleProperties(CSSStyleDeclaration*, InspectorObject* result, Vector<CSSPropertySourceData>* propertyData);
-    static String shorthandValue(CSSStyleDeclaration*, const String& shorthandProperty);
-    static String shorthandPriority(CSSStyleDeclaration*, const String& shorthandProperty);
-    static Vector<String> longhandProperties(CSSStyleDeclaration*, const String& shorthandProperty);
 
     InspectorStyleSheetForInlineStyle* asInspectorStyleSheet(Element* element);
     Element* elementForId(long nodeId);
 
     InspectorStyleSheet* bindStyleSheet(CSSStyleSheet*);
     InspectorStyleSheet* viaInspectorStyleSheet(Document*, bool createIfAbsent);
-    InspectorStyleSheet* styleSheetForId(const String& styleSheetId);
+    InspectorStyleSheet* styleSheetForId(const String&);
     String detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument);
 
     PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList* ruleList);
diff --git a/WebCore/inspector/InspectorStyleSheet.cpp b/WebCore/inspector/InspectorStyleSheet.cpp
index 11cd649..dc2a47a 100644
--- a/WebCore/inspector/InspectorStyleSheet.cpp
+++ b/WebCore/inspector/InspectorStyleSheet.cpp
@@ -98,6 +98,369 @@ RefPtr<WebCore::CSSRuleSourceData> ParsedStyleSheet::ruleSourceDataAt(unsigned i
 
 namespace WebCore {
 
+PassRefPtr<InspectorObject> InspectorStyle::buildObjectForStyle() const
+{
+    RefPtr<InspectorObject> result = InspectorObject::create();
+    if (!m_styleId.isEmpty())
+        result->setString("styleId", m_styleId.asString());
+
+    RefPtr<InspectorObject> propertiesObject = InspectorObject::create();
+    propertiesObject->setString("width", m_style->getPropertyValue("width"));
+    propertiesObject->setString("height", m_style->getPropertyValue("height"));
+
+    RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet ? m_parentStyleSheet->ruleSourceDataFor(m_style) : 0;
+    if (sourceData) {
+        propertiesObject->setNumber("startOffset", sourceData->styleSourceData->styleBodyRange.start);
+        propertiesObject->setNumber("endOffset", sourceData->styleSourceData->styleBodyRange.end);
+    }
+    result->setObject("properties", propertiesObject);
+
+    populateObjectWithStyleProperties(result.get());
+
+    return result.release();
+}
+
+bool InspectorStyle::setPropertyText(unsigned index, const String& propertyText, bool overwrite)
+{
+    ASSERT(m_parentStyleSheet);
+    if (!m_parentStyleSheet->ensureParsedDataReady())
+        return false;
+
+    Vector<InspectorStyleProperty> allProperties;
+    populateAllProperties(&allProperties);
+
+    unsigned propertyStart = 0; // Need to initialize to make the compiler happy.
+    long propertyLengthDelta;
+
+    if (overwrite) {
+        ASSERT(index < allProperties.size());
+        InspectorStyleProperty& property = allProperties.at(index);
+        propertyStart = property.sourceData.range.start;
+        unsigned propertyEnd = property.sourceData.range.end;
+        unsigned oldLength = propertyEnd - propertyStart;
+        unsigned newLength = propertyText.length();
+        propertyLengthDelta = newLength - oldLength;
+
+        if (!property.disabled) {
+            bool success = replacePropertyInStyleText(property, propertyText);
+            if (!success)
+                return false;
+        } else {
+            property.rawText = propertyText;
+            if (!propertyText.length()) {
+                bool success = enableProperty(index, allProperties);
+                return success;
+            }
+        }
+    } else {
+        // Insert at index.
+        RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style);
+        if (!sourceData)
+            return false;
+        String text;
+        bool success = styleText(&text);
+        if (!success)
+            return false;
+        propertyLengthDelta = propertyText.length();
+
+        bool insertLast = true;
+        if (index < allProperties.size()) {
+            InspectorStyleProperty& property = allProperties.at(index);
+            if (property.hasSource) {
+                propertyStart = property.sourceData.range.start;
+                // If inserting before a disabled property, it should be shifted, too.
+                insertLast = false;
+            }
+        }
+        if (insertLast)
+            propertyStart = sourceData->styleSourceData->styleBodyRange.end;
+
+        text.insert(propertyText, propertyStart);
+        m_parentStyleSheet->setStyleText(m_style, text);
+    }
+
+    // Recompute subsequent disabled property ranges.
+    shiftDisabledProperties(disabledIndexByOrdinal(index, true, allProperties), propertyLengthDelta);
+
+    return true;
+}
+
+bool InspectorStyle::toggleProperty(unsigned index, bool disable)
+{
+    ASSERT(m_parentStyleSheet);
+    if (!m_parentStyleSheet->ensureParsedDataReady())
+        return false; // Can toggle only source-based properties.
+    RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style);
+    if (!sourceData)
+        return false; // No source data for the style.
+
+    Vector<InspectorStyleProperty> allProperties;
+    populateAllProperties(&allProperties);
+    if (index >= allProperties.size())
+        return false; // Outside of property range.
+
+    InspectorStyleProperty& property = allProperties.at(index);
+    if (property.disabled == disable)
+        return true; // Idempotent operation.
+
+    bool success;
+    if (!disable)
+        success = enableProperty(index, allProperties);
+    else
+        success = disableProperty(index, allProperties);
+
+    return success;
+}
+
+// static
+unsigned InspectorStyle::disabledIndexByOrdinal(unsigned ordinal, bool canUseSubsequent, Vector<InspectorStyleProperty>& allProperties)
+{
+    unsigned disabledIndex = 0;
+    for (unsigned i = 0, size = allProperties.size(); i < size; ++i) {
+        InspectorStyleProperty& property = allProperties.at(i);
+        if (property.disabled) {
+            if (i == ordinal || (canUseSubsequent && i > ordinal))
+                return disabledIndex;
+            ++disabledIndex;
+        }
+    }
+
+    return UINT_MAX;
+}
+
+bool InspectorStyle::styleText(String* result)
+{
+    // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully.
+    RefPtr<CSSRuleSourceData> sourceData = m_parentStyleSheet->ruleSourceDataFor(m_style);
+    if (!sourceData)
+        return false;
+
+    String styleSheetText;
+    bool success = m_parentStyleSheet->text(&styleSheetText);
+    if (!success)
+        return false;
+
+    SourceRange& bodyRange = sourceData->styleSourceData->styleBodyRange;
+    *result = styleSheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start);
+    return true;
+}
+
+bool InspectorStyle::disableProperty(unsigned indexToDisable, Vector<InspectorStyleProperty>& allProperties)
+{
+    // Precondition: |indexToEnable| points to an enabled property.
+    const InspectorStyleProperty& property = allProperties.at(indexToDisable);
+    InspectorStyleProperty disabledProperty(property);
+    disabledProperty.disabled = true;
+    unsigned propertyStart = property.sourceData.range.start;
+    // This may have to be negated below.
+    long propertyLength = property.sourceData.range.end - propertyStart;
+    disabledProperty.sourceData.range.end = propertyStart;
+    String oldStyleText;
+    bool success = styleText(&oldStyleText);
+    if (!success)
+        return false;
+    disabledProperty.rawText = oldStyleText.substring(propertyStart, propertyLength);
+    success = replacePropertyInStyleText(property, "");
+    if (!success)
+        return false;
+
+    // Add disabled property at correct position.
+    unsigned insertionIndex = disabledIndexByOrdinal(indexToDisable, true, allProperties);
+    if (insertionIndex == UINT_MAX)
+        m_disabledProperties.append(disabledProperty);
+    else {
+        m_disabledProperties.insert(insertionIndex, disabledProperty);
+        shiftDisabledProperties(insertionIndex + 1, -propertyLength); // Property removed from text - shift these back.
+    }
+    return true;
+}
+
+bool InspectorStyle::enableProperty(unsigned indexToEnable, Vector<InspectorStyleProperty>& allProperties)
+{
+    // Precondition: |indexToEnable| points to a disabled property.
+    unsigned disabledIndex = disabledIndexByOrdinal(indexToEnable, false, allProperties);
+    if (disabledIndex == UINT_MAX)
+        return false;
+
+    InspectorStyleProperty disabledProperty = m_disabledProperties.at(disabledIndex);
+    m_disabledProperties.remove(disabledIndex);
+    bool success = replacePropertyInStyleText(disabledProperty, disabledProperty.rawText);
+    if (success)
+        shiftDisabledProperties(disabledIndex, disabledProperty.rawText.length());
+    return success;
+}
+
+bool InspectorStyle::populateAllProperties(Vector<InspectorStyleProperty>* result) const
+{
+    HashSet<String> foundShorthands;
+    HashSet<String> sourcePropertyNames;
+    unsigned disabledIndex = 0;
+    unsigned disabledLength = m_disabledProperties.size();
+    InspectorStyleProperty disabledProperty;
+    if (disabledIndex < disabledLength)
+        disabledProperty = m_disabledProperties.at(disabledIndex);
+
+    RefPtr<CSSRuleSourceData> sourceData = (m_parentStyleSheet && m_parentStyleSheet->ensureParsedDataReady()) ? m_parentStyleSheet->ruleSourceDataFor(m_style) : 0;
+    Vector<CSSPropertySourceData>* sourcePropertyData = sourceData ? &(sourceData->styleSourceData->propertyData) : 0;
+    if (sourcePropertyData) {
+        for (Vector<CSSPropertySourceData>::const_iterator it = sourcePropertyData->begin(); it != sourcePropertyData->end(); ++it) {
+            while (disabledIndex < disabledLength && disabledProperty.sourceData.range.start <= it->range.start) {
+                result->append(disabledProperty);
+                if (++disabledIndex < disabledLength)
+                    disabledProperty = m_disabledProperties.at(disabledIndex);
+            }
+            result->append(InspectorStyleProperty(*it, true, false));
+            sourcePropertyNames.add(it->name);
+        }
+    }
+
+    while (disabledIndex < disabledLength) {
+        disabledProperty = m_disabledProperties.at(disabledIndex++);
+        result->append(disabledProperty);
+    }
+
+    for (int i = 0, size = m_style->length(); i < size; ++i) {
+        String name = m_style->item(i);
+        if (sourcePropertyNames.contains(name))
+            continue;
+
+        sourcePropertyNames.add(name);
+        result->append(InspectorStyleProperty(CSSPropertySourceData(name, m_style->getPropertyValue(name), !m_style->getPropertyPriority(name).isEmpty(), true, SourceRange()), false, false));
+    }
+
+    return true;
+}
+
+void InspectorStyle::populateObjectWithStyleProperties(InspectorObject* result) const
+{
+    Vector<InspectorStyleProperty> properties;
+    populateAllProperties(&properties);
+
+    RefPtr<InspectorArray> propertiesObject = InspectorArray::create();
+    RefPtr<InspectorObject> shorthandValues = InspectorObject::create();
+    HashMap<String, RefPtr<InspectorObject> > propertyNameToPreviousActiveProperty;
+    HashSet<String> foundShorthands;
+
+    for (Vector<InspectorStyleProperty>::iterator it = properties.begin(), itEnd = properties.end(); it != itEnd; ++it) {
+        const CSSPropertySourceData& propertyEntry = it->sourceData;
+        const String& name = propertyEntry.name;
+
+        RefPtr<InspectorObject> property = InspectorObject::create();
+        propertiesObject->pushObject(property);
+        property->setString("status", it->disabled ? "disabled" : "active");
+        property->setBoolean("parsedOk", propertyEntry.parsedOk);
+        if (!it->disabled) {
+            property->setString("name", name);
+            property->setString("value", propertyEntry.value);
+            property->setString("priority", propertyEntry.important ? "important" : "");
+            if (it->hasSource) {
+                property->setBoolean("implicit", false);
+                property->setNumber("startOffset", propertyEntry.range.start);
+                property->setNumber("endOffset", propertyEntry.range.end);
+
+                HashMap<String, RefPtr<InspectorObject> >::iterator activeIt = propertyNameToPreviousActiveProperty.find(name);
+                if (activeIt != propertyNameToPreviousActiveProperty.end()) {
+                    activeIt->second->setString("status", "inactive");
+                    activeIt->second->setString("shorthandName", "");
+                }
+                propertyNameToPreviousActiveProperty.set(name, property);
+            } else {
+                property->setBoolean("implicit", m_style->isPropertyImplicit(name));
+                property->setString("status", "style");
+            }
+        } else
+            property->setString("text", it->rawText);
+
+        if (propertyEntry.parsedOk) {
+            // Both for style-originated and parsed source properties.
+            String shorthand = m_style->getPropertyShorthand(name);
+            property->setString("shorthandName", shorthand);
+            if (!shorthand.isEmpty() && !foundShorthands.contains(shorthand)) {
+                foundShorthands.add(shorthand);
+                shorthandValues->setString(shorthand, shorthandValue(shorthand));
+            }
+        } else
+            property->setString("shorthandName", "");
+    }
+
+    result->setArray("cssProperties", propertiesObject);
+    result->setObject("shorthandValues", shorthandValues);
+}
+
+
+void InspectorStyle::shiftDisabledProperties(unsigned fromIndex, long delta)
+{
+    for (unsigned i = fromIndex, size = m_disabledProperties.size(); i < size; ++i) {
+        SourceRange& range = m_disabledProperties.at(i).sourceData.range;
+        range.start += delta;
+        range.end += delta;
+    }
+}
+
+bool InspectorStyle::replacePropertyInStyleText(const InspectorStyleProperty& property, const String& newText)
+{
+    // Precondition: m_parentStyleSheet->ensureParsedDataReady() has been called successfully.
+    String text;
+    bool success = styleText(&text);
+    if (!success)
+        return false;
+    const SourceRange& range = property.sourceData.range;
+    text.replace(range.start, range.end - range.start, newText);
+    success = m_parentStyleSheet->setStyleText(m_style, text);
+    return success;
+}
+
+String InspectorStyle::shorthandValue(const String& shorthandProperty) const
+{
+    String value = m_style->getPropertyValue(shorthandProperty);
+    if (value.isEmpty()) {
+        for (unsigned i = 0; i < m_style->length(); ++i) {
+            String individualProperty = m_style->item(i);
+            if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+                continue;
+            if (m_style->isPropertyImplicit(individualProperty))
+                continue;
+            String individualValue = m_style->getPropertyValue(individualProperty);
+            if (individualValue == "initial")
+                continue;
+            if (value.length())
+                value.append(" ");
+            value.append(individualValue);
+        }
+    }
+    return value;
+}
+
+String InspectorStyle::shorthandPriority(const String& shorthandProperty) const
+{
+    String priority = m_style->getPropertyPriority(shorthandProperty);
+    if (priority.isEmpty()) {
+        for (unsigned i = 0; i < m_style->length(); ++i) {
+            String individualProperty = m_style->item(i);
+            if (m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+                continue;
+            priority = m_style->getPropertyPriority(individualProperty);
+            break;
+        }
+    }
+    return priority;
+}
+
+Vector<String> InspectorStyle::longhandProperties(const String& shorthandProperty) const
+{
+    Vector<String> properties;
+    HashSet<String> foundProperties;
+    for (unsigned i = 0; i < m_style->length(); ++i) {
+        String individualProperty = m_style->item(i);
+        if (foundProperties.contains(individualProperty) || m_style->getPropertyShorthand(individualProperty) != shorthandProperty)
+            continue;
+
+        foundProperties.add(individualProperty);
+        properties.append(individualProperty);
+    }
+    return properties;
+}
+
 InspectorStyleSheet::InspectorStyleSheet(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL)
     : m_id(id)
     , m_pageStyleSheet(pageStyleSheet)
@@ -121,14 +484,15 @@ bool InspectorStyleSheet::setText(const String& text)
     m_parsedStyleSheet->setText(text);
     for (unsigned i = 0, size = m_pageStyleSheet->length(); i < size; ++i)
         m_pageStyleSheet->remove(i);
+    m_inspectorStyles.clear();
 
     m_pageStyleSheet->parseString(text, m_pageStyleSheet->useStrictParsing());
     return true;
 }
 
-bool InspectorStyleSheet::setRuleSelector(const String& ruleId, const String& selector)
+bool InspectorStyleSheet::setRuleSelector(const InspectorCSSId& id, const String& selector)
 {
-    CSSStyleRule* rule = ruleForId(ruleId);
+    CSSStyleRule* rule = ruleForId(id);
     if (!rule)
         return false;
     CSSStyleSheet* styleSheet = InspectorCSSAgent::parentStyleSheet(rule);
@@ -140,18 +504,16 @@ bool InspectorStyleSheet::setRuleSelector(const String& ruleId, const String& se
     if (!sourceData)
         return false;
 
-    const String& sheetText = m_parsedStyleSheet->text();
-    String newStyleSheetText = sheetText.substring(0, sourceData->selectorListRange.start);
-    newStyleSheetText += selector;
-    newStyleSheetText += sheetText.right(sheetText.length() - sourceData->selectorListRange.end);
-    m_parsedStyleSheet->setText(newStyleSheetText);
+    String sheetText = m_parsedStyleSheet->text();
+    sheetText.replace(sourceData->selectorListRange.start, sourceData->selectorListRange.end - sourceData->selectorListRange.start, selector);
+    m_parsedStyleSheet->setText(sheetText);
     return true;
 }
 
 CSSStyleRule* InspectorStyleSheet::addRule(const String& selector)
 {
-    String text;
-    bool success = styleSheetText(&text);
+    String styleSheetText;
+    bool success = text(&styleSheetText);
     if (!success)
         return 0;
 
@@ -164,23 +526,24 @@ CSSStyleRule* InspectorStyleSheet::addRule(const String& selector)
     CSSStyleRule* rule = InspectorCSSAgent::asCSSStyleRule(rules->item(rules->length() - 1));
     ASSERT(rule);
 
-    if (text.length())
-        text += "\n";
+    if (styleSheetText.length())
+        styleSheetText += "\n";
 
-    text += selector;
-    text += " {}";
-    m_parsedStyleSheet->setText(text);
+    styleSheetText += selector;
+    styleSheetText += " {}";
+    m_parsedStyleSheet->setText(styleSheetText);
 
     return rule;
 }
 
-CSSStyleRule* InspectorStyleSheet::ruleForId(const String& id) const
+CSSStyleRule* InspectorStyleSheet::ruleForId(const InspectorCSSId& id) const
 {
     if (!m_pageStyleSheet)
         return 0;
 
+    ASSERT(!id.isEmpty());
     bool ok;
-    unsigned index = id.toUInt(&ok);
+    unsigned index = id.ordinal().toUInt(&ok);
     if (!ok)
         return 0;
 
@@ -204,19 +567,20 @@ PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForStyleSheet()
         return 0;
 
     RefPtr<InspectorObject> result = InspectorObject::create();
-    result->setString("id", id());
     result->setBoolean("disabled", styleSheet->disabled());
-    result->setString("href", styleSheet->href());
+    result->setString("sourceURL", styleSheet->href());
     result->setString("title", styleSheet->title());
     RefPtr<CSSRuleList> cssRuleList = CSSRuleList::create(styleSheet, true);
     RefPtr<InspectorArray> cssRules = buildArrayForRuleList(cssRuleList.get());
-    result->setArray("cssRules", cssRules.release());
+    result->setArray("rules", cssRules.release());
 
     String styleSheetText;
     bool success = text(&styleSheetText);
     if (success)
         result->setString("text", styleSheetText);
 
+    result->setString("styleSheetId", id());
+
     return result.release();
 }
 
@@ -228,27 +592,13 @@ PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForRule(CSSStyleRule
 
     RefPtr<InspectorObject> result = InspectorObject::create();
     result->setString("selectorText", rule->selectorText());
-    result->setString("cssText", rule->cssText());
+    result->setString("sourceURL", !styleSheet->href().isEmpty() ? styleSheet->href() : m_documentURL);
     result->setNumber("sourceLine", rule->sourceLine());
-    result->setString("documentURL", m_documentURL);
-
-    RefPtr<InspectorObject> parentStyleSheetValue = InspectorObject::create();
-    parentStyleSheetValue->setString("id", id());
-    parentStyleSheetValue->setString("href", styleSheet->href());
-    result->setObject("parentStyleSheet", parentStyleSheetValue.release());
     result->setString("origin", m_origin);
 
-    RefPtr<CSSRuleSourceData> sourceData;
-    if (ensureParsedDataReady())
-        sourceData = ruleSourceDataFor(rule->style());
-    if (sourceData) {
-        result->setNumber("selectorStartOffset", sourceData->selectorListRange.start);
-        result->setNumber("selectorEndOffset", sourceData->selectorListRange.end);
-    }
-
     result->setObject("style", buildObjectForStyle(rule->style()));
     if (canBind())
-        result->setString("id", fullRuleId(rule));
+        result->setString("ruleId", ruleId(rule).asString());
 
     return result.release();
 }
@@ -259,12 +609,48 @@ PassRefPtr<InspectorObject> InspectorStyleSheet::buildObjectForStyle(CSSStyleDec
     if (ensureParsedDataReady())
         sourceData = ruleSourceDataFor(style);
 
-    RefPtr<InspectorObject> result = InspectorCSSAgent::buildObjectForStyle(style, fullStyleId(style), sourceData ? sourceData->styleSourceData.get() : 0);
-    result->setString("parentStyleSheetId", id());
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(ruleOrStyleId(style));
+    RefPtr<InspectorObject> result = inspectorStyle->buildObjectForStyle();
+
+    // Style text cannot be retrieved without stylesheet, so set cssText here.
+    if (sourceData) {
+        String sheetText;
+        bool success = text(&sheetText);
+        if (success) {
+            const SourceRange& bodyRange = sourceData->styleSourceData->styleBodyRange;
+            result->setString("cssText", sheetText.substring(bodyRange.start, bodyRange.end - bodyRange.start));
+        }
+    }
+
     return result.release();
 }
 
-CSSStyleDeclaration* InspectorStyleSheet::styleForId(const String& id) const
+bool InspectorStyleSheet::setPropertyText(const InspectorCSSId& id, unsigned propertyIndex, const String& text, bool overwrite)
+{
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    if (!inspectorStyle)
+        return false;
+
+    return inspectorStyle->setPropertyText(propertyIndex, text, overwrite);
+}
+
+bool InspectorStyleSheet::toggleProperty(const InspectorCSSId& id, unsigned propertyIndex, bool disable)
+{
+    RefPtr<InspectorStyle> inspectorStyle = inspectorStyleForId(id);
+    if (!inspectorStyle)
+        return false;
+
+    bool success = inspectorStyle->toggleProperty(propertyIndex, disable);
+    if (success) {
+        if (disable)
+            rememberInspectorStyle(inspectorStyle);
+        else if (!inspectorStyle->hasDisabledProperties())
+            forgetInspectorStyle(inspectorStyle->cssStyle());
+    }
+    return success;
+}
+
+CSSStyleDeclaration* InspectorStyleSheet::styleForId(const InspectorCSSId& id) const
 {
     CSSStyleRule* rule = ruleForId(id);
     if (!rule)
@@ -273,13 +659,36 @@ CSSStyleDeclaration* InspectorStyleSheet::styleForId(const String& id) const
     return rule->style();
 }
 
-bool InspectorStyleSheet::setStyleText(const String& styleId, const String& newText)
+PassRefPtr<InspectorStyle> InspectorStyleSheet::inspectorStyleForId(const InspectorCSSId& id)
 {
-    CSSStyleDeclaration* style = styleForId(styleId);
+    CSSStyleDeclaration* style = styleForId(id);
     if (!style)
-        return false;
+        return 0;
+
+    InspectorStyleMap::iterator it = m_inspectorStyles.find(style);
+    if (it == m_inspectorStyles.end()) {
+        RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(id, style, this);
+        return inspectorStyle.release();
+    }
+    return it->second;
+}
 
-    return innerSetStyleText(style, newText);
+void InspectorStyleSheet::rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle)
+{
+    m_inspectorStyles.set(inspectorStyle->cssStyle(), inspectorStyle);
+}
+
+void InspectorStyleSheet::forgetInspectorStyle(CSSStyleDeclaration* style)
+{
+    m_inspectorStyles.remove(style);
+}
+
+InspectorCSSId InspectorStyleSheet::ruleOrStyleId(CSSStyleDeclaration* style) const
+{
+    unsigned index = ruleIndexByStyle(style);
+    if (index != UINT_MAX)
+        return InspectorCSSId::createFromParts(id(), String::number(index));
+    return InspectorCSSId();
 }
 
 Document* InspectorStyleSheet::ownerDocument() const
@@ -328,7 +737,7 @@ bool InspectorStyleSheet::ensureText() const
         return true;
 
     String text;
-    bool success = styleSheetText(&text);
+    bool success = originalStyleSheetText(&text);
     if (success)
         m_parsedStyleSheet->setText(text);
 
@@ -362,12 +771,7 @@ bool InspectorStyleSheet::ensureSourceData(Node* ownerNode)
     return m_parsedStyleSheet->hasSourceData();
 }
 
-void InspectorStyleSheet::innerSetStyleSheetText(const String& newText)
-{
-    m_parsedStyleSheet->setText(newText);
-}
-
-bool InspectorStyleSheet::innerSetStyleText(CSSStyleDeclaration* style, const String& text)
+bool InspectorStyleSheet::setStyleText(CSSStyleDeclaration* style, const String& text)
 {
     if (!pageStyleSheet())
         return false;
@@ -379,14 +783,14 @@ bool InspectorStyleSheet::innerSetStyleText(CSSStyleDeclaration* style, const St
     if (!success)
         return false;
 
-    String id = ruleOrStyleId(style);
+    InspectorCSSId id = ruleOrStyleId(style);
     if (id.isEmpty())
         return false;
 
     ExceptionCode ec = 0;
     style->setCssText(text, ec);
     if (!ec)
-        innerSetStyleSheetText(patchedStyleSheetText);
+        m_parsedStyleSheet->setText(patchedStyleSheetText);
 
     return !ec;
 }
@@ -407,10 +811,8 @@ bool InspectorStyleSheet::styleSheetTextWithChangedStyle(CSSStyleDeclaration* st
     String text = m_parsedStyleSheet->text();
     ASSERT(bodyEnd <= text.length()); // bodyEnd is exclusive
 
-    String patchedText = text.substring(0, bodyStart);
-    patchedText += newStyleText;
-    patchedText += text.substring(bodyEnd, text.length());
-    *result = patchedText;
+    text.replace(bodyStart, bodyEnd - bodyStart, newStyleText);
+    *result = text;
     return true;
 }
 
@@ -426,9 +828,9 @@ CSSStyleRule* InspectorStyleSheet::findPageRuleWithStyle(CSSStyleDeclaration* st
     return 0;
 }
 
-String InspectorStyleSheet::fullRuleId(CSSStyleRule* rule) const
+InspectorCSSId InspectorStyleSheet::ruleId(CSSStyleRule* rule) const
 {
-    return fullRuleOrStyleId(rule->style());
+    return ruleOrStyleId(rule->style());
 }
 
 void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle)
@@ -444,15 +846,18 @@ void InspectorStyleSheet::revalidateStyle(CSSStyleDeclaration* pageStyle)
         if (!parsedRule)
             continue;
         if (parsedRule->style() == pageStyle) {
-            if (parsedRule->style()->cssText() != pageStyle->cssText())
-                innerSetStyleText(pageStyle, pageStyle->cssText());
+            if (parsedRule->style()->cssText() != pageStyle->cssText()) {
+                // Clear the disabled properties for the invalid style here.
+                m_inspectorStyles.remove(pageStyle);
+                setStyleText(pageStyle, pageStyle->cssText());
+            }
             break;
         }
     }
     m_isRevalidating = false;
 }
 
-bool InspectorStyleSheet::styleSheetText(String* result) const
+bool InspectorStyleSheet::originalStyleSheetText(String* result) const
 {
     String text;
     bool success = inlineStyleSheetText(&text);
@@ -465,7 +870,7 @@ bool InspectorStyleSheet::styleSheetText(String* result) const
 
 bool InspectorStyleSheet::resourceStyleSheetText(String* result) const
 {
-    if (!m_pageStyleSheet)
+    if (!m_pageStyleSheet || !ownerDocument())
         return false;
 
     return InspectorResourceAgent::resourceContent(ownerDocument()->frame(), m_pageStyleSheet->finalURL(), result);
@@ -509,12 +914,12 @@ InspectorStyleSheetForInlineStyle::InspectorStyleSheetForInlineStyle(const Strin
     , m_ruleSourceData(0)
 {
     ASSERT(element);
+    m_inspectorStyle = InspectorStyle::create(InspectorCSSId::createFromParts(id, "0"), inlineStyle(), this);
 }
 
-bool InspectorStyleSheetForInlineStyle::setStyleText(const String& styleId, const String& text)
+bool InspectorStyleSheetForInlineStyle::setStyleText(CSSStyleDeclaration* style, const String& text)
 {
-    ASSERT(styleId == "0");
-    UNUSED_PARAM(styleId);
+    ASSERT_UNUSED(style, style == inlineStyle());
     ExceptionCode ec = 0;
     m_element->setAttribute("style", text, ec);
     m_ruleSourceData.clear();
@@ -541,6 +946,12 @@ bool InspectorStyleSheetForInlineStyle::ensureParsedDataReady()
     return true;
 }
 
+PassRefPtr<InspectorStyle> InspectorStyleSheetForInlineStyle::inspectorStyleForId(const InspectorCSSId& id)
+{
+    ASSERT_UNUSED(id, id.ordinal() == "0");
+    return m_inspectorStyle;
+}
+
 CSSStyleDeclaration* InspectorStyleSheetForInlineStyle::inlineStyle() const
 {
     return m_element->style();
diff --git a/WebCore/inspector/InspectorStyleSheet.h b/WebCore/inspector/InspectorStyleSheet.h
index 38ab777..06c4093 100644
--- a/WebCore/inspector/InspectorStyleSheet.h
+++ b/WebCore/inspector/InspectorStyleSheet.h
@@ -26,16 +26,14 @@
 #define InspectorStyleSheet_h
 
 #include "CSSPropertySourceData.h"
-#include "Document.h"
 #include "InspectorValues.h"
 #include "PlatformString.h"
 
 #include <wtf/HashMap.h>
 #include <wtf/HashSet.h>
-#include <wtf/OwnPtr.h>
 #include <wtf/PassRefPtr.h>
 #include <wtf/RefPtr.h>
-#include <wtf/UnusedParam.h>
+#include <wtf/Vector.h>
 
 class ParsedStyleSheet;
 
@@ -43,13 +41,102 @@ namespace WebCore {
 
 class CSSRuleList;
 class CSSStyleDeclaration;
+class CSSStyleSheet;
+class Document;
 class Element;
+class InspectorStyleSheet;
 class Node;
 
 #if ENABLE(INSPECTOR)
 
+class InspectorCSSId {
+public:
+    static InspectorCSSId createFromParts(const String& styleSheetId, const String& ordinal) { return InspectorCSSId(styleSheetId + ":" + ordinal); }
+
+    InspectorCSSId() { }
+    explicit InspectorCSSId(const String& id)
+    {
+        id.split(':', m_idParts);
+        ASSERT(m_idParts.size() == 2);
+    }
+
+    const String& styleSheetId() const { ASSERT(m_idParts.size() == 2); return m_idParts.at(0); }
+    const String& ordinal() const { ASSERT(m_idParts.size() == 2); return m_idParts.at(1); }
+    bool isEmpty() const { return m_idParts.isEmpty(); }
+    String asString() const
+    {
+        if (isEmpty())
+            return String();
+
+        return m_idParts.at(0) + ":" + m_idParts.at(1);
+    }
+
+private:
+    Vector<String> m_idParts;
+};
+
+struct InspectorStyleProperty {
+    InspectorStyleProperty()
+    {
+    }
+
+    InspectorStyleProperty(CSSPropertySourceData sourceData, bool hasSource, bool disabled)
+        : sourceData(sourceData)
+        , hasSource(hasSource)
+        , disabled(disabled)
+    {
+    }
+
+    CSSPropertySourceData sourceData;
+    bool hasSource;
+    bool disabled;
+    String rawText;
+};
+
+class InspectorStyle : public RefCounted<InspectorStyle> {
+public:
+    static PassRefPtr<InspectorStyle> create(const InspectorCSSId& styleId, CSSStyleDeclaration* style, InspectorStyleSheet* parentStyleSheet)
+    {
+        return adoptRef(new InspectorStyle(styleId, style, parentStyleSheet));
+    }
+
+    InspectorStyle(const InspectorCSSId& styleId, CSSStyleDeclaration* style, InspectorStyleSheet* parentStyleSheet)
+        : m_styleId(styleId)
+        , m_style(style)
+        , m_parentStyleSheet(parentStyleSheet)
+    {
+        ASSERT(style);
+    }
+
+    CSSStyleDeclaration* cssStyle() const { return m_style; }
+    PassRefPtr<InspectorObject> buildObjectForStyle() const;
+    bool hasDisabledProperties() const { return !m_disabledProperties.isEmpty(); }
+    bool setPropertyText(unsigned index, const String& text, bool overwrite);
+    bool toggleProperty(unsigned index, bool disable);
+
+private:
+    static unsigned disabledIndexByOrdinal(unsigned ordinal, bool canUseSubsequent, Vector<InspectorStyleProperty>& allProperties);
+
+    bool styleText(String* result);
+    bool disableProperty(unsigned indexToDisable, Vector<InspectorStyleProperty>& allProperties);
+    bool enableProperty(unsigned indexToEnable, Vector<InspectorStyleProperty>& allProperties);
+    bool populateAllProperties(Vector<InspectorStyleProperty>* result) const;
+    void populateObjectWithStyleProperties(InspectorObject* result) const;
+    void shiftDisabledProperties(unsigned fromIndex, long offset);
+    bool replacePropertyInStyleText(const InspectorStyleProperty& property, const String& newText);
+    String shorthandValue(const String& shorthandProperty) const;
+    String shorthandPriority(const String& shorthandProperty) const;
+    Vector<String> longhandProperties(const String& shorthandProperty) const;
+
+    InspectorCSSId m_styleId;
+    CSSStyleDeclaration* m_style;
+    InspectorStyleSheet* m_parentStyleSheet;
+    Vector<InspectorStyleProperty> m_disabledProperties;
+};
+
 class InspectorStyleSheet : public RefCounted<InspectorStyleSheet> {
 public:
+    typedef HashMap<CSSStyleDeclaration*, RefPtr<InspectorStyle> > InspectorStyleMap;
     static PassRefPtr<InspectorStyleSheet> create(const String& id, CSSStyleSheet* pageStyleSheet, const String& origin, const String& documentURL)
     {
         return adoptRef(new InspectorStyleSheet(id, pageStyleSheet, origin, documentURL));
@@ -61,46 +148,55 @@ public:
     const String& id() const { return m_id; }
     CSSStyleSheet* pageStyleSheet() const { return m_pageStyleSheet; }
     bool setText(const String&);
-    bool setRuleSelector(const String& ruleId, const String& selector);
+    bool setRuleSelector(const InspectorCSSId&, const String& selector);
     CSSStyleRule* addRule(const String& selector);
-    CSSStyleRule* ruleForId(const String&) const;
+    CSSStyleRule* ruleForId(const InspectorCSSId&) const;
     PassRefPtr<InspectorObject> buildObjectForStyleSheet();
     PassRefPtr<InspectorObject> buildObjectForRule(CSSStyleRule*);
     PassRefPtr<InspectorObject> buildObjectForStyle(CSSStyleDeclaration*);
-    virtual CSSStyleDeclaration* styleForId(const String&) const;
-    virtual bool setStyleText(const String& styleId, const String& text);
+    bool setPropertyText(const InspectorCSSId&, unsigned propertyIndex, const String& text, bool overwrite);
+    bool toggleProperty(const InspectorCSSId&, unsigned propertyIndex, bool disable);
+
+    virtual CSSStyleDeclaration* styleForId(const InspectorCSSId&) const;
 
 protected:
     bool canBind() const { return m_origin != "userAgent" && m_origin != "user"; }
-    String fullRuleOrStyleId(CSSStyleDeclaration* style) const { return id() + ":" + ruleOrStyleId(style); }
-    String ruleOrStyleId(CSSStyleDeclaration* style) const { unsigned index = ruleIndexByStyle(style); return index == UINT_MAX ? "" : String::number(index); }
+    InspectorCSSId ruleOrStyleId(CSSStyleDeclaration* style) const;
     virtual Document* ownerDocument() const;
     virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const;
     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const;
     virtual bool ensureParsedDataReady();
+    virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
+    virtual void rememberInspectorStyle(RefPtr<InspectorStyle> inspectorStyle);
+    virtual void forgetInspectorStyle(CSSStyleDeclaration* style);
+
+    // Also accessed by friend class InspectorStyle.
+    virtual bool setStyleText(CSSStyleDeclaration*, const String&);
 
 private:
     bool text(String* result) const;
     bool ensureText() const;
     bool ensureSourceData(Node* ownerNode);
-    void innerSetStyleSheetText(const String& newText);
-    bool innerSetStyleText(CSSStyleDeclaration*, const String&);
     bool styleSheetTextWithChangedStyle(CSSStyleDeclaration*, const String& newStyleText, String* result);
     CSSStyleRule* findPageRuleWithStyle(CSSStyleDeclaration*);
-    String fullRuleId(CSSStyleRule* rule) const;
-    String fullStyleId(CSSStyleDeclaration* style) const { return fullRuleOrStyleId(style); }
+    InspectorCSSId ruleId(CSSStyleRule* rule) const;
+    InspectorCSSId styleId(CSSStyleDeclaration* style) const { return ruleOrStyleId(style); }
     void revalidateStyle(CSSStyleDeclaration*);
-    bool styleSheetText(String* result) const;
+    bool originalStyleSheetText(String* result) const;
     bool resourceStyleSheetText(String* result) const;
     bool inlineStyleSheetText(String* result) const;
     PassRefPtr<InspectorArray> buildArrayForRuleList(CSSRuleList*);
 
+
     String m_id;
     CSSStyleSheet* m_pageStyleSheet;
     String m_origin;
     String m_documentURL;
     bool m_isRevalidating;
     ParsedStyleSheet* m_parsedStyleSheet;
+    InspectorStyleMap m_inspectorStyles;
+
+    friend class InspectorStyle;
 };
 
 class InspectorStyleSheetForInlineStyle : public InspectorStyleSheet {
@@ -111,14 +207,19 @@ public:
     }
 
     InspectorStyleSheetForInlineStyle(const String& id, Element* element, const String& origin);
-    virtual CSSStyleDeclaration* styleForId(const String& id) const { ASSERT(id == "0"); UNUSED_PARAM(id); return inlineStyle(); }
-    virtual bool setStyleText(const String& styleId, const String& text);
+    virtual CSSStyleDeclaration* styleForId(const InspectorCSSId& id) const { ASSERT_UNUSED(id, id.ordinal() == "0"); return inlineStyle(); }
 
 protected:
     virtual Document* ownerDocument() const;
-    virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT(style == inlineStyle()); UNUSED_PARAM(style); return m_ruleSourceData; }
+    virtual RefPtr<CSSRuleSourceData> ruleSourceDataFor(CSSStyleDeclaration* style) const { ASSERT_UNUSED(style, style == inlineStyle()); return m_ruleSourceData; }
     virtual unsigned ruleIndexByStyle(CSSStyleDeclaration*) const { return 0; }
     virtual bool ensureParsedDataReady();
+    virtual PassRefPtr<InspectorStyle> inspectorStyleForId(const InspectorCSSId&);
+    virtual void rememberInspectorStyle(RefPtr<InspectorStyle>) { }
+    virtual void forgetInspectorStyle(CSSStyleDeclaration*) { }
+
+    // Also accessed by friend class InspectorStyle.
+    virtual bool setStyleText(CSSStyleDeclaration*, const String&);
 
 private:
     CSSStyleDeclaration* inlineStyle() const;
@@ -126,6 +227,7 @@ private:
 
     Element* m_element;
     RefPtr<CSSRuleSourceData> m_ruleSourceData;
+    RefPtr<InspectorStyle> m_inspectorStyle;
 };
 
 #endif

-- 
WebKit Debian packaging



More information about the Pkg-webkit-commits mailing list