blob: 51996a3c353072ab8860e14fa90ed6f6e2e83635 [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"
mkwst@chromium.org33cdf432013-02-08 14:21:48 +000041#include "ExceptionCodePlaceholder.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000042#include "HTMLHeadElement.h"
43#include "InspectorDOMAgent.h"
pfeldman@chromium.org94451152012-02-07 17:00:32 +000044#include "InspectorHistory.h"
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000045#include "InspectorState.h"
apavlov@chromium.org47bfc332012-03-26 14:04:50 +000046#include "InspectorTypeBuilder.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000047#include "InspectorValues.h"
yurys@chromium.org29626f82011-03-04 15:15:45 +000048#include "InstrumentingAgents.h"
rniwa@webkit.org3fc452e2012-08-24 21:46:24 +000049#include "NamedFlowCollection.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000050#include "Node.h"
pfeldman@chromium.org840f3482011-02-11 15:23:26 +000051#include "NodeList.h"
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +000052#include "RenderRegion.h"
antti@apple.comf6601802012-02-03 22:41:09 +000053#include "StylePropertySet.h"
pfeldman@chromium.orga7128942012-07-25 13:48:47 +000054#include "StylePropertyShorthand.h"
alexis.menard@openbossa.orge6db2f62012-04-25 15:49:08 +000055#include "StyleResolver.h"
antti@apple.com8be9b562012-02-28 17:44:18 +000056#include "StyleRule.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000057#include "StyleSheetList.h"
commit-queue@webkit.org285994b2012-07-24 12:00:33 +000058#include "WebKitNamedFlow.h"
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000059
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000060#include <wtf/CurrentTime.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000061#include <wtf/HashSet.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000062#include <wtf/Vector.h>
63#include <wtf/text/CString.h>
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000064#include <wtf/text/StringConcatenate.h>
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000065
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000066namespace CSSAgentState {
commit-queue@webkit.org27444d52012-12-24 16:45:04 +000067static const char cssAgentEnabled[] = "cssAgentEnabled";
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000068static const char isSelectorProfiling[] = "isSelectorProfiling";
apavlov@chromium.orgad517d02011-12-15 09:23:19 +000069}
70
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +000071namespace WebCore {
72
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +000073enum ForcePseudoClassFlags {
74 PseudoNone = 0,
75 PseudoHover = 1 << 0,
76 PseudoFocus = 1 << 1,
77 PseudoActive = 1 << 2,
78 PseudoVisited = 1 << 3
79};
80
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000081struct RuleMatchData {
82 String selector;
83 String url;
84 unsigned lineNumber;
85 double startTime;
86};
87
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000088struct RuleMatchingStats {
89 RuleMatchingStats()
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000090 : lineNumber(0), totalTime(0.0), hits(0), matches(0)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000091 {
92 }
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000093 RuleMatchingStats(const RuleMatchData& data, double totalTime, unsigned hits, unsigned matches)
94 : selector(data.selector), url(data.url), lineNumber(data.lineNumber), totalTime(totalTime), hits(hits), matches(matches)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +000095 {
96 }
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +000097
98 String selector;
99 String url;
100 unsigned lineNumber;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000101 double totalTime;
102 unsigned hits;
103 unsigned matches;
104};
105
106class SelectorProfile {
zoltan@webkit.org2eb7bec2012-09-14 09:12:48 +0000107 WTF_MAKE_FAST_ALLOCATED;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000108public:
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000109 SelectorProfile()
110 : m_totalMatchingTimeMs(0.0)
111 {
112 }
113 virtual ~SelectorProfile()
114 {
115 }
116
117 double totalMatchingTimeMs() const { return m_totalMatchingTimeMs; }
118
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000119 String makeKey();
120 void startSelector(const CSSStyleRule*);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000121 void commitSelector(bool);
122 void commitSelectorTime();
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000123 PassRefPtr<TypeBuilder::CSS::SelectorProfile> toInspectorObject() const;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000124
125private:
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000126
127 // Key is "selector?url:line".
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000128 typedef HashMap<String, RuleMatchingStats> RuleMatchingStatsMap;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000129
130 double m_totalMatchingTimeMs;
131 RuleMatchingStatsMap m_ruleMatchingStats;
132 RuleMatchData m_currentMatchData;
133};
134
135
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000136static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray)
137{
abarth@webkit.orgf6d1b8c2012-08-29 07:38:10 +0000138 DEFINE_STATIC_LOCAL(String, active, (ASCIILiteral("active")));
139 DEFINE_STATIC_LOCAL(String, hover, (ASCIILiteral("hover")));
140 DEFINE_STATIC_LOCAL(String, focus, (ASCIILiteral("focus")));
141 DEFINE_STATIC_LOCAL(String, visited, (ASCIILiteral("visited")));
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000142 if (!pseudoClassArray || !pseudoClassArray->length())
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000143 return PseudoNone;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000144
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000145 unsigned result = PseudoNone;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000146 for (size_t i = 0; i < pseudoClassArray->length(); ++i) {
147 RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i);
148 String pseudoClass;
149 bool success = pseudoClassValue->asString(&pseudoClass);
150 if (!success)
151 continue;
152 if (pseudoClass == active)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000153 result |= PseudoActive;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000154 else if (pseudoClass == hover)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000155 result |= PseudoHover;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000156 else if (pseudoClass == focus)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000157 result |= PseudoFocus;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000158 else if (pseudoClass == visited)
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000159 result |= PseudoVisited;
apavlov@chromium.org6678c9b2011-06-28 12:07:48 +0000160 }
161
162 return result;
163}
164
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000165inline String SelectorProfile::makeKey()
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000166{
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000167 return makeString(m_currentMatchData.selector, "?", m_currentMatchData.url, ":", String::number(m_currentMatchData.lineNumber));
168}
169
170inline void SelectorProfile::startSelector(const CSSStyleRule* rule)
171{
172 m_currentMatchData.selector = rule->selectorText();
173 CSSStyleSheet* styleSheet = rule->parentStyleSheet();
174 String url = emptyString();
175 if (styleSheet) {
176 url = InspectorStyleSheet::styleSheetURL(styleSheet);
177 if (url.isEmpty())
antti@apple.comfe126eb2012-04-25 22:42:47 +0000178 url = InspectorDOMAgent::documentURLString(styleSheet->ownerDocument());
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000179 }
180 m_currentMatchData.url = url;
antti@apple.com972c0822012-02-28 09:38:51 +0000181 m_currentMatchData.lineNumber = rule->styleRule()->sourceLine();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000182 m_currentMatchData.startTime = WTF::currentTimeMS();
183}
184
185inline void SelectorProfile::commitSelector(bool matched)
186{
187 double matchTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
188 m_totalMatchingTimeMs += matchTimeMs;
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000189
caio.oliveira@openbossa.org4c11ee02012-03-29 18:48:23 +0000190 RuleMatchingStatsMap::AddResult result = m_ruleMatchingStats.add(makeKey(), RuleMatchingStats(m_currentMatchData, matchTimeMs, 1, matched ? 1 : 0));
191 if (!result.isNewEntry) {
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000192 result.iterator->value.totalTime += matchTimeMs;
193 result.iterator->value.hits += 1;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000194 if (matched)
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000195 result.iterator->value.matches += 1;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000196 }
197}
198
199inline void SelectorProfile::commitSelectorTime()
200{
201 double processingTimeMs = WTF::currentTimeMS() - m_currentMatchData.startTime;
202 m_totalMatchingTimeMs += processingTimeMs;
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000203
204 RuleMatchingStatsMap::iterator it = m_ruleMatchingStats.find(makeKey());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000205 if (it == m_ruleMatchingStats.end())
206 return;
207
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000208 it->value.totalTime += processingTimeMs;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000209}
210
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000211PassRefPtr<TypeBuilder::CSS::SelectorProfile> SelectorProfile::toInspectorObject() const
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000212{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000213 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry> > selectorProfileData = TypeBuilder::Array<TypeBuilder::CSS::SelectorProfileEntry>::create();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000214 for (RuleMatchingStatsMap::const_iterator it = m_ruleMatchingStats.begin(); it != m_ruleMatchingStats.end(); ++it) {
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000215 RefPtr<TypeBuilder::CSS::SelectorProfileEntry> entry = TypeBuilder::CSS::SelectorProfileEntry::create()
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000216 .setSelector(it->value.selector)
217 .setUrl(it->value.url)
218 .setLineNumber(it->value.lineNumber)
219 .setTime(it->value.totalTime)
220 .setHitCount(it->value.hits)
221 .setMatchCount(it->value.matches);
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000222 selectorProfileData->addItem(entry.release());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000223 }
224
225 RefPtr<TypeBuilder::CSS::SelectorProfile> result = TypeBuilder::CSS::SelectorProfile::create()
226 .setTotalTime(totalMatchingTimeMs())
apavlov@chromium.org5ee19fd2012-01-11 15:14:44 +0000227 .setData(selectorProfileData);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000228 return result.release();
229}
230
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000231class UpdateRegionLayoutTask {
232public:
233 UpdateRegionLayoutTask(InspectorCSSAgent*);
234 void scheduleFor(WebKitNamedFlow*, int documentNodeId);
235 void unschedule(WebKitNamedFlow*);
236 void reset();
237 void onTimer(Timer<UpdateRegionLayoutTask>*);
238
239private:
240 InspectorCSSAgent* m_cssAgent;
241 Timer<UpdateRegionLayoutTask> m_timer;
242 HashMap<WebKitNamedFlow*, int> m_namedFlows;
243};
244
245UpdateRegionLayoutTask::UpdateRegionLayoutTask(InspectorCSSAgent* cssAgent)
246 : m_cssAgent(cssAgent)
247 , m_timer(this, &UpdateRegionLayoutTask::onTimer)
248{
249}
250
251void UpdateRegionLayoutTask::scheduleFor(WebKitNamedFlow* namedFlow, int documentNodeId)
252{
253 m_namedFlows.add(namedFlow, documentNodeId);
254
255 if (!m_timer.isActive())
256 m_timer.startOneShot(0);
257}
258
259void UpdateRegionLayoutTask::unschedule(WebKitNamedFlow* namedFlow)
260{
261 m_namedFlows.remove(namedFlow);
262}
263
264void UpdateRegionLayoutTask::reset()
265{
266 m_timer.stop();
267 m_namedFlows.clear();
268}
269
270void UpdateRegionLayoutTask::onTimer(Timer<UpdateRegionLayoutTask>*)
271{
272 // The timer is stopped on m_cssAgent destruction, so this method will never be called after m_cssAgent has been destroyed.
273 Vector<std::pair<WebKitNamedFlow*, int> > namedFlows;
274
275 for (HashMap<WebKitNamedFlow*, int>::iterator it = m_namedFlows.begin(), end = m_namedFlows.end(); it != end; ++it)
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000276 namedFlows.append(std::make_pair(it->key, it->value));
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000277
278 for (unsigned i = 0, size = namedFlows.size(); i < size; ++i) {
279 WebKitNamedFlow* namedFlow = namedFlows.at(i).first;
280 int documentNodeId = namedFlows.at(i).second;
281
282 if (m_namedFlows.contains(namedFlow)) {
283 m_cssAgent->regionLayoutUpdated(namedFlow, documentNodeId);
284 m_namedFlows.remove(namedFlow);
285 }
286 }
287
288 if (!m_namedFlows.isEmpty() && !m_timer.isActive())
289 m_timer.startOneShot(0);
290}
291
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000292class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action {
293 WTF_MAKE_NONCOPYABLE(StyleSheetAction);
294public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000295 StyleSheetAction(const String& name, InspectorStyleSheet* styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000296 : InspectorHistory::Action(name)
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000297 , m_styleSheet(styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000298 {
299 }
300
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000301protected:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000302 RefPtr<InspectorStyleSheet> m_styleSheet;
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000303};
304
305class InspectorCSSAgent::SetStyleSheetTextAction : public InspectorCSSAgent::StyleSheetAction {
306 WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction);
307public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000308 SetStyleSheetTextAction(InspectorStyleSheet* styleSheet, const String& text)
309 : InspectorCSSAgent::StyleSheetAction("SetStyleSheetText", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000310 , m_text(text)
311 {
312 }
313
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000314 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000315 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000316 if (!m_styleSheet->getText(&m_oldText))
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000317 return false;
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000318 return redo(ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000319 }
320
apavlov@chromium.orge4f065a2013-02-26 09:15:17 +0000321 virtual bool undo(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000322 {
apavlov@chromium.orge4f065a2013-02-26 09:15:17 +0000323 if (m_styleSheet->setText(m_oldText, ec)) {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000324 m_styleSheet->reparseStyleSheet(m_oldText);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000325 return true;
326 }
327 return false;
328 }
329
apavlov@chromium.orge4f065a2013-02-26 09:15:17 +0000330 virtual bool redo(ExceptionCode& ec)
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000331 {
apavlov@chromium.orge4f065a2013-02-26 09:15:17 +0000332 if (m_styleSheet->setText(m_text, ec)) {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000333 m_styleSheet->reparseStyleSheet(m_text);
334 return true;
335 }
336 return false;
337 }
338
pfeldman@chromium.orga1a70a42012-02-14 08:50:19 +0000339 virtual String mergeId()
340 {
341 return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data());
342 }
343
344 virtual void merge(PassOwnPtr<Action> action)
345 {
346 ASSERT(action->mergeId() == mergeId());
347
348 SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action.get());
349 m_text = other->m_text;
350 }
351
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000352private:
353 String m_text;
354 String m_oldText;
355};
356
357class InspectorCSSAgent::SetPropertyTextAction : public InspectorCSSAgent::StyleSheetAction {
358 WTF_MAKE_NONCOPYABLE(SetPropertyTextAction);
359public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000360 SetPropertyTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, const String& text, bool overwrite)
361 : InspectorCSSAgent::StyleSheetAction("SetPropertyText", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000362 , m_cssId(cssId)
363 , m_propertyIndex(propertyIndex)
364 , m_text(text)
365 , m_overwrite(overwrite)
366 {
367 }
368
369 virtual String toString()
370 {
371 return mergeId() + ": " + m_oldText + " -> " + m_text;
372 }
373
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000374 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000375 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000376 return redo(ec);
377 }
378
379 virtual bool undo(ExceptionCode& ec)
380 {
381 String placeholder;
382 return m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec);
383 }
384
385 virtual bool redo(ExceptionCode& ec)
386 {
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000387 String oldText;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000388 bool result = m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000389 m_oldText = oldText.stripWhiteSpace();
390 // FIXME: remove this once the model handles this case.
benjamin@webkit.org127cec2c2012-04-30 21:32:44 +0000391 if (!m_oldText.endsWith(';'))
abarth@webkit.org96a2c952012-08-31 01:25:43 +0000392 m_oldText.append(';');
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000393 return result;
394 }
395
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000396 virtual String mergeId()
397 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000398 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 +0000399 }
400
401 virtual void merge(PassOwnPtr<Action> action)
402 {
403 ASSERT(action->mergeId() == mergeId());
404
405 SetPropertyTextAction* other = static_cast<SetPropertyTextAction*>(action.get());
406 m_text = other->m_text;
407 }
408
409private:
410 InspectorCSSId m_cssId;
411 unsigned m_propertyIndex;
412 String m_text;
413 String m_oldText;
414 bool m_overwrite;
415};
416
417class InspectorCSSAgent::TogglePropertyAction : public InspectorCSSAgent::StyleSheetAction {
418 WTF_MAKE_NONCOPYABLE(TogglePropertyAction);
419public:
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000420 TogglePropertyAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, bool disable)
421 : InspectorCSSAgent::StyleSheetAction("ToggleProperty", styleSheet)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000422 , m_cssId(cssId)
423 , m_propertyIndex(propertyIndex)
424 , m_disable(disable)
425 {
426 }
427
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000428 virtual bool perform(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000429 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000430 return redo(ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000431 }
432
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000433 virtual bool undo(ExceptionCode& ec)
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000434 {
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000435 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec);
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000436 }
437
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000438 virtual bool redo(ExceptionCode& ec)
439 {
440 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec);
441 }
442
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000443private:
444 InspectorCSSId m_cssId;
445 unsigned m_propertyIndex;
446 bool m_disable;
447};
448
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000449class InspectorCSSAgent::SetRuleSelectorAction : public InspectorCSSAgent::StyleSheetAction {
450 WTF_MAKE_NONCOPYABLE(SetRuleSelectorAction);
451public:
452 SetRuleSelectorAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& selector)
453 : InspectorCSSAgent::StyleSheetAction("SetRuleSelector", styleSheet)
454 , m_cssId(cssId)
455 , m_selector(selector)
456 {
457 }
458
459 virtual bool perform(ExceptionCode& ec)
460 {
461 m_oldSelector = m_styleSheet->ruleSelector(m_cssId, ec);
462 if (ec)
463 return false;
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000464 return redo(ec);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000465 }
466
467 virtual bool undo(ExceptionCode& ec)
468 {
469 return m_styleSheet->setRuleSelector(m_cssId, m_oldSelector, ec);
470 }
471
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000472 virtual bool redo(ExceptionCode& ec)
473 {
474 return m_styleSheet->setRuleSelector(m_cssId, m_selector, ec);
475 }
476
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000477private:
478 InspectorCSSId m_cssId;
479 String m_selector;
480 String m_oldSelector;
481};
482
483class InspectorCSSAgent::AddRuleAction : public InspectorCSSAgent::StyleSheetAction {
484 WTF_MAKE_NONCOPYABLE(AddRuleAction);
485public:
486 AddRuleAction(InspectorStyleSheet* styleSheet, const String& selector)
487 : InspectorCSSAgent::StyleSheetAction("AddRule", styleSheet)
488 , m_selector(selector)
489 {
490 }
491
492 virtual bool perform(ExceptionCode& ec)
493 {
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000494 return redo(ec);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000495 }
496
497 virtual bool undo(ExceptionCode& ec)
498 {
499 return m_styleSheet->deleteRule(m_newId, ec);
500 }
501
pfeldman@chromium.orga9730c42012-02-15 09:12:15 +0000502 virtual bool redo(ExceptionCode& ec)
503 {
504 CSSStyleRule* cssStyleRule = m_styleSheet->addRule(m_selector, ec);
505 if (ec)
506 return false;
507 m_newId = m_styleSheet->ruleId(cssStyleRule);
508 return true;
509 }
510
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000511 InspectorCSSId newRuleId() { return m_newId; }
512
513private:
514 InspectorCSSId m_newId;
515 String m_selector;
516 String m_oldSelector;
517};
518
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000519// static
andreas.kling@nokia.comf04e49c2011-10-14 21:33:49 +0000520CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000521{
akling@apple.comc713db32012-11-22 03:45:40 +0000522 if (rule->type() != CSSRule::STYLE_RULE)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000523 return 0;
524 return static_cast<CSSStyleRule*>(rule);
525}
526
apavlov@chromium.orgc7e14332012-12-25 09:00:28 +0000527InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorCompositeState* state, InspectorDOMAgent* domAgent)
pfeldman@chromium.org2f44edb2011-11-29 14:43:10 +0000528 : InspectorBaseAgent<InspectorCSSAgent>("CSS", instrumentingAgents, state)
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000529 , m_frontend(0)
yurys@chromium.org29626f82011-03-04 15:15:45 +0000530 , m_domAgent(domAgent)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000531 , m_lastStyleSheetId(1)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000532{
yurys@chromium.orgd8e367c2011-02-21 14:38:24 +0000533 m_domAgent->setDOMListener(this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000534}
535
536InspectorCSSAgent::~InspectorCSSAgent()
537{
pfeldman@chromium.orgeccfccf2011-12-02 08:21:57 +0000538 ASSERT(!m_domAgent);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000539 reset();
540}
541
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000542void InspectorCSSAgent::setFrontend(InspectorFrontend* frontend)
543{
544 ASSERT(!m_frontend);
545 m_frontend = frontend->css();
546}
547
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000548void InspectorCSSAgent::clearFrontend()
549{
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000550 ASSERT(m_frontend);
551 m_frontend = 0;
apavlov@chromium.orgd63acd82012-09-13 08:41:26 +0000552 resetNonPersistentData();
commit-queue@webkit.org261bc862013-02-19 16:01:52 +0000553 String errorString;
554 stopSelectorProfilerImpl(&errorString, false);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000555}
556
pfeldman@chromium.orgeccfccf2011-12-02 08:21:57 +0000557void InspectorCSSAgent::discardAgent()
558{
559 m_domAgent->setDOMListener(0);
560 m_domAgent = 0;
561}
562
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000563void InspectorCSSAgent::restore()
564{
commit-queue@webkit.org27444d52012-12-24 16:45:04 +0000565 if (m_state->getBoolean(CSSAgentState::cssAgentEnabled)) {
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000566 ErrorString error;
567 enable(&error);
568 }
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000569 if (m_state->getBoolean(CSSAgentState::isSelectorProfiling)) {
570 String errorString;
571 startSelectorProfiler(&errorString);
572 }
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000573}
574
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000575void InspectorCSSAgent::reset()
576{
577 m_idToInspectorStyleSheet.clear();
578 m_cssStyleSheetToInspectorStyleSheet.clear();
579 m_nodeToInspectorStyleSheet.clear();
580 m_documentToInspectorStyleSheet.clear();
apavlov@chromium.orgd63acd82012-09-13 08:41:26 +0000581 resetNonPersistentData();
582}
583
584void InspectorCSSAgent::resetNonPersistentData()
585{
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000586 m_namedFlowCollectionsRequested.clear();
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000587 if (m_updateRegionLayoutTask)
588 m_updateRegionLayoutTask->reset();
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000589 resetPseudoStates();
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000590}
591
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000592void InspectorCSSAgent::enable(ErrorString*)
593{
commit-queue@webkit.org27444d52012-12-24 16:45:04 +0000594 m_state->setBoolean(CSSAgentState::cssAgentEnabled, true);
apavlov@chromium.orgd63acd82012-09-13 08:41:26 +0000595 m_instrumentingAgents->setInspectorCSSAgent(this);
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000596}
597
598void InspectorCSSAgent::disable(ErrorString*)
599{
apavlov@chromium.orgd63acd82012-09-13 08:41:26 +0000600 m_instrumentingAgents->setInspectorCSSAgent(0);
commit-queue@webkit.org27444d52012-12-24 16:45:04 +0000601 m_state->setBoolean(CSSAgentState::cssAgentEnabled, false);
apavlov@chromium.orgad517d02011-12-15 09:23:19 +0000602}
603
604void InspectorCSSAgent::mediaQueryResultChanged()
605{
606 if (m_frontend)
607 m_frontend->mediaQueryResultChanged();
608}
609
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000610void InspectorCSSAgent::didCreateNamedFlow(Document* document, WebKitNamedFlow* namedFlow)
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000611{
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000612 int documentNodeId = documentNodeWithRequestedFlowsId(document);
613 if (!documentNodeId)
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000614 return;
615
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000616 ErrorString errorString;
617 m_frontend->namedFlowCreated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId));
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000618}
619
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000620void InspectorCSSAgent::willRemoveNamedFlow(Document* document, WebKitNamedFlow* namedFlow)
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000621{
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000622 int documentNodeId = documentNodeWithRequestedFlowsId(document);
623 if (!documentNodeId)
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000624 return;
625
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000626 if (m_updateRegionLayoutTask)
627 m_updateRegionLayoutTask->unschedule(namedFlow);
628
629 m_frontend->namedFlowRemoved(documentNodeId, namedFlow->name().string());
630}
631
632void InspectorCSSAgent::didUpdateRegionLayout(Document* document, WebKitNamedFlow* namedFlow)
633{
634 int documentNodeId = documentNodeWithRequestedFlowsId(document);
635 if (!documentNodeId)
636 return;
637
638 if (!m_updateRegionLayoutTask)
639 m_updateRegionLayoutTask = adoptPtr(new UpdateRegionLayoutTask(this));
640 m_updateRegionLayoutTask->scheduleFor(namedFlow, documentNodeId);
641}
642
643void InspectorCSSAgent::regionLayoutUpdated(WebKitNamedFlow* namedFlow, int documentNodeId)
644{
645 if (namedFlow->flowState() == WebKitNamedFlow::FlowStateNull)
646 return;
647
648 ErrorString errorString;
649 RefPtr<WebKitNamedFlow> protector(namedFlow);
650
651 m_frontend->regionLayoutUpdated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId));
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000652}
653
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000654bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoType pseudoType)
655{
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000656 if (m_nodeIdToForcedPseudoState.isEmpty())
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000657 return false;
658
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000659 int nodeId = m_domAgent->boundNodeId(element);
660 if (!nodeId)
661 return false;
662
663 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
664 if (it == m_nodeIdToForcedPseudoState.end())
665 return false;
666
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000667 unsigned forcedPseudoState = it->value;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000668 switch (pseudoType) {
669 case CSSSelector::PseudoActive:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000670 return forcedPseudoState & PseudoActive;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000671 case CSSSelector::PseudoFocus:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000672 return forcedPseudoState & PseudoFocus;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000673 case CSSSelector::PseudoHover:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000674 return forcedPseudoState & PseudoHover;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000675 case CSSSelector::PseudoVisited:
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +0000676 return forcedPseudoState & PseudoVisited;
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +0000677 default:
678 return false;
679 }
680}
681
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000682void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> >& matchedCSSRules, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> >& pseudoIdMatches, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> >& inheritedEntries)
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000683{
684 Element* element = elementForId(errorString, nodeId);
685 if (!element)
686 return;
687
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000688 // Matched rules.
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000689 StyleResolver* styleResolver = element->ownerDocument()->styleResolver();
690 RefPtr<CSSRuleList> matchedRules = styleResolver->styleRulesForElement(element, StyleResolver::AllCSSRules);
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000691 matchedCSSRules = buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element);
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000692
693 // Pseudo elements.
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000694 if (!includePseudo || *includePseudo) {
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000695 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches> > pseudoElements = TypeBuilder::Array<TypeBuilder::CSS::PseudoIdMatches>::create();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000696 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 +0000697 RefPtr<CSSRuleList> matchedRules = styleResolver->pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules);
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000698 if (matchedRules && matchedRules->length()) {
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000699 RefPtr<TypeBuilder::CSS::PseudoIdMatches> matches = TypeBuilder::CSS::PseudoIdMatches::create()
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000700 .setPseudoId(static_cast<int>(pseudoId))
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000701 .setMatches(buildArrayForMatchedRuleList(matchedRules.get(), styleResolver, element));
702 pseudoElements->addItem(matches.release());
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000703 }
704 }
705
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000706 pseudoIdMatches = pseudoElements.release();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000707 }
708
709 // Inherited styles.
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000710 if (!includeInherited || *includeInherited) {
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000711 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry> > entries = TypeBuilder::Array<TypeBuilder::CSS::InheritedStyleEntry>::create();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000712 Element* parentElement = element->parentElement();
713 while (parentElement) {
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000714 StyleResolver* parentStyleResolver = parentElement->ownerDocument()->styleResolver();
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +0000715 RefPtr<CSSRuleList> parentMatchedRules = parentStyleResolver->styleRulesForElement(parentElement, StyleResolver::AllCSSRules);
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000716 RefPtr<TypeBuilder::CSS::InheritedStyleEntry> entry = TypeBuilder::CSS::InheritedStyleEntry::create()
717 .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules.get(), styleResolver, parentElement));
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000718 if (parentElement->style() && parentElement->style()->length()) {
719 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement);
720 if (styleSheet)
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000721 entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0))));
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000722 }
723
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000724 entries->addItem(entry.release());
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000725 parentElement = parentElement->parentElement();
726 }
727
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +0000728 inheritedEntries = entries.release();
apavlov@chromium.orgd35f1492011-11-21 12:19:52 +0000729 }
730}
731
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000732void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<TypeBuilder::CSS::CSSStyle>& attributesStyle)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000733{
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000734 Element* element = elementForId(errorString, nodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000735 if (!element)
736 return;
737
738 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element);
739 if (!styleSheet)
740 return;
741
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000742 inlineStyle = styleSheet->buildObjectForStyle(element->style());
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000743 RefPtr<TypeBuilder::CSS::CSSStyle> attributes = buildObjectForAttributesStyle(element);
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +0000744 attributesStyle = attributes ? attributes.release() : 0;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000745}
746
apavlov@chromium.orgd728ecd2012-08-13 09:06:15 +0000747void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSComputedStyleProperty> >& style)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000748{
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +0000749 Element* element = elementForId(errorString, nodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000750 if (!element)
751 return;
752
antti@apple.comac019f32012-02-10 18:22:24 +0000753 RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = CSSComputedStyleDeclaration::create(element, true);
yurys@chromium.org418f91f2010-12-24 17:51:25 +0000754 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, 0);
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000755 style = inspectorStyle->buildArrayForComputedStyle();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000756}
757
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000758void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader> >& styleInfos)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000759{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000760 styleInfos = TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>::create();
commit-queue@webkit.org261bc862013-02-19 16:01:52 +0000761 Vector<Document*> documents = m_domAgent->documents();
762 for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) {
763 StyleSheetList* list = (*it)->styleSheets();
764 for (unsigned i = 0; i < list->length(); ++i) {
765 StyleSheet* styleSheet = list->item(i);
766 if (styleSheet->isCSSStyleSheet())
767 collectStyleSheets(static_cast<CSSStyleSheet*>(styleSheet), styleInfos.get());
768 }
769 }
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000770}
771
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000772void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<TypeBuilder::CSS::CSSStyleSheetBody>& styleSheetObject)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000773{
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000774 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000775 if (!inspectorStyleSheet)
776 return;
777
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000778 styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000779}
780
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000781void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result)
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000782{
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000783 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000784 if (!inspectorStyleSheet)
785 return;
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000786
pfeldman@chromium.org94451152012-02-07 17:00:32 +0000787 inspectorStyleSheet->getText(result);
pfeldman@chromium.org4ee21ff2010-11-24 10:11:39 +0000788}
789
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000790void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000791{
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000792 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId);
793 if (!inspectorStyleSheet)
794 return;
795
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000796 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000797 m_domAgent->history()->perform(adoptPtr(new SetStyleSheetTextAction(inspectorStyleSheet, text)), ec);
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000798 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000799}
800
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000801void 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 +0000802{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000803 InspectorCSSId compoundId(fullStyleId);
804 ASSERT(!compoundId.isEmpty());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000805
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000806 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000807 if (!inspectorStyleSheet)
808 return;
809
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000810 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000811 bool success = m_domAgent->history()->perform(adoptPtr(new SetPropertyTextAction(inspectorStyleSheet, compoundId, propertyIndex, text, overwrite)), ec);
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000812 if (success)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000813 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000814 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000815}
816
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000817void 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 +0000818{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000819 InspectorCSSId compoundId(fullStyleId);
820 ASSERT(!compoundId.isEmpty());
821
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000822 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000823 if (!inspectorStyleSheet)
824 return;
825
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000826 ExceptionCode ec = 0;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000827 bool success = m_domAgent->history()->perform(adoptPtr(new TogglePropertyAction(inspectorStyleSheet, compoundId, propertyIndex, disable)), ec);
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000828 if (success)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000829 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId));
pfeldman@chromium.orgb5db6a12012-02-10 13:15:12 +0000830 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000831}
832
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000833void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000834{
apavlov@chromium.orgfc8a58c2010-10-22 15:04:52 +0000835 InspectorCSSId compoundId(fullRuleId);
836 ASSERT(!compoundId.isEmpty());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000837
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +0000838 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000839 if (!inspectorStyleSheet)
840 return;
841
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000842 ExceptionCode ec = 0;
843 bool success = m_domAgent->history()->perform(adoptPtr(new SetRuleSelectorAction(inspectorStyleSheet, compoundId, selector)), ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000844
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000845 if (success)
846 result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId));
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000847 *errorString = InspectorDOMAgent::toErrorString(ec);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000848}
849
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000850void InspectorCSSAgent::addRule(ErrorString* errorString, const int contextNodeId, const String& selector, RefPtr<TypeBuilder::CSS::CSSRule>& result)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000851{
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000852 Node* node = m_domAgent->assertNode(errorString, contextNodeId);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000853 if (!node)
854 return;
855
856 InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(node->document(), true);
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000857 if (!inspectorStyleSheet) {
858 *errorString = "No target stylesheet found";
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +0000859 return;
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000860 }
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +0000861
pfeldman@chromium.org8ef57362012-02-13 13:12:15 +0000862 ExceptionCode ec = 0;
863 OwnPtr<AddRuleAction> action = adoptPtr(new AddRuleAction(inspectorStyleSheet, selector));
864 AddRuleAction* rawAction = action.get();
865 bool success = m_domAgent->history()->perform(action.release(), ec);
866 if (!success) {
867 *errorString = InspectorDOMAgent::toErrorString(ec);
868 return;
869 }
870
871 InspectorCSSId ruleId = rawAction->newRuleId();
872 CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId);
873 result = inspectorStyleSheet->buildObjectForRule(rule);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000874}
875
pfeldman@chromium.orga7128942012-07-25 13:48:47 +0000876void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> >& cssProperties)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000877{
pfeldman@chromium.orga7128942012-07-25 13:48:47 +0000878 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo> > properties = TypeBuilder::Array<TypeBuilder::CSS::CSSPropertyInfo>::create();
879 for (int i = firstCSSProperty; i <= lastCSSProperty; ++i) {
880 CSSPropertyID id = convertToCSSPropertyID(i);
881 RefPtr<TypeBuilder::CSS::CSSPropertyInfo> property = TypeBuilder::CSS::CSSPropertyInfo::create()
benjamin@webkit.org5ab707f2012-08-17 21:24:15 +0000882 .setName(getPropertyNameString(id));
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000883
pfeldman@chromium.orga7128942012-07-25 13:48:47 +0000884 const StylePropertyShorthand& shorthand = shorthandForProperty(id);
885 if (!shorthand.length()) {
886 properties->addItem(property.release());
887 continue;
888 }
889 RefPtr<TypeBuilder::Array<String> > longhands = TypeBuilder::Array<String>::create();
890 for (unsigned j = 0; j < shorthand.length(); ++j) {
891 CSSPropertyID longhandID = shorthand.properties()[j];
benjamin@webkit.org5ab707f2012-08-17 21:24:15 +0000892 longhands->addItem(getPropertyNameString(longhandID));
pfeldman@chromium.orga7128942012-07-25 13:48:47 +0000893 }
894 property->setLonghands(longhands);
895 properties->addItem(property.release());
896 }
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000897 cssProperties = properties.release();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000898}
899
apavlov@chromium.orgd728ecd2012-08-13 09:06:15 +0000900void InspectorCSSAgent::forcePseudoState(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses)
901{
902 Element* element = m_domAgent->assertElement(errorString, nodeId);
903 if (!element)
904 return;
905
906 unsigned forcedPseudoState = computePseudoClassMask(forcedPseudoClasses.get());
907 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId);
benjamin@webkit.orgee554052012-10-07 23:12:07 +0000908 unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->value;
apavlov@chromium.orgd728ecd2012-08-13 09:06:15 +0000909 bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState;
910 if (!needStyleRecalc)
911 return;
912
913 if (forcedPseudoState)
914 m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState);
915 else
916 m_nodeIdToForcedPseudoState.remove(nodeId);
917 element->ownerDocument()->styleResolverChanged(RecalcStyleImmediately);
918}
919
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +0000920void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int documentNodeId, RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> >& result)
commit-queue@webkit.org6f859512012-07-20 12:34:58 +0000921{
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +0000922 Document* document = m_domAgent->assertDocument(errorString, documentNodeId);
commit-queue@webkit.org6f859512012-07-20 12:34:58 +0000923 if (!document)
924 return;
925
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +0000926 m_namedFlowCollectionsRequested.add(documentNodeId);
commit-queue@webkit.org65563d42012-09-12 12:07:24 +0000927
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +0000928 Vector<RefPtr<WebKitNamedFlow> > namedFlowsVector = document->namedFlows()->namedFlows();
929 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::NamedFlow> > namedFlows = TypeBuilder::Array<TypeBuilder::CSS::NamedFlow>::create();
commit-queue@webkit.org5c25fc42012-08-06 16:39:56 +0000930
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +0000931 for (Vector<RefPtr<WebKitNamedFlow> >::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it)
932 namedFlows->addItem(buildObjectForNamedFlow(errorString, it->get(), documentNodeId));
commit-queue@webkit.org6f859512012-07-20 12:34:58 +0000933
934 result = namedFlows.release();
935}
936
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000937void InspectorCSSAgent::startSelectorProfiler(ErrorString*)
938{
939 m_currentSelectorProfile = adoptPtr(new SelectorProfile());
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000940 m_state->setBoolean(CSSAgentState::isSelectorProfiling, true);
941}
942
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000943void InspectorCSSAgent::stopSelectorProfiler(ErrorString* errorString, RefPtr<TypeBuilder::CSS::SelectorProfile>& result)
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000944{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000945 result = stopSelectorProfilerImpl(errorString, true);
loislo@chromium.orgf37187e2011-12-21 05:51:31 +0000946}
947
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000948PassRefPtr<TypeBuilder::CSS::SelectorProfile> InspectorCSSAgent::stopSelectorProfilerImpl(ErrorString*, bool needProfile)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000949{
950 if (!m_state->getBoolean(CSSAgentState::isSelectorProfiling))
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000951 return 0;
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000952 m_state->setBoolean(CSSAgentState::isSelectorProfiling, false);
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000953 RefPtr<TypeBuilder::CSS::SelectorProfile> result;
954 if (m_frontend && needProfile)
955 result = m_currentSelectorProfile->toInspectorObject();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000956 m_currentSelectorProfile.clear();
apavlov@chromium.org47bfc332012-03-26 14:04:50 +0000957 return result.release();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000958}
959
apavlov@chromium.orgd749e4c2012-12-11 14:06:01 +0000960void InspectorCSSAgent::willMatchRule(StyleRule* rule, StyleResolver* styleResolver)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000961{
dino@apple.com018d5e42013-02-11 21:34:50 +0000962// printf("InspectorCSSAgent::willMatchRule %s\n", rule->selectorList().selectorsText().utf8().data());
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000963 if (m_currentSelectorProfile)
hayato@chromium.org78f751a2013-01-31 05:03:58 +0000964 m_currentSelectorProfile->startSelector(styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule, styleResolver->document()->styleSheetCollection()));
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000965}
966
967void InspectorCSSAgent::didMatchRule(bool matched)
968{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000969 if (m_currentSelectorProfile)
970 m_currentSelectorProfile->commitSelector(matched);
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000971}
972
apavlov@chromium.orgd749e4c2012-12-11 14:06:01 +0000973void InspectorCSSAgent::willProcessRule(StyleRule* rule, StyleResolver* styleResolver)
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000974{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000975 if (m_currentSelectorProfile)
hayato@chromium.org78f751a2013-01-31 05:03:58 +0000976 m_currentSelectorProfile->startSelector(styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule, styleResolver->document()->styleSheetCollection()));
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000977}
978
979void InspectorCSSAgent::didProcessRule()
980{
apavlov@chromium.org1ed8ba32012-01-19 16:39:55 +0000981 if (m_currentSelectorProfile)
982 m_currentSelectorProfile->commitSelectorTime();
apavlov@chromium.orgba905e82011-12-19 15:14:14 +0000983}
984
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000985InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element)
986{
987 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
988 if (it == m_nodeToInspectorStyleSheet.end()) {
989 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : 0;
990 if (!style)
991 return 0;
992
993 String newStyleSheetId = String::number(m_lastStyleSheetId++);
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +0000994 RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(m_domAgent->pageAgent(), newStyleSheetId, element, TypeBuilder::CSS::StyleSheetOrigin::Regular, this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +0000995 m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet);
996 m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet);
997 return inspectorStyleSheet.get();
998 }
999
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001000 return it->value.get();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001001}
1002
pfeldman@chromium.org7e420b52011-03-21 07:54:32 +00001003Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001004{
1005 Node* node = m_domAgent->nodeForId(nodeId);
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +00001006 if (!node) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +00001007 *errorString = "No node with given id found";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +00001008 return 0;
1009 }
1010 if (node->nodeType() != Node::ELEMENT_NODE) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +00001011 *errorString = "Not an element node";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +00001012 return 0;
1013 }
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001014 return toElement(node);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001015}
1016
commit-queue@webkit.org65563d42012-09-12 12:07:24 +00001017int InspectorCSSAgent::documentNodeWithRequestedFlowsId(Document* document)
1018{
1019 int documentNodeId = m_domAgent->boundNodeId(document);
1020 if (!documentNodeId || !m_namedFlowCollectionsRequested.contains(documentNodeId))
1021 return 0;
1022
1023 return documentNodeId;
1024}
1025
commit-queue@webkit.org261bc862013-02-19 16:01:52 +00001026void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, TypeBuilder::Array<TypeBuilder::CSS::CSSStyleSheetHeader>* result)
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +00001027{
1028 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet));
commit-queue@webkit.org261bc862013-02-19 16:01:52 +00001029 result->addItem(inspectorStyleSheet->buildObjectForStyleSheetInfo());
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +00001030 for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) {
andreas.kling@nokia.com1678e2b2011-10-14 18:36:31 +00001031 CSSRule* rule = styleSheet->item(i);
akling@apple.comc713db32012-11-22 03:45:40 +00001032 if (rule->type() == CSSRule::IMPORT_RULE) {
andreas.kling@nokia.com1678e2b2011-10-14 18:36:31 +00001033 CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet();
1034 if (importedStyleSheet)
1035 collectStyleSheets(importedStyleSheet, result);
apavlov@chromium.orgbe789cf2011-05-18 13:32:07 +00001036 }
1037 }
1038}
1039
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001040InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet)
1041{
1042 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet);
1043 if (!inspectorStyleSheet) {
1044 String id = String::number(m_lastStyleSheetId++);
antti@apple.comfe126eb2012-04-25 22:42:47 +00001045 Document* document = styleSheet->ownerDocument();
pfeldman@chromium.orgf9adb6a2012-05-24 14:35:50 +00001046 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001047 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
1048 m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet);
1049 }
1050 return inspectorStyleSheet.get();
1051}
1052
1053InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent)
1054{
1055 if (!document) {
1056 ASSERT(!createIfAbsent);
1057 return 0;
1058 }
1059
1060 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document);
1061 if (inspectorStyleSheet || !createIfAbsent)
1062 return inspectorStyleSheet.get();
1063
1064 ExceptionCode ec = 0;
1065 RefPtr<Element> styleElement = document->createElement("style", ec);
1066 if (!ec)
1067 styleElement->setAttribute("type", "text/css", ec);
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +00001068 if (!ec) {
1069 ContainerNode* targetNode;
1070 // HEAD is absent in ImageDocuments, for example.
1071 if (document->head())
1072 targetNode = document->head();
1073 else if (document->body())
1074 targetNode = document->body();
1075 else
1076 return 0;
apavlov@chromium.org31442e82012-03-05 10:44:40 +00001077
1078 InlineStyleOverrideScope overrideScope(document);
apavlov@chromium.orgd41cebd2011-01-20 15:46:28 +00001079 targetNode->appendChild(styleElement, ec);
1080 }
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001081 if (ec)
1082 return 0;
commit-queue@webkit.org261bc862013-02-19 16:01:52 +00001083 StyleSheetList* styleSheets = document->styleSheets();
1084 StyleSheet* styleSheet = styleSheets->item(styleSheets->length() - 1);
1085 if (!styleSheet || !styleSheet->isCSSStyleSheet())
1086 return 0;
1087 CSSStyleSheet* cssStyleSheet = static_cast<CSSStyleSheet*>(styleSheet);
1088 String id = String::number(m_lastStyleSheetId++);
1089 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, cssStyleSheet, TypeBuilder::CSS::StyleSheetOrigin::Inspector, InspectorDOMAgent::documentURLString(document), this);
1090 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet);
1091 m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet);
1092 m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet);
1093 return inspectorStyleSheet.get();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001094}
1095
pfeldman@chromium.org8f286ef2011-04-15 12:39:32 +00001096InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001097{
1098 IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId);
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +00001099 if (it == m_idToInspectorStyleSheet.end()) {
caseq@chromium.orgc2485692011-03-31 15:21:33 +00001100 *errorString = "No style sheet with given id found";
pfeldman@chromium.orge573fa32011-03-17 18:10:15 +00001101 return 0;
1102 }
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001103 return it->value.get();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001104}
1105
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +00001106TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001107{
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +00001108 TypeBuilder::CSS::StyleSheetOrigin::Enum origin = TypeBuilder::CSS::StyleSheetOrigin::Regular;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001109 if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty())
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +00001110 origin = TypeBuilder::CSS::StyleSheetOrigin::User_agent;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001111 else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document")
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +00001112 origin = TypeBuilder::CSS::StyleSheetOrigin::User;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001113 else {
1114 InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false);
1115 if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet())
apavlov@chromium.org0c1c3732012-05-25 16:24:48 +00001116 origin = TypeBuilder::CSS::StyleSheetOrigin::Inspector;
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001117 }
1118 return origin;
1119}
1120
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001121PassRefPtr<TypeBuilder::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule, StyleResolver* styleResolver)
1122{
1123 if (!rule)
1124 return 0;
1125
1126 // CSSRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available.
1127 // Since the inspector wants to walk the parent chain, we construct the full wrappers here.
1128 // FIXME: This could be factored better. StyleResolver::styleRulesForElement should return a StyleRule vector, not a CSSRuleList.
1129 if (!rule->parentStyleSheet()) {
hayato@chromium.org78f751a2013-01-31 05:03:58 +00001130 rule = styleResolver->inspectorCSSOMWrappers().getWrapperForRuleInSheets(rule->styleRule(), styleResolver->document()->styleSheetCollection());
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001131 if (!rule)
1132 return 0;
1133 }
commit-queue@webkit.org261bc862013-02-19 16:01:52 +00001134 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet());
1135 return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule) : 0;
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001136}
1137
alexis.menard@openbossa.org31b77cb2012-04-24 23:51:22 +00001138PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001139{
apavlov@chromium.org47bfc332012-03-26 14:04:50 +00001140 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::CSSRule> > result = TypeBuilder::Array<TypeBuilder::CSS::CSSRule>::create();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001141 if (!ruleList)
1142 return result.release();
1143
1144 for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
1145 CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001146 RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver);
1147 if (!ruleObject)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001148 continue;
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001149 result->addItem(ruleObject);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001150 }
1151 return result.release();
1152}
1153
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001154PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > InspectorCSSAgent::buildArrayForMatchedRuleList(CSSRuleList* ruleList, StyleResolver* styleResolver, Element* element)
1155{
1156 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::RuleMatch> > result = TypeBuilder::Array<TypeBuilder::CSS::RuleMatch>::create();
1157 if (!ruleList)
1158 return result.release();
1159
1160 for (unsigned i = 0, size = ruleList->length(); i < size; ++i) {
1161 CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i));
1162 RefPtr<TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule, styleResolver);
1163 if (!ruleObject)
1164 continue;
1165 RefPtr<TypeBuilder::Array<int> > matchingSelectors = TypeBuilder::Array<int>::create();
1166 const CSSSelectorList& selectorList = rule->styleRule()->selectorList();
1167 long index = 0;
akling@apple.com140a7712013-01-23 10:26:04 +00001168 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) {
mkwst@chromium.org33cdf432013-02-08 14:21:48 +00001169 bool matched = element->webkitMatchesSelector(selector->selectorText(), IGNORE_EXCEPTION);
apavlov@chromium.orgcecb43f2012-09-25 08:05:18 +00001170 if (matched)
1171 matchingSelectors->addItem(index);
1172 ++index;
1173 }
1174 RefPtr<TypeBuilder::CSS::RuleMatch> match = TypeBuilder::CSS::RuleMatch::create()
1175 .setRule(ruleObject)
1176 .setMatchingSelectors(matchingSelectors);
1177 result->addItem(match);
1178 }
1179
1180 return result;
1181}
1182
apavlov@chromium.org47bfc332012-03-26 14:04:50 +00001183PassRefPtr<TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element)
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001184{
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001185 if (!element->isStyledElement())
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001186 return 0;
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001187
kling@webkit.org569556d2012-11-12 23:52:12 +00001188 const StylePropertySet* attributeStyle = static_cast<StyledElement*>(element)->presentationAttributeStyle();
commit-queue@webkit.org844de9e2012-11-05 10:47:35 +00001189 if (!attributeStyle)
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001190 return 0;
kling@webkit.org119bc4e2012-02-04 12:24:19 +00001191
commit-queue@webkit.org844de9e2012-11-05 10:47:35 +00001192 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), const_cast<StylePropertySet*>(attributeStyle)->ensureCSSStyleDeclaration(), 0);
apavlov@chromium.org0d4c01a2012-02-09 12:41:37 +00001193 return inspectorStyle->buildObjectForStyle();
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001194}
1195
commit-queue@webkit.orge2bb32c2012-08-10 09:58:35 +00001196PassRefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > InspectorCSSAgent::buildArrayForRegions(ErrorString* errorString, PassRefPtr<NodeList> regionList, int documentNodeId)
1197{
1198 RefPtr<TypeBuilder::Array<TypeBuilder::CSS::Region> > regions = TypeBuilder::Array<TypeBuilder::CSS::Region>::create();
1199
1200 for (unsigned i = 0; i < regionList->length(); ++i) {
1201 TypeBuilder::CSS::Region::RegionOverset::Enum regionOverset;
1202
1203 switch (toElement(regionList->item(i))->renderRegion()->regionState()) {
1204 case RenderRegion::RegionFit:
1205 regionOverset = TypeBuilder::CSS::Region::RegionOverset::Fit;
1206 break;
1207 case RenderRegion::RegionEmpty:
1208 regionOverset = TypeBuilder::CSS::Region::RegionOverset::Empty;
1209 break;
1210 case RenderRegion::RegionOverset:
1211 regionOverset = TypeBuilder::CSS::Region::RegionOverset::Overset;
1212 break;
1213 case RenderRegion::RegionUndefined:
1214 continue;
1215 default:
1216 ASSERT_NOT_REACHED();
1217 continue;
1218 }
1219
1220 RefPtr<TypeBuilder::CSS::Region> region = TypeBuilder::CSS::Region::create()
1221 .setRegionOverset(regionOverset)
1222 // documentNodeId was previously asserted
1223 .setNodeId(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, regionList->item(i)));
1224
1225 regions->addItem(region);
1226 }
1227
1228 return regions.release();
1229}
1230
1231PassRefPtr<TypeBuilder::CSS::NamedFlow> InspectorCSSAgent::buildObjectForNamedFlow(ErrorString* errorString, WebKitNamedFlow* webkitNamedFlow, int documentNodeId)
1232{
1233 RefPtr<NodeList> contentList = webkitNamedFlow->getContent();
1234 RefPtr<TypeBuilder::Array<int> > content = TypeBuilder::Array<int>::create();
1235
1236 for (unsigned i = 0; i < contentList->length(); ++i) {
1237 // documentNodeId was previously asserted
1238 content->addItem(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, contentList->item(i)));
1239 }
1240
1241 RefPtr<TypeBuilder::CSS::NamedFlow> namedFlow = TypeBuilder::CSS::NamedFlow::create()
1242 .setDocumentNodeId(documentNodeId)
1243 .setName(webkitNamedFlow->name().string())
1244 .setOverset(webkitNamedFlow->overset())
1245 .setContent(content)
1246 .setRegions(buildArrayForRegions(errorString, webkitNamedFlow->getRegions(), documentNodeId));
1247
1248 return namedFlow.release();
1249}
1250
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001251void InspectorCSSAgent::didRemoveDocument(Document* document)
1252{
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +00001253 if (document)
1254 m_documentToInspectorStyleSheet.remove(document);
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001255}
1256
1257void InspectorCSSAgent::didRemoveDOMNode(Node* node)
1258{
apavlov@chromium.org6dbb39d2010-11-10 17:12:45 +00001259 if (!node)
1260 return;
1261
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001262 int nodeId = m_domAgent->boundNodeId(node);
1263 if (nodeId)
1264 m_nodeIdToForcedPseudoState.remove(nodeId);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001265
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001266 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node);
1267 if (it == m_nodeToInspectorStyleSheet.end())
1268 return;
1269
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001270 m_idToInspectorStyleSheet.remove(it->value->id());
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001271 m_nodeToInspectorStyleSheet.remove(node);
1272}
1273
apavlov@chromium.org93e800a2010-12-24 16:39:32 +00001274void InspectorCSSAgent::didModifyDOMAttr(Element* element)
1275{
1276 if (!element)
1277 return;
1278
1279 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element);
1280 if (it == m_nodeToInspectorStyleSheet.end())
1281 return;
1282
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001283 it->value->didModifyElementAttribute();
apavlov@chromium.org93e800a2010-12-24 16:39:32 +00001284}
1285
pfeldman@chromium.orga1a70a42012-02-14 08:50:19 +00001286void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheet* styleSheet)
1287{
1288 if (m_frontend)
1289 m_frontend->styleSheetChanged(styleSheet->id());
1290}
1291
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001292void InspectorCSSAgent::resetPseudoStates()
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001293{
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001294 HashSet<Document*> documentsToChange;
1295 for (NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.begin(), end = m_nodeIdToForcedPseudoState.end(); it != end; ++it) {
benjamin@webkit.orgee554052012-10-07 23:12:07 +00001296 Element* element = toElement(m_domAgent->nodeForId(it->key));
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001297 if (element && element->ownerDocument())
1298 documentsToChange.add(element->ownerDocument());
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001299 }
apavlov@chromium.orgcc4fd4a2012-07-04 16:10:45 +00001300
1301 m_nodeIdToForcedPseudoState.clear();
1302 for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = documentsToChange.end(); it != end; ++it)
1303 (*it)->styleResolverChanged(RecalcStyleImmediately);
pfeldman@chromium.orgefb43862011-08-16 17:15:06 +00001304}
1305
apavlov@chromium.org8d79d7f2010-10-07 09:53:40 +00001306} // namespace WebCore
1307
1308#endif // ENABLE(INSPECTOR)