OSDN Git Service

Merge WebKit at r84325: Initial merge by git.
[android-x86/external-webkit.git] / Source / WebCore / inspector / InspectorCSSAgent.cpp
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)