Replace more instances of += with StringBuilder
[WebKit-https.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
27 #if ENABLE(INSPECTOR)
28
29 #include "InspectorCSSAgent.h"
30
31 #include "CSSComputedStyleDeclaration.h"
32 #include "CSSImportRule.h"
33 #include "CSSPropertyNames.h"
34 #include "CSSPropertySourceData.h"
35 #include "CSSRule.h"
36 #include "CSSRuleList.h"
37 #include "CSSStyleRule.h"
38 #include "CSSStyleSheet.h"
39 #include "ContentSecurityPolicy.h"
40 #include "DOMWindow.h"
41 #include "HTMLHeadElement.h"
42 #include "InspectorDOMAgent.h"
43 #include "InspectorHistory.h"
44 #include "InspectorState.h"
45 #include "InspectorTypeBuilder.h"
46 #include "InspectorValues.h"
47 #include "InstrumentingAgents.h"
48 #include "NamedFlowCollection.h"
49 #include "Node.h"
50 #include "NodeList.h"
51 #include "RenderRegion.h"
52 #include "StylePropertySet.h"
53 #include "StylePropertyShorthand.h"
54 #include "StyleResolver.h"
55 #include "StyleRule.h"
56 #include "StyleSheetList.h"
57 #include "WebKitNamedFlow.h"
58
59 #include <wtf/CurrentTime.h>
60 #include <wtf/HashSet.h>
61 #include <wtf/Vector.h>
62 #include <wtf/text/CString.h>
63 #include <wtf/text/StringConcatenate.h>
64
65 namespace CSSAgentState {
66 static const char cssAgentEnabled[] = "cssAgentEnabled";
67 static const char isSelectorProfiling[] = "isSelectorProfiling";
68 }
69
70 namespace WebCore {
71
72 enum ForcePseudoClassFlags {
73     PseudoNone = 0,
74     PseudoHover = 1 << 0,
75     PseudoFocus = 1 << 1,
76     PseudoActive = 1 << 2,
77     PseudoVisited = 1 << 3
78 };
79
80 struct RuleMatchData {
81     String selector;
82     String url;
83     unsigned lineNumber;
84     double startTime;
85 };
86
87 struct RuleMatchingStats {
88     RuleMatchingStats()
89         : lineNumber(0), totalTime(0.0), hits(0), matches(0)
90     {
91     }
92     RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits, unsigned matches)
93         : selector(data.selector), url(data.url), lineNumber(data.lineNumber), totalTime(totalTime), hits(hits), matches(matches)
94     {
95     }
96
97     String selector;
98     String url;
99     unsigned lineNumber;
100     double totalTime;
101     unsigned hits;
102     unsigned matches;
103 };
104
105 class SelectorProfile {
106 public:
107     SelectorProfile()
108         : m_totalMatchingTimeMs(0.0)
109     {
110     }
111     virtual ~SelectorProfile()
112     {
113     }
114
115     double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; }
116
117     String makeKey();
118     void startSelector(const CSSStyleRule*);
119     void commitSelector(bool);
120     void commitSelectorTime();
121     PassRefPtr<TypeBuilder::CSS::SelectorProfile> toInspectorObject() const;
122
123 private:
124
125     // Key is "selector?url:line".
126     typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap;
127
128     double m_totalMatchingTimeMs;
129     RuleMatchingStatsMap m_ruleMatchingStats;
130     RuleMatchData m_currentMatchData;
131 };
132
133
134 static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray)
135 {
136     DEFINE_STATIC_LOCAL(String, active, (ASCIILiteral("active")));
137     DEFINE_STATIC_LOCAL(String, hover, (ASCIILiteral("hover")));
138     DEFINE_STATIC_LOCAL(String, focus, (ASCIILiteral("focus")));
139     DEFINE_STATIC_LOCAL(String, visited, (ASCIILiteral("visited")));
140     if (!pseudoClassArray || !pseudoClassArray->length())
141         return PseudoNone;
142
143     unsigned result = PseudoNone;
144     for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
145         RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i);
146         String pseudoClass;
147         bool success = pseudoClassValue->asString(&pseudoClass);
148         if (!success)
149             continue;
150         if (pseudoClass == active)
151             result |= PseudoActive;
152         else if (pseudoClass == hover)
153             result |= PseudoHover;
154         else if (pseudoClass == focus)
155             result |= PseudoFocus;
156         else if (pseudoClass == visited)
157             result |= PseudoVisited;
158     }
159
160     return result;
161 }
162
163 inline String SelectorProfile::makeKey()
164 {
165     return makeString(m_currentMatchData.selector, "?", m_currentMatchData.url, ":", String::number(m_currentMatchData.lineNumber));
166 }
167
168 inline void SelectorProfile::startSelector(const CSSStyleRule* rule)
169 {
170     m_currentMatchData.selector = rule->selectorText();
171     CSSStyleSheet* styleSheet = rule->parentStyleSheet();
172     String url = emptyString();
173     if (styleSheet) {
174         url = InspectorStyleSheet::styleSheetURL(styleSheet);
175         if (url.isEmpty())
176             url = InspectorDOMAgent::documentURLString(styleSheet->ownerDocument());
177     }
178     m_currentMatchData.url = url;
179     m_currentMatchData.lineNumber = rule->styleRule()->sourceLine();
180     m_currentMatchData.startTime = WTF::currentTimeMS();
181 }
182
183 inline void SelectorProfile::commitSelector(bool matched)
184 {
185     double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
186     m_totalMatchingTimeMs += matchTimeMs;
187
188     RuleMatchingStatsMap::AddResult result = m_ruleMatchingStats.add(makeKey(), RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0));
189     if (!result.isNewEntry) {
190         result.iterator->second.totalTime += matchTimeMs;
191         result.iterator->second.hits += 1;
192         if (matched)
193             result.iterator->second.matches += 1;
194     }
195 }
196
197 inline void SelectorProfile::commitSelectorTime()
198 {
199     double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
200     m_totalMatchingTimeMs += processingTimeMs;
201
202     RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey());
203     if (it == m_ruleMatchingStats.end())
204         return;
205
206     it->second.totalTime += processingTimeMs;
207 }
208
209 PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject() const
210 {
211     RefPtr<TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry> > selectorProfileData = TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry>::create();
212     for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin(); it != m_ruleMatchingStats.end(); ++it) {
213         RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS::SelectorProfileEntry::create()
214             .setSelector(it->second.selector)
215             .setUrl(it->second.url)
216             .setLineNumber(it->second.lineNumber)
217             .setTime(it->second.totalTime)
218             .setHitCount(it->second.hits)
219             .setMatchCount(it->second.matches);
220         selectorProfileData->addItem(entry.release());
221     }
222
223     RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::SelectorProfile::create()
224         .setTotalTime(totalMatchingTimeMs())
225         .setData(selectorProfileData);
226     return result.release();
227 }
228
229 class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
230     WTF_MAKE_NONCOPYABLE(StyleSheetAction);
231 public:
232     StyleSheetAction(const String& name, InspectorStyleSheet* styleSheet)
233         : InspectorHistory::Action(name)
234         , m_styleSheet(styleSheet)
235     {
236     }
237
238 protected:
239     RefPtr<InspectorStyleSheet> m_styleSheet;
240 };
241
242 class InspectorCSSAgent::SetStyleSheetTextAction : public InspectorCSSAgent::StyleSheetAction {
243     WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction);
244 public:
245     SetStyleSheetTextAction(InspectorStyleSheet* styleSheet, const String& text)
246         : InspectorCSSAgent::StyleSheetAction("SetStyleSheetText", styleSheet)
247         , m_text(text)
248     {
249     }
250
251     virtual bool perform(ExceptionCode& ec)
252     {
253         if (!m_styleSheet->getText(&m_oldText))
254             return false;
255         return redo(ec);
256     }
257
258     virtual bool undo(ExceptionCode&)
259     {
260         if (m_styleSheet->setText(m_oldText)) {
261             m_styleSheet->reparseStyleSheet(m_oldText);
262             return true;
263         }
264         return false;
265     }
266
267     virtual bool redo(ExceptionCode&)
268     {
269         if (m_styleSheet->setText(m_text)) {
270             m_styleSheet->reparseStyleSheet(m_text);
271             return true;
272         }
273         return false;
274     }
275
276     virtual String mergeId()
277     {
278         return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data());
279     }
280
281     virtual void merge(PassOwnPtr<Action> action)
282     {
283         ASSERT(action->mergeId() == mergeId());
284
285         SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action.get());
286         m_text = other->m_text;
287     }
288
289 private:
290     String m_text;
291     String m_oldText;
292 };
293
294 class InspectorCSSAgent::SetPropertyTextAction : public InspectorCSSAgent::StyleSheetAction {
295     WTF_MAKE_NONCOPYABLE(SetPropertyTextAction);
296 public:
297     SetPropertyTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, const String& text, bool overwrite)
298         : InspectorCSSAgent::StyleSheetAction("SetPropertyText", styleSheet)
299         , m_cssId(cssId)
300         , m_propertyIndex(propertyIndex)
301         , m_text(text)
302         , m_overwrite(overwrite)
303     {
304     }
305
306     virtual String toString()
307     {
308         return mergeId() + ": " + m_oldText + " -> " + m_text;
309     }
310
311     virtual bool perform(ExceptionCode& ec)
312     {
313         return redo(ec);
314     }
315
316     virtual bool undo(ExceptionCode& ec)
317     {
318         String placeholder;
319         return m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec);
320     }
321
322     virtual bool redo(ExceptionCode& ec)
323     {
324         String oldText;
325         bool result = m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec);
326         m_oldText = oldText.stripWhiteSpace();
327         // FIXME: remove this once the model handles this case.
328         if (!m_oldText.endsWith(';'))
329             m_oldText.append(';');
330         return result;
331     }
332
333     virtual String mergeId()
334     {
335         return String::format("SetPropertyText %s:%u:%s", m_styleSheet->id().utf8().data(), m_propertyIndex, m_overwrite ? "true" : "false");
336     }
337
338     virtual void merge(PassOwnPtr<Action> action)
339     {
340         ASSERT(action->mergeId() == mergeId());
341
342         SetPropertyTextAction* other = static_cast<SetPropertyTextAction*>(action.get());
343         m_text = other->m_text;
344     }
345
346 private:
347     InspectorCSSId m_cssId;
348     unsigned m_propertyIndex;
349     String m_text;
350     String m_oldText;
351     bool m_overwrite;
352 };
353
354 class InspectorCSSAgent::TogglePropertyAction : public InspectorCSSAgent::StyleSheetAction {
355     WTF_MAKE_NONCOPYABLE(TogglePropertyAction);
356 public:
357     TogglePropertyAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, bool disable)
358         : InspectorCSSAgent::StyleSheetAction("ToggleProperty", styleSheet)
359         , m_cssId(cssId)
360         , m_propertyIndex(propertyIndex)
361         , m_disable(disable)
362     {
363     }
364
365     virtual bool perform(ExceptionCode& ec)
366     {
367         return redo(ec);
368     }
369
370     virtual bool undo(ExceptionCode& ec)
371     {
372         return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec);
373     }
374
375     virtual bool redo(ExceptionCode& ec)
376     {
377         return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec);
378     }
379
380 private:
381     InspectorCSSId m_cssId;
382     unsigned m_propertyIndex;
383     bool m_disable;
384 };
385
386 class InspectorCSSAgent::SetRuleSelectorAction : public InspectorCSSAgent::StyleSheetAction {
387     WTF_MAKE_NONCOPYABLE(SetRuleSelectorAction);
388 public:
389     SetRuleSelectorAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& selector)
390         : InspectorCSSAgent::StyleSheetAction("SetRuleSelector", styleSheet)
391         , m_cssId(cssId)
392         , m_selector(selector)
393     {
394     }
395
396     virtual bool perform(ExceptionCode& ec)
397     {
398         m_oldSelector = m_styleSheet->ruleSelector(m_cssId, ec);
399         if (ec)
400             return false;
401         return redo(ec);
402     }
403
404     virtual bool undo(ExceptionCode& ec)
405     {
406         return m_styleSheet->setRuleSelector(m_cssId, m_oldSelector, ec);
407     }
408
409     virtual bool redo(ExceptionCode& ec)
410     {
411         return m_styleSheet->setRuleSelector(m_cssId, m_selector, ec);
412     }
413
414 private:
415     InspectorCSSId m_cssId;
416     String m_selector;
417     String m_oldSelector;
418 };
419
420 class InspectorCSSAgent::AddRuleAction : public InspectorCSSAgent::StyleSheetAction {
421     WTF_MAKE_NONCOPYABLE(AddRuleAction);
422 public:
423     AddRuleAction(InspectorStyleSheet* styleSheet, const String& selector)
424         : InspectorCSSAgent::StyleSheetAction("AddRule", styleSheet)
425         , m_selector(selector)
426     {
427     }
428
429     virtual bool perform(ExceptionCode& ec)
430     {
431         return redo(ec);
432     }
433
434     virtual bool undo(ExceptionCode& ec)
435     {
436         return m_styleSheet->deleteRule(m_newId, ec);
437     }
438
439     virtual bool redo(ExceptionCode& ec)
440     {
441         CSSStyleRule* cssStyleRule = m_styleSheet->addRule(m_selector, ec);
442         if (ec)
443             return false;
444         m_newId = m_styleSheet->ruleId(cssStyleRule);
445         return true;
446     }
447
448     InspectorCSSId newRuleId() { return m_newId; }
449
450 private:
451     InspectorCSSId m_newId;
452     String m_selector;
453     String m_oldSelector;
454 };
455
456 // static
457 CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
458 {
459     if (!rule->isStyleRule())
460         return 0;
461     return static_cast<CSSStyleRule*>(rule);
462 }
463
464 InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, InspectorDOMAgent* domAgent)
465     : InspectorBaseAgent<InspectorCSSAgent>("CSS", instrumentingAgents, state)
466     , m_frontend(0)
467     , m_domAgent(domAgent)
468     , m_lastStyleSheetId(1)
469 {
470     m_domAgent->setDOMListener(this);
471 }
472
473 InspectorCSSAgent::~InspectorCSSAgent()
474 {
475     ASSERT(!m_domAgent);
476     reset();
477 }
478
479 void InspectorCSSAgent::setFrontend(InspectorFrontend* frontend)
480 {
481     ASSERT(!m_frontend);
482     m_frontend = frontend->css();
483     m_instrumentingAgents->setInspectorCSSAgent(this);
484 }
485
486 void InspectorCSSAgent::clearFrontend()
487 {
488     ASSERT(m_frontend);
489     m_frontend = 0;
490     m_instrumentingAgents->setInspectorCSSAgent(0);
491     resetPseudoStates();
492     String errorString;
493     stopSelectorProfilerImpl(&errorString, false);
494 }
495
496 void InspectorCSSAgent::discardAgent()
497 {
498     m_domAgent->setDOMListener(0);
499     m_domAgent = 0;
500 }
501
502 void InspectorCSSAgent::restore()
503 {
504     if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) {
505         ErrorString error;
506         enable(&error);
507     }
508     if (m_state->getBoolean(CSSAgentState::isSelectorProfiling)) {
509         String errorString;
510         startSelectorProfiler(&errorString);
511     }
512 }
513
514 void InspectorCSSAgent::reset()
515 {
516     m_idToInspectorStyleSheet.clear();
517     m_cssStyleSheetToInspectorStyleSheet.clear();
518     m_nodeToInspectorStyleSheet.clear();
519     m_documentToInspectorStyleSheet.clear();
520     m_namedFlowCollectionsRequested.clear();
521     resetPseudoStates();
522 }
523
524 void InspectorCSSAgent::enable(ErrorString*)
525 {
526     m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
527 }
528
529 void InspectorCSSAgent::disable(ErrorString*)
530 {
531     m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
532 }
533
534 void InspectorCSSAgent::mediaQueryResultChanged()
535 {
536     if (m_frontend)
537         m_frontend->mediaQueryResultChanged();
538 }
539
540 void InspectorCSSAgent::didCreateNamedFlow(Document* document, const AtomicString& name)
541 {
542     int nodeId = m_domAgent->boundNodeId(document);
543     if (!nodeId || !m_namedFlowCollectionsRequested.contains(nodeId))
544         return;
545
546     m_frontend->namedFlowCreated(nodeId, name.string());
547 }
548
549 void InspectorCSSAgent::didRemoveNamedFlow(Document* document, const AtomicString& name)
550 {
551     int nodeId = m_domAgent->boundNodeId(document);
552     if (!nodeId || !m_namedFlowCollectionsRequested.contains(nodeId))
553         return;
554
555     m_frontend->namedFlowRemoved(nodeId, name.string());
556 }
557
558 bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
559 {
560     if (m_nodeIdToForcedPseudoState.isEmpty())
561         return false;
562
563     int nodeId = m_domAgent->boundNodeId(element);
564     if (!nodeId)
565         return false;
566
567     NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
568     if (it == m_nodeIdToForcedPseudoState.end())
569         return false;
570
571     unsigned forcedPseudoState = it->second;
572     switch (pseudoType) {
573     case CSSSelector::PseudoActive:
574         return forcedPseudoState & PseudoActive;
575     case CSSSelector::PseudoFocus:
576         return forcedPseudoState & PseudoFocus;
577     case CSSSelector::PseudoHover:
578         return forcedPseudoState & PseudoHover;
579     case CSSSelector::PseudoVisited:
580         return forcedPseudoState & PseudoVisited;
581     default:
582         return false;
583     }
584 }
585
586 void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> >& pseudoIdRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries)
587 {
588     Element* element = elementForId(errorString, nodeId);
589     if (!element)
590         return;
591
592     // Matched rules.
593     StyleResolver* styleResolver = element->ownerDocument()->styleResolver();
594     RefPtr<CSSRuleList> matchedRules = styleResolver->styleRulesForElement(element, StyleResolver::AllCSSRules);
595     matchedCSSRules = buildArrayForRuleList(matchedRules.get(), styleResolver);
596
597     // Pseudo elements.
598     if (!includePseudo || *includePseudo) {
599         RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules>::create();
600         for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
601             RefPtr<CSSRuleList> matchedRules = styleResolver->pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
602             if (matchedRules && matchedRules->length()) {
603                 RefPtr<TypeBuilder::CSS::PseudoIdRules> pseudoStyles = TypeBuilder::CSS::PseudoIdRules::create()
604                     .setPseudoId(static_cast<int>(pseudoId))
605                     .setRules(buildArrayForRuleList(matchedRules.get(), styleResolver));
606                 pseudoElements->addItem(pseudoStyles.release());
607             }
608         }
609
610         pseudoIdRules = pseudoElements.release();
611     }
612
613     // Inherited styles.
614     if (!includeInherited || *includeInherited) {
615         RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > inheritedStyles = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create();
616         Element* parentElement = element->parentElement();
617         while (parentElement) {
618             StyleResolver* parentStyleResolver= parentElement->ownerDocument()->styleResolver();
619             RefPtr<CSSRuleList> parentMatchedRules = parentStyleResolver->styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
620             RefPtr<TypeBuilder::CSS::InheritedStyleEntry> parentStyle = TypeBuilder::CSS::InheritedStyleEntry::create()
621                 .setMatchedCSSRules(buildArrayForRuleList(parentMatchedRules.get(), styleResolver));
622             if (parentElement->style() && parentElement->style()->length()) {
623                 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
624                 if (styleSheet)
625                     parentStyle->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
626             }
627
628             inheritedStyles->addItem(parentStyle.release());
629             parentElement = parentElement->parentElement();
630         }
631
632         inheritedEntries = inheritedStyles.release();
633     }
634 }
635
636 void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributesStyle)
637 {
638     Element* element = elementForId(errorString, nodeId);
639     if (!element)
640         return;
641
642     InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
643     if (!styleSheet)
644         return;
645
646     inlineStyle = styleSheet->buildObjectForStyle(element->style());
647     RefPtr<TypeBuilder::CSS::CSSStyle> attributes = buildObjectForAttributesStyle(element);
648     attributesStyle = attributes ? attributes.release() : 0;
649 }
650
651 void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >& style)
652 {
653     Element* element = elementForId(errorString, nodeId);
654     if (!element)
655         return;
656
657     RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = CSSComputedStyleDeclaration::create(element, true);
658     RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
659     style = inspectorStyle->buildArrayForComputedStyle();
660 }
661
662 void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleInfos)
663 {
664     styleInfos = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
665     Vector<Document*> documents = m_domAgent->documents();
666     for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
667         StyleSheetList* list = (*it)->styleSheets();
668         for (unsigned i = 0; i < list->length(); ++i) {
669             StyleSheet* styleSheet = list->item(i);
670             if (styleSheet->isCSSStyleSheet())
671                 collectStyleSheets(static_cast<CSSStyleSheet*>(styleSheet), styleInfos.get());
672         }
673     }
674 }
675
676 void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& styleSheetObject)
677 {
678     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
679     if (!inspectorStyleSheet)
680         return;
681
682     styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
683 }
684
685 void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
686 {
687     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
688     if (!inspectorStyleSheet)
689         return;
690
691     inspectorStyleSheet->getText(result);
692 }
693
694 void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
695 {
696     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
697     if (!inspectorStyleSheet)
698         return;
699
700     ExceptionCode ec = 0;
701     m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(inspectorStyleSheet, text)), ec);
702     *errorString = InspectorDOMAgent::toErrorString(ec);
703 }
704
705 void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
706 {
707     InspectorCSSId compoundId(fullStyleId);
708     ASSERT(!compoundId.isEmpty());
709
710     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
711     if (!inspectorStyleSheet)
712         return;
713
714     ExceptionCode ec = 0;
715     bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(inspectorStyleSheet, compoundId, propertyIndex, text, overwrite)), ec);
716     if (success)
717         result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
718     *errorString = InspectorDOMAgent::toErrorString(ec);
719 }
720
721 void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
722 {
723     InspectorCSSId compoundId(fullStyleId);
724     ASSERT(!compoundId.isEmpty());
725
726     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
727     if (!inspectorStyleSheet)
728         return;
729
730     ExceptionCode ec = 0;
731     bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(inspectorStyleSheet, compoundId, propertyIndex, disable)), ec);
732     if (success)
733         result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
734     *errorString = InspectorDOMAgent::toErrorString(ec);
735 }
736
737 void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
738 {
739     InspectorCSSId compoundId(fullRuleId);
740     ASSERT(!compoundId.isEmpty());
741
742     InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
743     if (!inspectorStyleSheet)
744         return;
745
746     ExceptionCode ec = 0;
747     bool success = m_domAgent->history()->perform(adoptPtr(new SetRuleSelectorAction(inspectorStyleSheet, compoundId, selector)), ec);
748
749     if (success)
750         result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
751     *errorString = InspectorDOMAgent::toErrorString(ec);
752 }
753
754 void InspectorCSSAgent::addRule(ErrorString* errorString, const int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
755 {
756     Node* node = m_domAgent->assertNode(errorString, contextNodeId);
757     if (!node)
758         return;
759
760     InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
761     if (!inspectorStyleSheet) {
762         *errorString = "No target stylesheet found";
763         return;
764     }
765
766     ExceptionCode ec = 0;
767     OwnPtr<AddRuleAction> action = adoptPtr(new AddRuleAction(inspectorStyleSheet, selector));
768     AddRuleAction* rawAction = action.get();
769     bool success = m_domAgent->history()->perform(action.release(), ec);
770     if (!success) {
771         *errorString = InspectorDOMAgent::toErrorString(ec);
772         return;
773     }
774
775     InspectorCSSId ruleId = rawAction->newRuleId();
776     CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
777     result = inspectorStyleSheet->buildObjectForRule(rule);
778 }
779
780 void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& cssProperties)
781 {
782     RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> > properties = TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo>::create();
783     for (int i = firstCSSProperty; i <= lastCSSProperty; ++i) {
784         CSSPropertyID id = convertToCSSPropertyID(i);
785         RefPtr<TypeBuilder::CSS::CSSPropertyInfo> property = TypeBuilder::CSS::CSSPropertyInfo::create()
786             .setName(getPropertyNameString(id));
787
788         const StylePropertyShorthand& shorthand = shorthandForProperty(id);
789         if (!shorthand.length()) {
790             properties->addItem(property.release());
791             continue;
792         }
793         RefPtr<TypeBuilder::Array<String> > longhands = TypeBuilder::Array<String>::create();
794         for (unsigned j = 0; j < shorthand.length(); ++j) {
795             CSSPropertyID longhandID = shorthand.properties()[j];
796             longhands->addItem(getPropertyNameString(longhandID));
797         }
798         property->setLonghands(longhands);
799         properties->addItem(property.release());
800     }
801     cssProperties = properties.release();
802 }
803
804 void InspectorCSSAgent::forcePseudoState(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses)
805 {
806     Element* element = m_domAgent->assertElement(errorString, nodeId);
807     if (!element)
808         return;
809
810     unsigned forcedPseudoState = computePseudoClassMask(forcedPseudoClasses.get());
811     NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
812     unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->second;
813     bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState;
814     if (!needStyleRecalc)
815         return;
816
817     if (forcedPseudoState)
818         m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState);
819     else
820         m_nodeIdToForcedPseudoState.remove(nodeId);
821     element->ownerDocument()->styleResolverChanged(RecalcStyleImmediately);
822 }
823
824 void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result)
825 {
826     Document* document = m_domAgent->assertDocument(errorString, documentNodeId);
827     if (!document)
828         return;
829
830     m_namedFlowCollectionsRequested.add(documentNodeId);
831     Vector<RefPtr<WebKitNamedFlow> > namedFlowsVector = document->namedFlows()->namedFlows();
832     RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> > namedFlows = TypeBuilder::Array<TypeBuilder::CSS::NamedFlow>::create();
833
834
835     for (Vector<RefPtr<WebKitNamedFlow> >::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it)
836         namedFlows->addItem(buildObjectForNamedFlow(errorString, it->get(), documentNodeId));
837
838     result = namedFlows.release();
839 }
840
841 void InspectorCSSAgent::getFlowByName(ErrorString* errorString, int documentNodeId, const String& flowName, RefPtr<TypeBuilder::CSS::NamedFlow>& result)
842 {
843     Document* document = m_domAgent->assertDocument(errorString, documentNodeId);
844     if (!document)
845         return;
846
847     WebKitNamedFlow* webkitNamedFlow = document->namedFlows()->flowByName(flowName);
848     if (!webkitNamedFlow) {
849         *errorString = "No target CSS Named Flow found";
850         return;
851     }
852
853     RefPtr<WebKitNamedFlow> protector(webkitNamedFlow);
854     result = buildObjectForNamedFlow(errorString, webkitNamedFlow, documentNodeId);
855 }
856
857 void InspectorCSSAgent::startSelectorProfiler(ErrorString*)
858 {
859     m_currentSelectorProfile = adoptPtr(new SelectorProfile());
860     m_state->setBoolean(CSSAgentState::isSelectorProfiling, true);
861 }
862
863 void InspectorCSSAgent::stopSelectorProfiler(ErrorString* errorString, RefPtr<TypeBuilder::CSS::SelectorProfile>& result)
864 {
865     result = stopSelectorProfilerImpl(errorString, true);
866 }
867
868 PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorProfilerImpl(ErrorString*, bool needProfile)
869 {
870     if (!m_state->getBoolean(CSSAgentState::isSelectorProfiling))
871         return 0;
872     m_state->setBoolean(CSSAgentState::isSelectorProfiling, false);
873     RefPtr<TypeBuilder::CSS::SelectorProfile> result;
874     if (m_frontend && needProfile)
875         result = m_currentSelectorProfile->toInspectorObject();
876     m_currentSelectorProfile.clear();
877     return result.release();
878 }
879
880 void InspectorCSSAgent::willMatchRule(const CSSStyleRule* rule)
881 {
882     if (m_currentSelectorProfile)
883         m_currentSelectorProfile->startSelector(rule);
884 }
885
886 void InspectorCSSAgent::didMatchRule(bool matched)
887 {
888     if (m_currentSelectorProfile)
889         m_currentSelectorProfile->commitSelector(matched);
890 }
891
892 void InspectorCSSAgent::willProcessRule(const CSSStyleRule* rule)
893 {
894     if (m_currentSelectorProfile)
895         m_currentSelectorProfile->startSelector(rule);
896 }
897
898 void InspectorCSSAgent::didProcessRule()
899 {
900     if (m_currentSelectorProfile)
901         m_currentSelectorProfile->commitSelectorTime();
902 }
903
904 InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
905 {
906     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
907     if (it == m_nodeToInspectorStyleSheet.end()) {
908         CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
909         if (!style)
910             return 0;
911
912         String newStyleSheetId = String::number(m_lastStyleSheetId++);
913         RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(m_domAgent->pageAgent(), newStyleSheetId, element, TypeBuilder::CSS::StyleSheetOrigin::Regular, this);
914         m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
915         m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
916         return inspectorStyleSheet.get();
917     }
918
919     return it->second.get();
920 }
921
922 Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
923 {
924     Node* node = m_domAgent->nodeForId(nodeId);
925     if (!node) {
926         *errorString = "No node with given id found";
927         return 0;
928     }
929     if (node->nodeType() != Node::ELEMENT_NODE) {
930         *errorString = "Not an element node";
931         return 0;
932     }
933     return toElement(node);
934 }
935
936 void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>* result)
937 {
938     InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
939     result->addItem(inspectorStyleSheet->buildObjectForStyleSheetInfo());
940     for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
941         CSSRule* rule = styleSheet->item(i);
942         if (rule->isImportRule()) {
943             CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet();
944             if (importedStyleSheet)
945                 collectStyleSheets(importedStyleSheet, result);
946         }
947     }
948 }
949
950 InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
951 {
952     RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
953     if (!inspectorStyleSheet) {
954         String id = String::number(m_lastStyleSheetId++);
955         Document* document = styleSheet->ownerDocument();
956         inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this);
957         m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
958         m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
959     }
960     return inspectorStyleSheet.get();
961 }
962
963 InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
964 {
965     if (!document) {
966         ASSERT(!createIfAbsent);
967         return 0;
968     }
969
970     RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
971     if (inspectorStyleSheet || !createIfAbsent)
972         return inspectorStyleSheet.get();
973
974     ExceptionCode ec = 0;
975     RefPtr<Element> styleElement = document->createElement("style", ec);
976     if (!ec)
977         styleElement->setAttribute("type", "text/css", ec);
978     if (!ec) {
979         ContainerNode* targetNode;
980         // HEAD is absent in ImageDocuments, for example.
981         if (document->head())
982             targetNode = document->head();
983         else if (document->body())
984             targetNode = document->body();
985         else
986             return 0;
987
988         InlineStyleOverrideScope overrideScope(document);
989         targetNode->appendChild(styleElement, ec);
990     }
991     if (ec)
992         return 0;
993     StyleSheetList* styleSheets = document->styleSheets();
994     StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1);
995     if (!styleSheet || !styleSheet->isCSSStyleSheet())
996         return 0;
997     CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet);
998     String id = String::number(m_lastStyleSheetId++);
999     inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, cssStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Inspector, InspectorDOMAgent::documentURLString(document), this);
1000     m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
1001     m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet);
1002     m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet);
1003     return inspectorStyleSheet.get();
1004 }
1005
1006 InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
1007 {
1008     IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
1009     if (it == m_idToInspectorStyleSheet.end()) {
1010         *errorString = "No style sheet with given id found";
1011         return 0;
1012     }
1013     return it->second.get();
1014 }
1015
1016 TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
1017 {
1018     TypeBuilder::CSS::StyleSheetOrigin::Enum origin = TypeBuilder::CSS::StyleSheetOrigin::Regular;
1019     if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
1020         origin = TypeBuilder::CSS::StyleSheetOrigin::User_agent;
1021     else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
1022         origin = TypeBuilder::CSS::StyleSheetOrigin::User;
1023     else {
1024         InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
1025         if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
1026             origin = TypeBuilder::CSS::StyleSheetOrigin::Inspector;
1027     }
1028     return origin;
1029 }
1030
1031 PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver)
1032 {
1033     RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create();
1034     if (!ruleList)
1035         return result.release();
1036
1037     for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
1038         CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
1039         if (!rule)
1040             continue;
1041
1042         // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available.
1043         // Since the inspector wants to walk the parent chain, we construct the full wrappers here.
1044         // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList.
1045         if (!rule->parentStyleSheet()) {
1046             rule = styleResolver->ensureFullCSSOMWrapperForInspector(rule->styleRule());
1047             if (!rule)
1048                 continue;
1049         }
1050         InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
1051         if (inspectorStyleSheet)
1052             result->addItem(inspectorStyleSheet->buildObjectForRule(rule));
1053     }
1054     return result.release();
1055 }
1056
1057 PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element)
1058 {
1059     if (!element->isStyledElement())
1060         return 0;
1061
1062     const StylePropertySet* attributeStyle = static_cast<StyledElement*>(element)->attributeStyle();
1063     if (!attributeStyle)
1064         return 0;
1065
1066     RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), const_cast<StylePropertySet*>(attributeStyle)->ensureCSSStyleDeclaration(), 0);
1067     return inspectorStyle->buildObjectForStyle();
1068 }
1069
1070 PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > InspectorCSSAgent::buildArrayForRegions(ErrorString* errorString, PassRefPtr<NodeList> regionList, int documentNodeId)
1071 {
1072     RefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > regions = TypeBuilder::Array<TypeBuilder::CSS::Region>::create();
1073
1074     for (unsigned i = 0; i < regionList->length(); ++i) {
1075         TypeBuilder::CSS::Region::RegionOverset::Enum regionOverset;
1076
1077         switch (toElement(regionList->item(i))->renderRegion()->regionState()) {
1078         case RenderRegion::RegionFit:
1079             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Fit;
1080             break;
1081         case RenderRegion::RegionEmpty:
1082             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Empty;
1083             break;
1084         case RenderRegion::RegionOverset:
1085             regionOverset = TypeBuilder::CSS::Region::RegionOverset::Overset;
1086             break;
1087         case RenderRegion::RegionUndefined:
1088             continue;
1089         default:
1090             ASSERT_NOT_REACHED();
1091             continue;
1092         }
1093
1094         RefPtr<TypeBuilder::CSS::Region> region = TypeBuilder::CSS::Region::create()
1095             .setRegionOverset(regionOverset)
1096             // documentNodeId was previously asserted
1097             .setNodeId(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, regionList->item(i)));
1098
1099         regions->addItem(region);
1100     }
1101
1102     return regions.release();
1103 }
1104
1105 PassRefPtr<TypeBuilder::CSS::NamedFlow> InspectorCSSAgent::buildObjectForNamedFlow(ErrorString* errorString, WebKitNamedFlow* webkitNamedFlow, int documentNodeId)
1106 {
1107     RefPtr<NodeList> contentList = webkitNamedFlow->getContent();
1108     RefPtr<TypeBuilder::Array<int> > content = TypeBuilder::Array<int>::create();
1109
1110     for (unsigned i = 0; i < contentList->length(); ++i) {
1111         // documentNodeId was previously asserted
1112         content->addItem(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, contentList->item(i)));
1113     }
1114
1115     RefPtr<TypeBuilder::CSS::NamedFlow> namedFlow = TypeBuilder::CSS::NamedFlow::create()
1116         .setDocumentNodeId(documentNodeId)
1117         .setName(webkitNamedFlow->name().string())
1118         .setOverset(webkitNamedFlow->overset())
1119         .setContent(content)
1120         .setRegions(buildArrayForRegions(errorString, webkitNamedFlow->getRegions(), documentNodeId));
1121
1122     return namedFlow.release();
1123 }
1124
1125 void InspectorCSSAgent::didRemoveDocument(Document* document)
1126 {
1127     if (document)
1128         m_documentToInspectorStyleSheet.remove(document);
1129 }
1130
1131 void InspectorCSSAgent::didRemoveDOMNode(Node* node)
1132 {
1133     if (!node)
1134         return;
1135
1136     int nodeId = m_domAgent->boundNodeId(node);
1137     if (nodeId)
1138         m_nodeIdToForcedPseudoState.remove(nodeId);
1139
1140     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
1141     if (it == m_nodeToInspectorStyleSheet.end())
1142         return;
1143
1144     m_idToInspectorStyleSheet.remove(it->second->id());
1145     m_nodeToInspectorStyleSheet.remove(node);
1146 }
1147
1148 void InspectorCSSAgent::didModifyDOMAttr(Element* element)
1149 {
1150     if (!element)
1151         return;
1152
1153     NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
1154     if (it == m_nodeToInspectorStyleSheet.end())
1155         return;
1156
1157     it->second->didModifyElementAttribute();
1158 }
1159
1160 void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheet* styleSheet)
1161 {
1162     if (m_frontend)
1163         m_frontend->styleSheetChanged(styleSheet->id());
1164 }
1165
1166 void InspectorCSSAgent::resetPseudoStates()
1167 {
1168     HashSet<Document*> documentsToChange;
1169     for (NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.begin(), end = m_nodeIdToForcedPseudoState.end(); it != end; ++it) {
1170         Element* element = toElement(m_domAgent->nodeForId(it->first));
1171         if (element && element->ownerDocument())
1172             documentsToChange.add(element->ownerDocument());
1173     }
1174
1175     m_nodeIdToForcedPseudoState.clear();
1176     for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = documentsToChange.end(); it != end; ++it)
1177         (*it)->styleResolverChanged(RecalcStyleImmediately);
1178 }
1179
1180 } // namespace WebCore
1181
1182 #endif // ENABLE(INSPECTOR)