Home | History | Annotate | Download | only in inspector
      1 /*
      2  * Copyright (C) 2010, Google Inc. All rights reserved.
      3  *
      4  * Redistribution and use in source and binary forms, with or without
      5  * modification, are permitted provided that the following conditions
      6  * are met:
      7  * 1.  Redistributions of source code must retain the above copyright
      8  *     notice, this list of conditions and the following disclaimer.
      9  * 2.  Redistributions in binary form must reproduce the above copyright
     10  *     notice, this list of conditions and the following disclaimer in the
     11  *     documentation and/or other materials provided with the distribution.
     12  *
     13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
     14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
     17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
     18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
     19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
     20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
     22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     23  */
     24 
     25 #include "config.h"
     26 #include "InspectorCSSAgent.h"
     27 
     28 #if ENABLE(INSPECTOR)
     29 
     30 #include "CSSComputedStyleDeclaration.h"
     31 #include "CSSMutableStyleDeclaration.h"
     32 #include "CSSPropertyNames.h"
     33 #include "CSSPropertySourceData.h"
     34 #include "CSSRule.h"
     35 #include "CSSRuleList.h"
     36 #include "CSSStyleRule.h"
     37 #include "CSSStyleSelector.h"
     38 #include "CSSStyleSheet.h"
     39 #include "DOMWindow.h"
     40 #include "HTMLHeadElement.h"
     41 #include "InspectorDOMAgent.h"
     42 #include "InspectorValues.h"
     43 #include "InstrumentingAgents.h"
     44 #include "Node.h"
     45 #include "NodeList.h"
     46 #include "StyleSheetList.h"
     47 
     48 #include <wtf/HashSet.h>
     49 #include <wtf/Vector.h>
     50 #include <wtf/text/CString.h>
     51 
     52 // Currently implemented model:
     53 //
     54 // cssProperty = {
     55 //    name          : <string>,
     56 //    value         : <string>,
     57 //    priority      : <string>, // "" for non-parsedOk properties
     58 //    implicit      : <boolean>,
     59 //    parsedOk      : <boolean>, // whether property is understood by WebCore
     60 //    status        : <string>, // "disabled" | "active" | "inactive" | "style"
     61 //    shorthandName : <string>,
     62 //    startOffset   : <number>, // Optional - property text start offset in enclosing style declaration. Absent for computed styles and such.
     63 //    endOffset     : <number>, // Optional - property text end offset in enclosing style declaration. Absent for computed styles and such.
     64 // }
     65 //
     66 // name + value + priority : present when the property is enabled
     67 // text                    : present when the property is disabled
     68 //
     69 // For disabled properties, startOffset === endOffset === insertion point for the property.
     70 //
     71 // status:
     72 // "disabled" == property disabled by user
     73 // "active" == property participates in the computed style calculation
     74 // "inactive" == property does no participate in the computed style calculation (i.e. overridden by a subsequent property with the same name)
     75 // "style" == property is active and originates from the WebCore CSSStyleDeclaration rather than CSS source code (e.g. implicit longhand properties)
     76 //
     77 // cssStyle = {
     78 //    styleId            : <string>, // Optional
     79 //    cssProperties      : [
     80 //                          #cssProperty,
     81 //                          ...
     82 //                          #cssProperty
     83 //                         ],
     84 //    shorthandEntries   : [
     85 //                          #shorthandEntry,
     86 //                          ...
     87 //                          #shorthandEntry
     88 //                         ],
     89 //    cssText            : <string>, // Optional - declaration text
     90 //    properties         : {
     91 //                          width,
     92 //                          height,
     93 //                          startOffset, // Optional - for source-based styles only
     94 //                          endOffset, // Optional - for source-based styles only
     95 //                         }
     96 // }
     97 //
     98 // shorthandEntry = {
     99 //    name: <string>,
    100 //    value: <string>
    101 // }
    102 //
    103 // cssRule = {
    104 //    ruleId       : <string>, // Optional
    105 //    selectorText : <string>,
    106 //    sourceURL    : <string>,
    107 //    sourceLine   : <string>,
    108 //    origin       : <string>, // "" || "user-agent" || "user" || "inspector"
    109 //    style        : #cssStyle,
    110 //    selectorRange: { start: <number>, end: <number> } // Optional - for source-based rules only
    111 // }
    112 //
    113 // cssStyleSheetInfo = {
    114 //    styleSheetId : <number>
    115 //    sourceURL    : <string>
    116 //    title        : <string>
    117 //    disabled     : <boolean>
    118 // }
    119 //
    120 // cssStyleSheet = {
    121 //    styleSheetId : <number>
    122 //    rules        : [
    123 //                       #cssRule,
    124 //                       ...
    125 //                       #cssRule
    126 //                   ]
    127 //    text         : <string> // Optional - whenever the text is available for a text-based stylesheet
    128 // }
    129 
    130 namespace WebCore {
    131 
    132 // static
    133 CSSStyleSheet* InspectorCSSAgent::parentStyleSheet(StyleBase* styleBase)
    134 {
    135     if (!styleBase)
    136         return 0;
    137 
    138     StyleSheet* styleSheet = styleBase->stylesheet();
    139     if (styleSheet && styleSheet->isCSSStyleSheet())
    140         return static_cast<CSSStyleSheet*>(styleSheet);
    141 
    142     return 0;
    143 }
    144 
    145 // static
    146 CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(StyleBase* styleBase)
    147 {
    148     if (!styleBase->isStyleRule())
    149         return 0;
    150     CSSRule* rule = static_cast<CSSRule*>(styleBase);
    151     if (rule->type() != CSSRule::STYLE_RULE)
    152         return 0;
    153     return static_cast<CSSStyleRule*>(rule);
    154 }
    155 
    156 InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorDOMAgent* domAgent)
    157     : m_instrumentingAgents(instrumentingAgents)
    158     , m_domAgent(domAgent)
    159     , m_lastStyleSheetId(1)
    160     , m_lastRuleId(1)
    161     , m_lastStyleId(1)
    162 {
    163     m_domAgent->setDOMListener(this);
    164     m_instrumentingAgents->setInspectorCSSAgent(this);
    165 }
    166 
    167 InspectorCSSAgent::~InspectorCSSAgent()
    168 {
    169     m_instrumentingAgents->setInspectorCSSAgent(0);
    170     // DOM agent should be destroyed after CSS agent.
    171     m_domAgent->setDOMListener(0);
    172     m_domAgent = 0;
    173     reset();
    174 }
    175 
    176 void InspectorCSSAgent::reset()
    177 {
    178     m_idToInspectorStyleSheet.clear();
    179     m_cssStyleSheetToInspectorStyleSheet.clear();
    180     m_nodeToInspectorStyleSheet.clear();
    181     m_documentToInspectorStyleSheet.clear();
    182 }
    183 
    184 void InspectorCSSAgent::getStylesForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* result)
    185 {
    186     Element* element = elementForId(errorString, nodeId);
    187     if (!element)
    188         return;
    189 
    190     RefPtr<InspectorObject> resultObject = InspectorObject::create();
    191 
    192     InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
    193     if (styleSheet)
    194         resultObject->setObject("inlineStyle", styleSheet->buildObjectForStyle(element->style()));
    195 
    196     RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true); // Support the viewing of :visited information in computed style.
    197     RefPtr<InspectorStyle> computedInspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
    198     resultObject->setObject("computedStyle", computedInspectorStyle->buildObjectForStyle());
    199 
    200     CSSStyleSelector* selector = element->ownerDocument()->styleSelector();
    201     RefPtr<CSSRuleList> matchedRules = selector->styleRulesForElement(element, false, true);
    202     resultObject->setArray("matchedCSSRules", buildArrayForRuleList(matchedRules.get()));
    203 
    204     resultObject->setArray("styleAttributes", buildArrayForAttributeStyles(element));
    205 
    206     RefPtr<InspectorArray> pseudoElements = InspectorArray::create();
    207     for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
    208         RefPtr<CSSRuleList> matchedRules = selector->pseudoStyleRulesForElement(element, pseudoId, false, true);
    209         if (matchedRules && matchedRules->length()) {
    210             RefPtr<InspectorObject> pseudoStyles = InspectorObject::create();
    211             pseudoStyles->setNumber("pseudoId", static_cast<int>(pseudoId));
    212             pseudoStyles->setArray("rules", buildArrayForRuleList(matchedRules.get()));
    213             pseudoElements->pushObject(pseudoStyles.release());
    214         }
    215     }
    216     resultObject->setArray("pseudoElements", pseudoElements.release());
    217 
    218     RefPtr<InspectorArray> inheritedStyles = InspectorArray::create();
    219     Element* parentElement = element->parentElement();
    220     while (parentElement) {
    221         RefPtr<InspectorObject> parentStyle = InspectorObject::create();
    222         if (parentElement->style() && parentElement->style()->length()) {
    223             InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
    224             if (styleSheet)
    225                 parentStyle->setObject("inlineStyle", styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
    226         }
    227 
    228         CSSStyleSelector* parentSelector = parentElement->ownerDocument()->styleSelector();
    229         RefPtr<CSSRuleList> parentMatchedRules = parentSelector->styleRulesForElement(parentElement, false, true);
    230         parentStyle->setArray("matchedCSSRules", buildArrayForRuleList(parentMatchedRules.get()));
    231         inheritedStyles->pushObject(parentStyle.release());
    232         parentElement = parentElement->parentElement();
    233     }
    234     resultObject->setArray("inherited", inheritedStyles.release());
    235 
    236     *result = resultObject.release();
    237 }
    238 
    239 void InspectorCSSAgent::getInlineStyleForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* style)
    240 {
    241     Element* element = elementForId(errorString, nodeId);
    242     if (!element)
    243         return;
    244 
    245     InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
    246     if (!styleSheet)
    247         return;
    248 
    249     *style = styleSheet->buildObjectForStyle(element->style());
    250 }
    251 
    252 void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<InspectorObject>* style)
    253 {
    254     Element* element = elementForId(errorString, nodeId);
    255     if (!element)
    256         return;
    257 
    258     RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = computedStyle(element, true);
    259     RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
    260     *style = inspectorStyle->buildObjectForStyle();
    261 }
    262 
    263 void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<InspectorArray>* styleInfos)
    264 {
    265     Vector<Document*> documents = m_domAgent->documents();
    266     for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
    267         StyleSheetList* list = (*it)->styleSheets();
    268         for (unsigned i = 0; i < list->length(); ++i) {
    269             StyleSheet* styleSheet = list->item(i);
    270             if (styleSheet->isCSSStyleSheet()) {
    271                 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
    272                 (*styleInfos)->pushObject(inspectorStyleSheet->buildObjectForStyleSheetInfo());
    273             }
    274         }
    275     }
    276 }
    277 
    278 void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<InspectorObject>* styleSheetObject)
    279 {
    280     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
    281     if (!inspectorStyleSheet)
    282         return;
    283 
    284     *styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
    285 }
    286 
    287 void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
    288 {
    289     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
    290     if (!inspectorStyleSheet)
    291         return;
    292 
    293     inspectorStyleSheet->text(result);
    294 }
    295 
    296 void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
    297 {
    298     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
    299     if (!inspectorStyleSheet)
    300         return;
    301 
    302     if (inspectorStyleSheet->setText(text))
    303         inspectorStyleSheet->reparseStyleSheet(text);
    304     else
    305         *errorString = "Internal error setting style sheet text";
    306 }
    307 
    308 void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<InspectorObject>* result)
    309 {
    310     InspectorCSSId compoundId(fullStyleId);
    311     ASSERT(!compoundId.isEmpty());
    312 
    313     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
    314     if (!inspectorStyleSheet)
    315         return;
    316 
    317     bool success = inspectorStyleSheet->setPropertyText(errorString, compoundId, propertyIndex, text, overwrite);
    318     if (success)
    319         *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
    320 }
    321 
    322 void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<InspectorObject>* result)
    323 {
    324     InspectorCSSId compoundId(fullStyleId);
    325     ASSERT(!compoundId.isEmpty());
    326 
    327     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
    328     if (!inspectorStyleSheet)
    329         return;
    330 
    331     bool success = inspectorStyleSheet->toggleProperty(errorString, compoundId, propertyIndex, disable);
    332     if (success)
    333         *result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
    334 }
    335 
    336 void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<InspectorObject>* result)
    337 {
    338     InspectorCSSId compoundId(fullRuleId);
    339     ASSERT(!compoundId.isEmpty());
    340 
    341     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
    342     if (!inspectorStyleSheet)
    343         return;
    344 
    345     bool success = inspectorStyleSheet->setRuleSelector(compoundId, selector);
    346     if (!success)
    347         return;
    348 
    349     *result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
    350 }
    351 
    352 void InspectorCSSAgent::addRule(ErrorString*, const int contextNodeId, const String& selector, RefPtr<InspectorObject>* result)
    353 {
    354     Node* node = m_domAgent->nodeForId(contextNodeId);
    355     if (!node)
    356         return;
    357 
    358     InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
    359     if (!inspectorStyleSheet)
    360         return;
    361     CSSStyleRule* newRule = inspectorStyleSheet->addRule(selector);
    362     if (!newRule)
    363         return;
    364 
    365     *result = inspectorStyleSheet->buildObjectForRule(newRule);
    366 }
    367 
    368 void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<InspectorArray>* cssProperties)
    369 {
    370     RefPtr<InspectorArray> properties = InspectorArray::create();
    371     for (int i = 0; i < numCSSProperties; ++i)
    372         properties->pushString(propertyNameStrings[i]);
    373 
    374     *cssProperties = properties.release();
    375 }
    376 
    377 // static
    378 Element* InspectorCSSAgent::inlineStyleElement(CSSStyleDeclaration* style)
    379 {
    380     if (!style || !style->isMutableStyleDeclaration())
    381         return 0;
    382     Node* node = static_cast<CSSMutableStyleDeclaration*>(style)->node();
    383     if (!node || !node->isStyledElement() || static_cast<StyledElement*>(node)->getInlineStyleDecl() != style)
    384         return 0;
    385     return static_cast<Element*>(node);
    386 }
    387 
    388 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
    389 {
    390     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
    391     if (it == m_nodeToInspectorStyleSheet.end()) {
    392         CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
    393         if (!style)
    394             return 0;
    395 
    396         String newStyleSheetId = String::number(m_lastStyleSheetId++);
    397         RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(newStyleSheetId, element, "");
    398         m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
    399         m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
    400         return inspectorStyleSheet.get();
    401     }
    402 
    403     return it->second.get();
    404 }
    405 
    406 Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
    407 {
    408     Node* node = m_domAgent->nodeForId(nodeId);
    409     if (!node) {
    410         *errorString = "No node with given id found";
    411         return 0;
    412     }
    413     if (node->nodeType() != Node::ELEMENT_NODE) {
    414         *errorString = "Not an element node";
    415         return 0;
    416     }
    417     return static_cast<Element*>(node);
    418 }
    419 
    420 InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
    421 {
    422     RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
    423     if (!inspectorStyleSheet) {
    424         String id = String::number(m_lastStyleSheetId++);
    425         inspectorStyleSheet = InspectorStyleSheet::create(id, styleSheet, detectOrigin(styleSheet, styleSheet->document()), m_domAgent->documentURLString(styleSheet->document()));
    426         m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
    427         m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
    428     }
    429     return inspectorStyleSheet.get();
    430 }
    431 
    432 InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
    433 {
    434     if (!document) {
    435         ASSERT(!createIfAbsent);
    436         return 0;
    437     }
    438 
    439     RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
    440     if (inspectorStyleSheet || !createIfAbsent)
    441         return inspectorStyleSheet.get();
    442 
    443     ExceptionCode ec = 0;
    444     RefPtr<Element> styleElement = document->createElement("style", ec);
    445     if (!ec)
    446         styleElement->setAttribute("type", "text/css", ec);
    447     if (!ec) {
    448         ContainerNode* targetNode;
    449         // HEAD is absent in ImageDocuments, for example.
    450         if (document->head())
    451             targetNode = document->head();
    452         else if (document->body())
    453             targetNode = document->body();
    454         else
    455             return 0;
    456         targetNode->appendChild(styleElement, ec);
    457     }
    458     if (ec)
    459         return 0;
    460     StyleSheetList* styleSheets = document->styleSheets();
    461     StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1);
    462     if (!styleSheet->isCSSStyleSheet())
    463         return 0;
    464     CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet);
    465     String id = String::number(m_lastStyleSheetId++);
    466     inspectorStyleSheet = InspectorStyleSheet::create(id, cssStyleSheet, "inspector", m_domAgent->documentURLString(document));
    467     m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
    468     m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet);
    469     m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet);
    470     return inspectorStyleSheet.get();
    471 }
    472 
    473 InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
    474 {
    475     IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
    476     if (it == m_idToInspectorStyleSheet.end()) {
    477         *errorString = "No style sheet with given id found";
    478         return 0;
    479     }
    480     return it->second.get();
    481 }
    482 
    483 String InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
    484 {
    485     DEFINE_STATIC_LOCAL(String, userAgent, ("user-agent"));
    486     DEFINE_STATIC_LOCAL(String, user, ("user"));
    487     DEFINE_STATIC_LOCAL(String, inspector, ("inspector"));
    488 
    489     String origin("");
    490     if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
    491         origin = userAgent;
    492     else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
    493         origin = user;
    494     else {
    495         InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
    496         if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
    497             origin = inspector;
    498     }
    499     return origin;
    500 }
    501 
    502 PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList)
    503 {
    504     RefPtr<InspectorArray> result = InspectorArray::create();
    505     if (!ruleList)
    506         return result.release();
    507 
    508     for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
    509         CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
    510         if (!rule)
    511             continue;
    512 
    513         InspectorStyleSheet* styleSheet = bindStyleSheet(parentStyleSheet(rule));
    514         if (styleSheet)
    515             result->pushObject(styleSheet->buildObjectForRule(rule));
    516     }
    517     return result.release();
    518 }
    519 
    520 PassRefPtr<InspectorArray> InspectorCSSAgent::buildArrayForAttributeStyles(Element* element)
    521 {
    522     RefPtr<InspectorArray> attrStyles = InspectorArray::create();
    523     NamedNodeMap* attributes = element->attributes();
    524     for (unsigned i = 0; attributes && i < attributes->length(); ++i) {
    525         Attribute* attribute = attributes->attributeItem(i);
    526         if (attribute->style()) {
    527             RefPtr<InspectorObject> attrStyleObject = InspectorObject::create();
    528             String attributeName = attribute->localName();
    529             RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), attribute->style(), 0);
    530             attrStyleObject->setString("name", attributeName.utf8().data());
    531             attrStyleObject->setObject("style", inspectorStyle->buildObjectForStyle());
    532             attrStyles->pushObject(attrStyleObject.release());
    533         }
    534     }
    535 
    536     return attrStyles.release();
    537 }
    538 
    539 void InspectorCSSAgent::didRemoveDocument(Document* document)
    540 {
    541     if (document)
    542         m_documentToInspectorStyleSheet.remove(document);
    543 }
    544 
    545 void InspectorCSSAgent::didRemoveDOMNode(Node* node)
    546 {
    547     if (!node)
    548         return;
    549 
    550     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
    551     if (it == m_nodeToInspectorStyleSheet.end())
    552         return;
    553 
    554     m_idToInspectorStyleSheet.remove(it->second->id());
    555     m_nodeToInspectorStyleSheet.remove(node);
    556 }
    557 
    558 void InspectorCSSAgent::didModifyDOMAttr(Element* element)
    559 {
    560     if (!element)
    561         return;
    562 
    563     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
    564     if (it == m_nodeToInspectorStyleSheet.end())
    565         return;
    566 
    567     it->second->didModifyElementAttribute();
    568 }
    569 
    570 } // namespace WebCore
    571 
    572 #endif // ENABLE(INSPECTOR)
    573