blob: b2ec10cdcbea62ce4895fcca686d00db35e4c4e2 [file] [log] [blame]
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001/*
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"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000026
27#if ENABLE(INSPECTOR)
28
yurys@chromium.org83110c82012-03-15 16:44:09 +000029#include "InspectorCSSAgent.h"
30
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000031#include "CSSComputedStyleDeclaration.h"
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +000032#include "CSSImportRule.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000033#include "CSSPropertyNames.h"
34#include "CSSPropertySourceData.h"
35#include "CSSRule.h"
36#include "CSSRuleList.h"
37#include "CSSStyleRule.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000038#include "CSSStyleSheet.h"
apavlov@chromium.org31442e82012-03-05 10:44:40 +000039#include "ContentSecurityPolicy.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000040#include "DOMWindow.h"
41#include "HTMLHeadElement.h"
42#include "InspectorDOMAgent.h"
pfeldman@chromium.org94451152012-02-07 17:00:32 +000043#include "InspectorHistory.h"
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000044#include "InspectorState.h"
apavlov@chromium.org47bfc332012-03-26 14:04:50 +000045#include "InspectorTypeBuilder.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000046#include "InspectorValues.h"
yurys@chromium.org29626f82011-03-04 15:15:45 +000047#include "InstrumentingAgents.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000048#include "Node.h"
pfeldman@chromium.org840f3482011-02-11 15:23:26 +000049#include "NodeList.h"
antti@apple.comf6601802012-02-03 22:41:09 +000050#include "StylePropertySet.h"
alexis.menard@openbossa.orge6db2f62012-04-25 15:49:08 +000051#include "StyleResolver.h"
antti@apple.com8be9b562012-02-28 17:44:18 +000052#include "StyleRule.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000053#include "StyleSheetList.h"
commit-queue@webkit.org6f859512012-07-20 12:34:58 +000054#include "WebKitNamedFlowCollection.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000055
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000056#include <wtf/CurrentTime.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000057#include <wtf/HashSet.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000058#include <wtf/Vector.h>
59#include <wtf/text/CString.h>
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000060#include <wtf/text/StringConcatenate.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000061
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000062namespace CSSAgentState {
63static const char cssAgentEnabled[] = "cssAgentEnabled";
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000064static const char isSelectorProfiling[] = "isSelectorProfiling";
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000065}
66
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000067namespace WebCore {
68
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +000069enum ForcePseudoClassFlags {
70 PseudoNone = 0,
71 PseudoHover = 1 << 0,
72 PseudoFocus = 1 << 1,
73 PseudoActive = 1 << 2,
74 PseudoVisited = 1 << 3
75};
76
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000077struct RuleMatchData {
78 String selector;
79 String url;
80 unsigned lineNumber;
81 double startTime;
82};
83
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000084struct RuleMatchingStats {
85 RuleMatchingStats()
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000086 : lineNumber(0), totalTime(0.0), hits(0), matches(0)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000087 {
88 }
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000089 RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits, unsigned matches)
90 : selector(data.selector), url(data.url), lineNumber(data.lineNumber), totalTime(totalTime), hits(hits), matches(matches)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000091 {
92 }
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000093
94 String selector;
95 String url;
96 unsigned lineNumber;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000097 double totalTime;
98 unsigned hits;
99 unsigned matches;
100};
101
102class SelectorProfile {
103public:
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000104 SelectorProfile()
105 : m_totalMatchingTimeMs(0.0)
106 {
107 }
108 virtual ~SelectorProfile()
109 {
110 }
111
112 double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; }
113
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000114 String makeKey();
115 void startSelector(const CSSStyleRule*);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000116 void commitSelector(bool);
117 void commitSelectorTime();
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000118 PassRefPtr<TypeBuilder::CSS::SelectorProfile> toInspectorObject() const;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000119
120private:
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000121
122 // Key is "selector?url:line".
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000123 typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000124
125 double m_totalMatchingTimeMs;
126 RuleMatchingStatsMap m_ruleMatchingStats;
127 RuleMatchData m_currentMatchData;
128};
129
130
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000131static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray)
132{
133 DEFINE_STATIC_LOCAL(String, active, ("active"));
134 DEFINE_STATIC_LOCAL(String, hover, ("hover"));
135 DEFINE_STATIC_LOCAL(String, focus, ("focus"));
136 DEFINE_STATIC_LOCAL(String, visited, ("visited"));
137 if (!pseudoClassArray || !pseudoClassArray->length())
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000138 return PseudoNone;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000139
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000140 unsigned result = PseudoNone;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000141 for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
142 RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i);
143 String pseudoClass;
144 bool success = pseudoClassValue->asString(&pseudoClass);
145 if (!success)
146 continue;
147 if (pseudoClass == active)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000148 result |= PseudoActive;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000149 else if (pseudoClass == hover)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000150 result |= PseudoHover;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000151 else if (pseudoClass == focus)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000152 result |= PseudoFocus;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000153 else if (pseudoClass == visited)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000154 result |= PseudoVisited;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000155 }
156
157 return result;
158}
159
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000160inline String SelectorProfile::makeKey()
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000161{
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000162 return makeString(m_currentMatchData.selector, "?", m_currentMatchData.url, ":", String::number(m_currentMatchData.lineNumber));
163}
164
165inline void SelectorProfile::startSelector(const CSSStyleRule* rule)
166{
167 m_currentMatchData.selector = rule->selectorText();
168 CSSStyleSheet* styleSheet = rule->parentStyleSheet();
169 String url = emptyString();
170 if (styleSheet) {
171 url = InspectorStyleSheet::styleSheetURL(styleSheet);
172 if (url.isEmpty())
antti@apple.comfe126eb2012-04-25 22:42:47 +0000173 url = InspectorDOMAgent::documentURLString(styleSheet->ownerDocument());
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000174 }
175 m_currentMatchData.url = url;
antti@apple.com972c0822012-02-28 09:38:51 +0000176 m_currentMatchData.lineNumber = rule->styleRule()->sourceLine();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000177 m_currentMatchData.startTime = WTF::currentTimeMS();
178}
179
180inline void SelectorProfile::commitSelector(bool matched)
181{
182 double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
183 m_totalMatchingTimeMs += matchTimeMs;
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000184
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000185 RuleMatchingStatsMap::AddResult result = m_ruleMatchingStats.add(makeKey(), RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0));
186 if (!result.isNewEntry) {
187 result.iterator->second.totalTime += matchTimeMs;
188 result.iterator->second.hits += 1;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000189 if (matched)
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000190 result.iterator->second.matches += 1;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000191 }
192}
193
194inline void SelectorProfile::commitSelectorTime()
195{
196 double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
197 m_totalMatchingTimeMs += processingTimeMs;
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000198
199 RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000200 if (it == m_ruleMatchingStats.end())
201 return;
202
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000203 it->second.totalTime += processingTimeMs;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000204}
205
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000206PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject() const
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000207{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000208 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry> > selectorProfileData = TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry>::create();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000209 for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin(); it != m_ruleMatchingStats.end(); ++it) {
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000210 RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS::SelectorProfileEntry::create()
211 .setSelector(it->second.selector)
212 .setUrl(it->second.url)
213 .setLineNumber(it->second.lineNumber)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000214 .setTime(it->second.totalTime)
215 .setHitCount(it->second.hits)
216 .setMatchCount(it->second.matches);
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000217 selectorProfileData->addItem(entry.release());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000218 }
219
220 RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::SelectorProfile::create()
221 .setTotalTime(totalMatchingTimeMs())
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000222 .setData(selectorProfileData);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000223 return result.release();
224}
225
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000226class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
227 WTF_MAKE_NONCOPYABLE(StyleSheetAction);
228public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000229 StyleSheetAction(const String& name, InspectorStyleSheet* styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000230 : InspectorHistory::Action(name)
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000231 , m_styleSheet(styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000232 {
233 }
234
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000235protected:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000236 RefPtr<InspectorStyleSheet> m_styleSheet;
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000237};
238
239class InspectorCSSAgent::SetStyleSheetTextAction : public InspectorCSSAgent::StyleSheetAction {
240 WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction);
241public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000242 SetStyleSheetTextAction(InspectorStyleSheet* styleSheet, const String& text)
243 : InspectorCSSAgent::StyleSheetAction("SetStyleSheetText", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000244 , m_text(text)
245 {
246 }
247
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000248 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000249 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000250 if (!m_styleSheet->getText(&m_oldText))
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000251 return false;
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000252 return redo(ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000253 }
254
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000255 virtual bool undo(ExceptionCode&)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000256 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000257 if (m_styleSheet->setText(m_oldText)) {
258 m_styleSheet->reparseStyleSheet(m_oldText);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000259 return true;
260 }
261 return false;
262 }
263
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000264 virtual bool redo(ExceptionCode&)
265 {
266 if (m_styleSheet->setText(m_text)) {
267 m_styleSheet->reparseStyleSheet(m_text);
268 return true;
269 }
270 return false;
271 }
272
pfeldman@chromium.orga1a70a42012-02-14 08:50:19 +0000273 virtual String mergeId()
274 {
275 return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data());
276 }
277
278 virtual void merge(PassOwnPtr<Action> action)
279 {
280 ASSERT(action->mergeId() == mergeId());
281
282 SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action.get());
283 m_text = other->m_text;
284 }
285
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000286private:
287 String m_text;
288 String m_oldText;
289};
290
291class InspectorCSSAgent::SetPropertyTextAction : public InspectorCSSAgent::StyleSheetAction {
292 WTF_MAKE_NONCOPYABLE(SetPropertyTextAction);
293public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000294 SetPropertyTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, const String& text, bool overwrite)
295 : InspectorCSSAgent::StyleSheetAction("SetPropertyText", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000296 , m_cssId(cssId)
297 , m_propertyIndex(propertyIndex)
298 , m_text(text)
299 , m_overwrite(overwrite)
300 {
301 }
302
303 virtual String toString()
304 {
305 return mergeId() + ": " + m_oldText + " -> " + m_text;
306 }
307
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000308 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000309 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000310 return redo(ec);
311 }
312
313 virtual bool undo(ExceptionCode& ec)
314 {
315 String placeholder;
316 return m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec);
317 }
318
319 virtual bool redo(ExceptionCode& ec)
320 {
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000321 String oldText;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000322 bool result = m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000323 m_oldText = oldText.stripWhiteSpace();
324 // FIXME: remove this once the model handles this case.
benjamin@webkit.org127cec2c2012-04-30 21:32:44 +0000325 if (!m_oldText.endsWith(';'))
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000326 m_oldText += ";";
327 return result;
328 }
329
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000330 virtual String mergeId()
331 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000332 return String::format("SetPropertyText %s:%u:%s", m_styleSheet->id().utf8().data(), m_propertyIndex, m_overwrite ? "true" : "false");
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000333 }
334
335 virtual void merge(PassOwnPtr<Action> action)
336 {
337 ASSERT(action->mergeId() == mergeId());
338
339 SetPropertyTextAction* other = static_cast<SetPropertyTextAction*>(action.get());
340 m_text = other->m_text;
341 }
342
343private:
344 InspectorCSSId m_cssId;
345 unsigned m_propertyIndex;
346 String m_text;
347 String m_oldText;
348 bool m_overwrite;
349};
350
351class InspectorCSSAgent::TogglePropertyAction : public InspectorCSSAgent::StyleSheetAction {
352 WTF_MAKE_NONCOPYABLE(TogglePropertyAction);
353public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000354 TogglePropertyAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, bool disable)
355 : InspectorCSSAgent::StyleSheetAction("ToggleProperty", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000356 , m_cssId(cssId)
357 , m_propertyIndex(propertyIndex)
358 , m_disable(disable)
359 {
360 }
361
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000362 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000363 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000364 return redo(ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000365 }
366
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000367 virtual bool undo(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000368 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000369 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000370 }
371
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000372 virtual bool redo(ExceptionCode& ec)
373 {
374 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec);
375 }
376
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000377private:
378 InspectorCSSId m_cssId;
379 unsigned m_propertyIndex;
380 bool m_disable;
381};
382
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000383class InspectorCSSAgent::SetRuleSelectorAction : public InspectorCSSAgent::StyleSheetAction {
384 WTF_MAKE_NONCOPYABLE(SetRuleSelectorAction);
385public:
386 SetRuleSelectorAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& selector)
387 : InspectorCSSAgent::StyleSheetAction("SetRuleSelector", styleSheet)
388 , m_cssId(cssId)
389 , m_selector(selector)
390 {
391 }
392
393 virtual bool perform(ExceptionCode& ec)
394 {
395 m_oldSelector = m_styleSheet->ruleSelector(m_cssId, ec);
396 if (ec)
397 return false;
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000398 return redo(ec);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000399 }
400
401 virtual bool undo(ExceptionCode& ec)
402 {
403 return m_styleSheet->setRuleSelector(m_cssId, m_oldSelector, ec);
404 }
405
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000406 virtual bool redo(ExceptionCode& ec)
407 {
408 return m_styleSheet->setRuleSelector(m_cssId, m_selector, ec);
409 }
410
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000411private:
412 InspectorCSSId m_cssId;
413 String m_selector;
414 String m_oldSelector;
415};
416
417class InspectorCSSAgent::AddRuleAction : public InspectorCSSAgent::StyleSheetAction {
418 WTF_MAKE_NONCOPYABLE(AddRuleAction);
419public:
420 AddRuleAction(InspectorStyleSheet* styleSheet, const String& selector)
421 : InspectorCSSAgent::StyleSheetAction("AddRule", styleSheet)
422 , m_selector(selector)
423 {
424 }
425
426 virtual bool perform(ExceptionCode& ec)
427 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000428 return redo(ec);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000429 }
430
431 virtual bool undo(ExceptionCode& ec)
432 {
433 return m_styleSheet->deleteRule(m_newId, ec);
434 }
435
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000436 virtual bool redo(ExceptionCode& ec)
437 {
438 CSSStyleRule* cssStyleRule = m_styleSheet->addRule(m_selector, ec);
439 if (ec)
440 return false;
441 m_newId = m_styleSheet->ruleId(cssStyleRule);
442 return true;
443 }
444
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000445 InspectorCSSId newRuleId() { return m_newId; }
446
447private:
448 InspectorCSSId m_newId;
449 String m_selector;
450 String m_oldSelector;
451};
452
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000453// static
andreas.kling@nokia.comf04e49c2011-10-14 21:33:49 +0000454CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000455{
andreas.kling@nokia.com0fb29262011-10-31 15:53:14 +0000456 if (!rule->isStyleRule())
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000457 return 0;
458 return static_cast<CSSStyleRule*>(rule);
459}
460
pfeldman@chromium.orgccc8cd932011-11-28 14:41:48 +0000461InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorState* state, InspectorDOMAgent* domAgent)
pfeldman@chromium.org2f44edb2011-11-29 14:43:10 +0000462 : InspectorBaseAgent<InspectorCSSAgent>("CSS", instrumentingAgents, state)
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000463 , m_frontend(0)
yurys@chromium.org29626f82011-03-04 15:15:45 +0000464 , m_domAgent(domAgent)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000465 , m_lastStyleSheetId(1)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000466{
yurys@chromium.orgd8e367c2011-02-21 14:38:24 +0000467 m_domAgent->setDOMListener(this);
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000468 m_instrumentingAgents->setInspectorCSSAgent(this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000469}
470
471InspectorCSSAgent::~InspectorCSSAgent()
472{
pfeldman@chromium.orgeccfccf2011-12-02 08:21:57 +0000473 ASSERT(!m_domAgent);
yurys@chromium.org29626f82011-03-04 15:15:45 +0000474 m_instrumentingAgents->setInspectorCSSAgent(0);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000475 reset();
476}
477
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000478void InspectorCSSAgent::setFrontend(InspectorFrontend* frontend)
479{
480 ASSERT(!m_frontend);
481 m_frontend = frontend->css();
482}
483
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000484void InspectorCSSAgent::clearFrontend()
485{
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000486 ASSERT(m_frontend);
487 m_frontend = 0;
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000488 resetPseudoStates();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000489 String errorString;
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000490 stopSelectorProfilerImpl(&errorString, false);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000491}
492
pfeldman@chromium.orgeccfccf2011-12-02 08:21:57 +0000493void InspectorCSSAgent::discardAgent()
494{
495 m_domAgent->setDOMListener(0);
496 m_domAgent = 0;
497}
498
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000499void InspectorCSSAgent::restore()
500{
501 if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) {
502 ErrorString error;
503 enable(&error);
504 }
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000505 if (m_state->getBoolean(CSSAgentState::isSelectorProfiling)) {
506 String errorString;
507 startSelectorProfiler(&errorString);
508 }
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000509}
510
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000511void InspectorCSSAgent::reset()
512{
513 m_idToInspectorStyleSheet.clear();
514 m_cssStyleSheetToInspectorStyleSheet.clear();
515 m_nodeToInspectorStyleSheet.clear();
516 m_documentToInspectorStyleSheet.clear();
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000517 resetPseudoStates();
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000518}
519
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000520void InspectorCSSAgent::enable(ErrorString*)
521{
522 m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000523}
524
525void InspectorCSSAgent::disable(ErrorString*)
526{
527 m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
528}
529
530void InspectorCSSAgent::mediaQueryResultChanged()
531{
532 if (m_frontend)
533 m_frontend->mediaQueryResultChanged();
534}
535
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000536bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
537{
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000538 if (m_nodeIdToForcedPseudoState.isEmpty())
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000539 return false;
540
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000541 int nodeId = m_domAgent->boundNodeId(element);
542 if (!nodeId)
543 return false;
544
545 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
546 if (it == m_nodeIdToForcedPseudoState.end())
547 return false;
548
549 unsigned forcedPseudoState = it->second;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000550 switch (pseudoType) {
551 case CSSSelector::PseudoActive:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000552 return forcedPseudoState & PseudoActive;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000553 case CSSSelector::PseudoFocus:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000554 return forcedPseudoState & PseudoFocus;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000555 case CSSSelector::PseudoHover:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000556 return forcedPseudoState & PseudoHover;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000557 case CSSSelector::PseudoVisited:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000558 return forcedPseudoState & PseudoVisited;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000559 default:
560 return false;
561 }
562}
563
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000564void InspectorCSSAgent::recalcStyleForPseudoStateIfNeeded(Element* element, InspectorArray* forcedPseudoClasses)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000565{
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000566 int nodeId = m_domAgent->boundNodeId(element);
567 if (!nodeId)
568 return;
569
570 unsigned forcedPseudoState = computePseudoClassMask(forcedPseudoClasses);
571 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
572 unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->second;
573 bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState;
574 if (!needStyleRecalc)
575 return;
576
577 if (forcedPseudoState)
578 m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState);
579 else
580 m_nodeIdToForcedPseudoState.remove(nodeId);
581 element->ownerDocument()->styleResolverChanged(RecalcStyleImmediately);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000582}
583
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000584void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>* forcedPseudoClasses, 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)
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000585{
586 Element* element = elementForId(errorString, nodeId);
587 if (!element)
588 return;
589
590 recalcStyleForPseudoStateIfNeeded(element, forcedPseudoClasses ? forcedPseudoClasses->get() : 0);
591
592 // Matched rules.
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000593 StyleResolver* styleResolver = element->ownerDocument()->styleResolver();
594 RefPtr<CSSRuleList> matchedRules = styleResolver->styleRulesForElement(element, StyleResolver::AllCSSRules);
595 matchedCSSRules = buildArrayForRuleList(matchedRules.get(), styleResolver);
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000596
597 // Pseudo elements.
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000598 if (!includePseudo || *includePseudo) {
599 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdRules>::create();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000600 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) {
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000601 RefPtr<CSSRuleList> matchedRules = styleResolver->pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000602 if (matchedRules && matchedRules->length()) {
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000603 RefPtr<TypeBuilder::CSS::PseudoIdRules> pseudoStyles = TypeBuilder::CSS::PseudoIdRules::create()
604 .setPseudoId(static_cast<int>(pseudoId))
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000605 .setRules(buildArrayForRuleList(matchedRules.get(), styleResolver));
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000606 pseudoElements->addItem(pseudoStyles.release());
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000607 }
608 }
609
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000610 pseudoIdRules = pseudoElements.release();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000611 }
612
613 // Inherited styles.
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000614 if (!includeInherited || *includeInherited) {
615 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > inheritedStyles = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000616 Element* parentElement = element->parentElement();
617 while (parentElement) {
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000618 StyleResolver* parentStyleResolver= parentElement->ownerDocument()->styleResolver();
619 RefPtr<CSSRuleList> parentMatchedRules = parentStyleResolver->styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000620 RefPtr<TypeBuilder::CSS::InheritedStyleEntry> parentStyle = TypeBuilder::CSS::InheritedStyleEntry::create()
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000621 .setMatchedCSSRules(buildArrayForRuleList(parentMatchedRules.get(), styleResolver));
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000622 if (parentElement->style() && parentElement->style()->length()) {
623 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
624 if (styleSheet)
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000625 parentStyle->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000626 }
627
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000628 inheritedStyles->addItem(parentStyle.release());
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000629 parentElement = parentElement->parentElement();
630 }
631
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000632 inheritedEntries = inheritedStyles.release();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000633 }
634}
635
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000636void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributesStyle)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000637{
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000638 Element* element = elementForId(errorString, nodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000639 if (!element)
640 return;
641
642 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
643 if (!styleSheet)
644 return;
645
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000646 inlineStyle = styleSheet->buildObjectForStyle(element->style());
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000647 RefPtr<TypeBuilder::CSS::CSSStyle> attributes = buildObjectForAttributesStyle(element);
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +0000648 attributesStyle = attributes ? attributes.release() : 0;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000649}
650
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000651void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>* forcedPseudoClasses, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >& style)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000652{
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000653 Element* element = elementForId(errorString, nodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000654 if (!element)
655 return;
656
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000657 recalcStyleForPseudoStateIfNeeded(element, forcedPseudoClasses ? forcedPseudoClasses->get() : 0);
658
antti@apple.comac019f32012-02-10 18:22:24 +0000659 RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = CSSComputedStyleDeclaration::create(element, true);
yurys@chromium.org418f91f2010-12-24 17:51:25 +0000660 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000661 style = inspectorStyle->buildArrayForComputedStyle();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000662}
663
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000664void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleInfos)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000665{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000666 styleInfos = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
pfeldman@chromium.org840f3482011-02-11 15:23:26 +0000667 Vector<Document*> documents = m_domAgent->documents();
668 for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000669 StyleSheetList* list = (*it)->styleSheets();
670 for (unsigned i = 0; i < list->length(); ++i) {
671 StyleSheet* styleSheet = list->item(i);
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +0000672 if (styleSheet->isCSSStyleSheet())
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000673 collectStyleSheets(static_cast<CSSStyleSheet*>(styleSheet), styleInfos.get());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000674 }
675 }
676}
677
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000678void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& styleSheetObject)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000679{
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000680 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000681 if (!inspectorStyleSheet)
682 return;
683
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000684 styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000685}
686
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000687void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000688{
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000689 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000690 if (!inspectorStyleSheet)
691 return;
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000692
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000693 inspectorStyleSheet->getText(result);
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000694}
695
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000696void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000697{
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000698 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
699 if (!inspectorStyleSheet)
700 return;
701
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000702 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000703 m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(inspectorStyleSheet, text)), ec);
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000704 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000705}
706
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000707void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000708{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000709 InspectorCSSId compoundId(fullStyleId);
710 ASSERT(!compoundId.isEmpty());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000711
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000712 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000713 if (!inspectorStyleSheet)
714 return;
715
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000716 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000717 bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(inspectorStyleSheet, compoundId, propertyIndex, text, overwrite)), ec);
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000718 if (success)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000719 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000720 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000721}
722
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000723void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<TypeBuilder::CSS::CSSStyle>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000724{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000725 InspectorCSSId compoundId(fullStyleId);
726 ASSERT(!compoundId.isEmpty());
727
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000728 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000729 if (!inspectorStyleSheet)
730 return;
731
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000732 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000733 bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(inspectorStyleSheet, compoundId, propertyIndex, disable)), ec);
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000734 if (success)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000735 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000736 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000737}
738
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000739void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000740{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000741 InspectorCSSId compoundId(fullRuleId);
742 ASSERT(!compoundId.isEmpty());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000743
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000744 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000745 if (!inspectorStyleSheet)
746 return;
747
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000748 ExceptionCode ec = 0;
749 bool success = m_domAgent->history()->perform(adoptPtr(new SetRuleSelectorAction(inspectorStyleSheet, compoundId, selector)), ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000750
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000751 if (success)
752 result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000753 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000754}
755
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000756void InspectorCSSAgent::addRule(ErrorString* errorString, const int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000757{
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000758 Node* node = m_domAgent->assertNode(errorString, contextNodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000759 if (!node)
760 return;
761
762 InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000763 if (!inspectorStyleSheet) {
764 *errorString = "No target stylesheet found";
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +0000765 return;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000766 }
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000767
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000768 ExceptionCode ec = 0;
769 OwnPtr<AddRuleAction> action = adoptPtr(new AddRuleAction(inspectorStyleSheet, selector));
770 AddRuleAction* rawAction = action.get();
771 bool success = m_domAgent->history()->perform(action.release(), ec);
772 if (!success) {
773 *errorString = InspectorDOMAgent::toErrorString(ec);
774 return;
775 }
776
777 InspectorCSSId ruleId = rawAction->newRuleId();
778 CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
779 result = inspectorStyleSheet->buildObjectForRule(rule);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000780}
781
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000782void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<String> >& cssProperties)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000783{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000784 RefPtr<TypeBuilder::Array<String> > properties = TypeBuilder::Array<String>::create();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000785 for (int i = 0; i < numCSSProperties; ++i)
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000786 properties->addItem(propertyNameStrings[i]);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000787
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000788 cssProperties = properties.release();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000789}
790
commit-queue@webkit.org6f859512012-07-20 12:34:58 +0000791void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<String> >& result)
792{
793 Document* document = m_domAgent->assertDocument(errorString, nodeId);
794 if (!document)
795 return;
796
797 Vector<String> namedFlowsVector = document->namedFlows()->namedFlowsNames();
798 RefPtr<TypeBuilder::Array<String> > namedFlows = TypeBuilder::Array<String>::create();
799
800 for (Vector<String>::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it)
801 namedFlows->addItem(*it);
802
803 result = namedFlows.release();
804}
805
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000806void InspectorCSSAgent::startSelectorProfiler(ErrorString*)
807{
808 m_currentSelectorProfile = adoptPtr(new SelectorProfile());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000809 m_state->setBoolean(CSSAgentState::isSelectorProfiling, true);
810}
811
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000812void InspectorCSSAgent::stopSelectorProfiler(ErrorString* errorString, RefPtr<TypeBuilder::CSS::SelectorProfile>& result)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000813{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000814 result = stopSelectorProfilerImpl(errorString, true);
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000815}
816
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000817PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorProfilerImpl(ErrorString*, bool needProfile)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000818{
819 if (!m_state->getBoolean(CSSAgentState::isSelectorProfiling))
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000820 return 0;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000821 m_state->setBoolean(CSSAgentState::isSelectorProfiling, false);
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000822 RefPtr<TypeBuilder::CSS::SelectorProfile> result;
823 if (m_frontend && needProfile)
824 result = m_currentSelectorProfile->toInspectorObject();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000825 m_currentSelectorProfile.clear();
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000826 return result.release();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000827}
828
829void InspectorCSSAgent::willMatchRule(const CSSStyleRule* rule)
830{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000831 if (m_currentSelectorProfile)
832 m_currentSelectorProfile->startSelector(rule);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000833}
834
835void InspectorCSSAgent::didMatchRule(bool matched)
836{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000837 if (m_currentSelectorProfile)
838 m_currentSelectorProfile->commitSelector(matched);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000839}
840
841void InspectorCSSAgent::willProcessRule(const CSSStyleRule* rule)
842{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000843 if (m_currentSelectorProfile)
844 m_currentSelectorProfile->startSelector(rule);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000845}
846
847void InspectorCSSAgent::didProcessRule()
848{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000849 if (m_currentSelectorProfile)
850 m_currentSelectorProfile->commitSelectorTime();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000851}
852
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000853InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
854{
855 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
856 if (it == m_nodeToInspectorStyleSheet.end()) {
857 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
858 if (!style)
859 return 0;
860
861 String newStyleSheetId = String::number(m_lastStyleSheetId++);
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000862 RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(m_domAgent->pageAgent(), newStyleSheetId, element, TypeBuilder::CSS::StyleSheetOrigin::Regular, this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000863 m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
864 m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
865 return inspectorStyleSheet.get();
866 }
867
868 return it->second.get();
869}
870
pfeldman@chromium.org7e420b52011-03-21 07:54:32 +0000871Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000872{
873 Node* node = m_domAgent->nodeForId(nodeId);
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000874 if (!node) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +0000875 *errorString = "No node with given id found";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000876 return 0;
877 }
878 if (node->nodeType() != Node::ELEMENT_NODE) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +0000879 *errorString = "Not an element node";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000880 return 0;
881 }
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000882 return toElement(node);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000883}
884
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000885void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>* result)
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +0000886{
887 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000888 result->addItem(inspectorStyleSheet->buildObjectForStyleSheetInfo());
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +0000889 for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
andreas.kling@nokia.com1678e2b2011-10-14 18:36:31 +0000890 CSSRule* rule = styleSheet->item(i);
891 if (rule->isImportRule()) {
892 CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet();
893 if (importedStyleSheet)
894 collectStyleSheets(importedStyleSheet, result);
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +0000895 }
896 }
897}
898
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000899InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
900{
901 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
902 if (!inspectorStyleSheet) {
903 String id = String::number(m_lastStyleSheetId++);
antti@apple.comfe126eb2012-04-25 22:42:47 +0000904 Document* document = styleSheet->ownerDocument();
pfeldman@chromium.orgf9adb6a2012-05-24 14:35:50 +0000905 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000906 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
907 m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
908 }
909 return inspectorStyleSheet.get();
910}
911
912InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
913{
914 if (!document) {
915 ASSERT(!createIfAbsent);
916 return 0;
917 }
918
919 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
920 if (inspectorStyleSheet || !createIfAbsent)
921 return inspectorStyleSheet.get();
922
923 ExceptionCode ec = 0;
924 RefPtr<Element> styleElement = document->createElement("style", ec);
925 if (!ec)
926 styleElement->setAttribute("type", "text/css", ec);
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +0000927 if (!ec) {
928 ContainerNode* targetNode;
929 // HEAD is absent in ImageDocuments, for example.
930 if (document->head())
931 targetNode = document->head();
932 else if (document->body())
933 targetNode = document->body();
934 else
935 return 0;
apavlov@chromium.org31442e82012-03-05 10:44:40 +0000936
937 InlineStyleOverrideScope overrideScope(document);
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +0000938 targetNode->appendChild(styleElement, ec);
939 }
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000940 if (ec)
941 return 0;
942 StyleSheetList* styleSheets = document->styleSheets();
943 StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1);
apavlov@chromium.org31442e82012-03-05 10:44:40 +0000944 if (!styleSheet || !styleSheet->isCSSStyleSheet())
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000945 return 0;
946 CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet);
947 String id = String::number(m_lastStyleSheetId++);
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000948 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, cssStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Inspector, InspectorDOMAgent::documentURLString(document), this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000949 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
950 m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet);
951 m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet);
952 return inspectorStyleSheet.get();
953}
954
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000955InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000956{
957 IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000958 if (it == m_idToInspectorStyleSheet.end()) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +0000959 *errorString = "No style sheet with given id found";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000960 return 0;
961 }
962 return it->second.get();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000963}
964
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000965TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000966{
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000967 TypeBuilder::CSS::StyleSheetOrigin::Enum origin = TypeBuilder::CSS::StyleSheetOrigin::Regular;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000968 if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000969 origin = TypeBuilder::CSS::StyleSheetOrigin::User_agent;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000970 else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000971 origin = TypeBuilder::CSS::StyleSheetOrigin::User;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000972 else {
973 InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
974 if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000975 origin = TypeBuilder::CSS::StyleSheetOrigin::Inspector;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000976 }
977 return origin;
978}
979
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000980PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000981{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000982 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000983 if (!ruleList)
984 return result.release();
985
986 for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
987 CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
988 if (!rule)
989 continue;
990
alexis.menard@openbossa.org2d5f8df2012-04-24 19:46:29 +0000991 // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available.
antti@apple.comc3fcabe2012-04-02 11:50:00 +0000992 // Since the inspector wants to walk the parent chain, we construct the full wrappers here.
alexis.menard@openbossa.org2d5f8df2012-04-24 19:46:29 +0000993 // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList.
antti@apple.comc3fcabe2012-04-02 11:50:00 +0000994 if (!rule->parentStyleSheet()) {
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000995 rule = styleResolver->ensureFullCSSOMWrapperForInspector(rule->styleRule());
antti@apple.comc3fcabe2012-04-02 11:50:00 +0000996 if (!rule)
997 continue;
998 }
999 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
1000 if (inspectorStyleSheet)
1001 result->addItem(inspectorStyleSheet->buildObjectForRule(rule));
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001002 }
1003 return result.release();
1004}
1005
apavlov@chromium.org47bfc332012-03-26 14:04:50 +00001006PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001007{
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001008 if (!element->isStyledElement())
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001009 return 0;
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001010
kling@webkit.org42c11822012-02-05 08:29:38 +00001011 StylePropertySet* attributeStyle = static_cast<StyledElement*>(element)->attributeStyle();
1012 if (!attributeStyle)
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001013 return 0;
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001014
kling@webkit.org42c11822012-02-05 08:29:38 +00001015 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), attributeStyle->ensureCSSStyleDeclaration(), 0);
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001016 return inspectorStyle->buildObjectForStyle();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001017}
1018
1019void InspectorCSSAgent::didRemoveDocument(Document* document)
1020{
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +00001021 if (document)
1022 m_documentToInspectorStyleSheet.remove(document);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001023}
1024
1025void InspectorCSSAgent::didRemoveDOMNode(Node* node)
1026{
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +00001027 if (!node)
1028 return;
1029
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001030 int nodeId = m_domAgent->boundNodeId(node);
1031 if (nodeId)
1032 m_nodeIdToForcedPseudoState.remove(nodeId);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001033
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001034 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
1035 if (it == m_nodeToInspectorStyleSheet.end())
1036 return;
1037
1038 m_idToInspectorStyleSheet.remove(it->second->id());
1039 m_nodeToInspectorStyleSheet.remove(node);
1040}
1041
apavlov@chromium.org93e800a2010-12-24 16:39:32 +00001042void InspectorCSSAgent::didModifyDOMAttr(Element* element)
1043{
1044 if (!element)
1045 return;
1046
1047 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
1048 if (it == m_nodeToInspectorStyleSheet.end())
1049 return;
1050
1051 it->second->didModifyElementAttribute();
1052}
1053
pfeldman@chromium.orga1a70a42012-02-14 08:50:19 +00001054void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheet* styleSheet)
1055{
1056 if (m_frontend)
1057 m_frontend->styleSheetChanged(styleSheet->id());
1058}
1059
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001060void InspectorCSSAgent::resetPseudoStates()
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001061{
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001062 HashSet<Document*> documentsToChange;
1063 for (NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.begin(), end = m_nodeIdToForcedPseudoState.end(); it != end; ++it) {
1064 Element* element = toElement(m_domAgent->nodeForId(it->first));
1065 if (element && element->ownerDocument())
1066 documentsToChange.add(element->ownerDocument());
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001067 }
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001068
1069 m_nodeIdToForcedPseudoState.clear();
1070 for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = documentsToChange.end(); it != end; ++it)
1071 (*it)->styleResolverChanged(RecalcStyleImmediately);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001072}
1073
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001074} // namespace WebCore
1075
1076#endif // ENABLE(INSPECTOR)