1/* 2 * Copyright (C) 2010, Google Inc. All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions 6 * are met: 7 * 1. Redistributions of source code must retain the above copyright 8 * notice, this list of conditions and the following disclaimer. 9 * 2. Redistributions in binary form must reproduce the above copyright 10 * notice, this list of conditions and the following disclaimer in the 11 * documentation and/or other materials provided with the distribution. 12 * 13 * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY 14 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 16 * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY 17 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 18 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 19 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON 20 * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 22 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23 */ 24 25#include "config.h" 26 27#if ENABLE(INSPECTOR) 28 29#include "InspectorCSSAgent.h" 30 31#include "CSSComputedStyleDeclaration.h" 32#include "CSSImportRule.h" 33#include "CSSPropertyNames.h" 34#include "CSSPropertySourceData.h" 35#include "CSSRule.h" 36#include "CSSRuleList.h" 37#include "CSSStyleRule.h" 38#include "CSSStyleSheet.h" 39#include "ContentSecurityPolicy.h" 40#include "DOMWindow.h" 41#include "ExceptionCodePlaceholder.h" 42#include "HTMLHeadElement.h" 43#include "HTMLStyleElement.h" 44#include "InspectorDOMAgent.h" 45#include "InspectorHistory.h" 46#include "InspectorWebTypeBuilders.h" 47#include "InstrumentingAgents.h" 48#include "NamedFlowCollection.h" 49#include "Node.h" 50#include "NodeList.h" 51#include "RenderNamedFlowFragment.h" 52#include "SVGStyleElement.h" 53#include "StyleProperties.h" 54#include "StylePropertyShorthand.h" 55#include "StyleResolver.h" 56#include "StyleRule.h" 57#include "StyleSheetList.h" 58#include "WebKitNamedFlow.h" 59#include <inspector/InspectorValues.h> 60#include <wtf/CurrentTime.h> 61#include <wtf/HashSet.h> 62#include <wtf/Ref.h> 63#include <wtf/Vector.h> 64#include <wtf/text/CString.h> 65#include <wtf/text/StringConcatenate.h> 66 67using namespace Inspector; 68 69namespace WebCore { 70 71enum ForcePseudoClassFlags { 72 PseudoClassNone = 0, 73 PseudoClassHover = 1 << 0, 74 PseudoClassFocus = 1 << 1, 75 PseudoClassActive = 1 << 2, 76 PseudoClassVisited = 1 << 3 77}; 78 79static unsigned computePseudoClassMask(InspectorArray* pseudoClassArray) 80{ 81 DEPRECATED_DEFINE_STATIC_LOCAL(String, active, (ASCIILiteral("active"))); 82 DEPRECATED_DEFINE_STATIC_LOCAL(String, hover, (ASCIILiteral("hover"))); 83 DEPRECATED_DEFINE_STATIC_LOCAL(String, focus, (ASCIILiteral("focus"))); 84 DEPRECATED_DEFINE_STATIC_LOCAL(String, visited, (ASCIILiteral("visited"))); 85 if (!pseudoClassArray || !pseudoClassArray->length()) 86 return PseudoClassNone; 87 88 unsigned result = PseudoClassNone; 89 for (size_t i = 0; i < pseudoClassArray->length(); ++i) { 90 RefPtr<InspectorValue> pseudoClassValue = pseudoClassArray->get(i); 91 String pseudoClass; 92 bool success = pseudoClassValue->asString(&pseudoClass); 93 if (!success) 94 continue; 95 if (pseudoClass == active) 96 result |= PseudoClassActive; 97 else if (pseudoClass == hover) 98 result |= PseudoClassHover; 99 else if (pseudoClass == focus) 100 result |= PseudoClassFocus; 101 else if (pseudoClass == visited) 102 result |= PseudoClassVisited; 103 } 104 105 return result; 106} 107 108class ChangeRegionOversetTask { 109public: 110 ChangeRegionOversetTask(InspectorCSSAgent*); 111 void scheduleFor(WebKitNamedFlow*, int documentNodeId); 112 void unschedule(WebKitNamedFlow*); 113 void reset(); 114 void timerFired(Timer<ChangeRegionOversetTask>&); 115 116private: 117 InspectorCSSAgent* m_cssAgent; 118 Timer<ChangeRegionOversetTask> m_timer; 119 HashMap<WebKitNamedFlow*, int> m_namedFlows; 120}; 121 122ChangeRegionOversetTask::ChangeRegionOversetTask(InspectorCSSAgent* cssAgent) 123 : m_cssAgent(cssAgent) 124 , m_timer(this, &ChangeRegionOversetTask::timerFired) 125{ 126} 127 128void ChangeRegionOversetTask::scheduleFor(WebKitNamedFlow* namedFlow, int documentNodeId) 129{ 130 m_namedFlows.add(namedFlow, documentNodeId); 131 132 if (!m_timer.isActive()) 133 m_timer.startOneShot(0); 134} 135 136void ChangeRegionOversetTask::unschedule(WebKitNamedFlow* namedFlow) 137{ 138 m_namedFlows.remove(namedFlow); 139} 140 141void ChangeRegionOversetTask::reset() 142{ 143 m_timer.stop(); 144 m_namedFlows.clear(); 145} 146 147void ChangeRegionOversetTask::timerFired(Timer<ChangeRegionOversetTask>&) 148{ 149 // The timer is stopped on m_cssAgent destruction, so this method will never be called after m_cssAgent has been destroyed. 150 for (HashMap<WebKitNamedFlow*, int>::iterator it = m_namedFlows.begin(), end = m_namedFlows.end(); it != end; ++it) 151 m_cssAgent->regionOversetChanged(it->key, it->value); 152 153 m_namedFlows.clear(); 154} 155 156class InspectorCSSAgent::StyleSheetAction : public InspectorHistory::Action { 157 WTF_MAKE_NONCOPYABLE(StyleSheetAction); 158public: 159 StyleSheetAction(const String& name, InspectorStyleSheet* styleSheet) 160 : InspectorHistory::Action(name) 161 , m_styleSheet(styleSheet) 162 { 163 } 164 165protected: 166 RefPtr<InspectorStyleSheet> m_styleSheet; 167}; 168 169class InspectorCSSAgent::SetStyleSheetTextAction final : public InspectorCSSAgent::StyleSheetAction { 170 WTF_MAKE_NONCOPYABLE(SetStyleSheetTextAction); 171public: 172 SetStyleSheetTextAction(InspectorStyleSheet* styleSheet, const String& text) 173 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("SetStyleSheetText"), styleSheet) 174 , m_text(text) 175 { 176 } 177 178 virtual bool perform(ExceptionCode& ec) override 179 { 180 if (!m_styleSheet->getText(&m_oldText)) 181 return false; 182 return redo(ec); 183 } 184 185 virtual bool undo(ExceptionCode& ec) override 186 { 187 if (m_styleSheet->setText(m_oldText, ec)) { 188 m_styleSheet->reparseStyleSheet(m_oldText); 189 return true; 190 } 191 return false; 192 } 193 194 virtual bool redo(ExceptionCode& ec) override 195 { 196 if (m_styleSheet->setText(m_text, ec)) { 197 m_styleSheet->reparseStyleSheet(m_text); 198 return true; 199 } 200 return false; 201 } 202 203 virtual String mergeId() override 204 { 205 return String::format("SetStyleSheetText %s", m_styleSheet->id().utf8().data()); 206 } 207 208 virtual void merge(std::unique_ptr<Action> action) override 209 { 210 ASSERT(action->mergeId() == mergeId()); 211 212 SetStyleSheetTextAction* other = static_cast<SetStyleSheetTextAction*>(action.get()); 213 m_text = other->m_text; 214 } 215 216private: 217 String m_text; 218 String m_oldText; 219}; 220 221class InspectorCSSAgent::SetStyleTextAction final : public InspectorCSSAgent::StyleSheetAction { 222 WTF_MAKE_NONCOPYABLE(SetStyleTextAction); 223public: 224 SetStyleTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& text) 225 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("SetStyleText"), styleSheet) 226 , m_cssId(cssId) 227 , m_text(text) 228 { 229 } 230 231 virtual bool perform(ExceptionCode& ec) override 232 { 233 return redo(ec); 234 } 235 236 virtual bool undo(ExceptionCode& ec) override 237 { 238 return m_styleSheet->setStyleText(m_cssId, m_oldText, nullptr, ec); 239 } 240 241 virtual bool redo(ExceptionCode& ec) override 242 { 243 return m_styleSheet->setStyleText(m_cssId, m_text, &m_oldText, ec); 244 } 245 246 virtual String mergeId() override 247 { 248 ASSERT(m_styleSheet->id() == m_cssId.styleSheetId()); 249 return String::format("SetStyleText %s:%u", m_styleSheet->id().utf8().data(), m_cssId.ordinal()); 250 } 251 252 virtual void merge(std::unique_ptr<Action> action) override 253 { 254 ASSERT(action->mergeId() == mergeId()); 255 256 SetStyleTextAction* other = static_cast<SetStyleTextAction*>(action.get()); 257 m_text = other->m_text; 258 } 259 260private: 261 InspectorCSSId m_cssId; 262 String m_text; 263 String m_oldText; 264}; 265 266class InspectorCSSAgent::SetPropertyTextAction final : public InspectorCSSAgent::StyleSheetAction { 267 WTF_MAKE_NONCOPYABLE(SetPropertyTextAction); 268public: 269 SetPropertyTextAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, const String& text, bool overwrite) 270 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("SetPropertyText"), styleSheet) 271 , m_cssId(cssId) 272 , m_propertyIndex(propertyIndex) 273 , m_text(text) 274 , m_overwrite(overwrite) 275 { 276 } 277 278 virtual String toString() override 279 { 280 return mergeId() + ": " + m_oldText + " -> " + m_text; 281 } 282 283 virtual bool perform(ExceptionCode& ec) override 284 { 285 return redo(ec); 286 } 287 288 virtual bool undo(ExceptionCode& ec) override 289 { 290 String placeholder; 291 return m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_overwrite ? m_oldText : "", true, &placeholder, ec); 292 } 293 294 virtual bool redo(ExceptionCode& ec) override 295 { 296 String oldText; 297 bool result = m_styleSheet->setPropertyText(m_cssId, m_propertyIndex, m_text, m_overwrite, &oldText, ec); 298 m_oldText = oldText.stripWhiteSpace(); 299 // FIXME: remove this once the model handles this case. 300 if (!m_oldText.endsWith(';')) 301 m_oldText.append(';'); 302 303 return result; 304 } 305 306 virtual String mergeId() override 307 { 308 return String::format("SetPropertyText %s:%u:%s", m_styleSheet->id().utf8().data(), m_propertyIndex, m_overwrite ? "true" : "false"); 309 } 310 311 virtual void merge(std::unique_ptr<Action> action) override 312 { 313 ASSERT(action->mergeId() == mergeId()); 314 315 SetPropertyTextAction* other = static_cast<SetPropertyTextAction*>(action.get()); 316 m_text = other->m_text; 317 } 318 319private: 320 InspectorCSSId m_cssId; 321 unsigned m_propertyIndex; 322 String m_text; 323 String m_oldText; 324 bool m_overwrite; 325}; 326 327class InspectorCSSAgent::TogglePropertyAction final : public InspectorCSSAgent::StyleSheetAction { 328 WTF_MAKE_NONCOPYABLE(TogglePropertyAction); 329public: 330 TogglePropertyAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, unsigned propertyIndex, bool disable) 331 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("ToggleProperty"), styleSheet) 332 , m_cssId(cssId) 333 , m_propertyIndex(propertyIndex) 334 , m_disable(disable) 335 { 336 } 337 338 virtual bool perform(ExceptionCode& ec) override 339 { 340 return redo(ec); 341 } 342 343 virtual bool undo(ExceptionCode& ec) override 344 { 345 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, !m_disable, ec); 346 } 347 348 virtual bool redo(ExceptionCode& ec) override 349 { 350 return m_styleSheet->toggleProperty(m_cssId, m_propertyIndex, m_disable, ec); 351 } 352 353private: 354 InspectorCSSId m_cssId; 355 unsigned m_propertyIndex; 356 bool m_disable; 357}; 358 359class InspectorCSSAgent::SetRuleSelectorAction final : public InspectorCSSAgent::StyleSheetAction { 360 WTF_MAKE_NONCOPYABLE(SetRuleSelectorAction); 361public: 362 SetRuleSelectorAction(InspectorStyleSheet* styleSheet, const InspectorCSSId& cssId, const String& selector) 363 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("SetRuleSelector"), styleSheet) 364 , m_cssId(cssId) 365 , m_selector(selector) 366 { 367 } 368 369 virtual bool perform(ExceptionCode& ec) override 370 { 371 m_oldSelector = m_styleSheet->ruleSelector(m_cssId, ec); 372 if (ec) 373 return false; 374 return redo(ec); 375 } 376 377 virtual bool undo(ExceptionCode& ec) override 378 { 379 return m_styleSheet->setRuleSelector(m_cssId, m_oldSelector, ec); 380 } 381 382 virtual bool redo(ExceptionCode& ec) override 383 { 384 return m_styleSheet->setRuleSelector(m_cssId, m_selector, ec); 385 } 386 387private: 388 InspectorCSSId m_cssId; 389 String m_selector; 390 String m_oldSelector; 391}; 392 393class InspectorCSSAgent::AddRuleAction final : public InspectorCSSAgent::StyleSheetAction { 394 WTF_MAKE_NONCOPYABLE(AddRuleAction); 395public: 396 AddRuleAction(InspectorStyleSheet* styleSheet, const String& selector) 397 : InspectorCSSAgent::StyleSheetAction(ASCIILiteral("AddRule"), styleSheet) 398 , m_selector(selector) 399 { 400 } 401 402 virtual bool perform(ExceptionCode& ec) override 403 { 404 return redo(ec); 405 } 406 407 virtual bool undo(ExceptionCode& ec) override 408 { 409 return m_styleSheet->deleteRule(m_newId, ec); 410 } 411 412 virtual bool redo(ExceptionCode& ec) override 413 { 414 CSSStyleRule* cssStyleRule = m_styleSheet->addRule(m_selector, ec); 415 if (ec) 416 return false; 417 m_newId = m_styleSheet->ruleId(cssStyleRule); 418 return true; 419 } 420 421 InspectorCSSId newRuleId() { return m_newId; } 422 423private: 424 InspectorCSSId m_newId; 425 String m_selector; 426 String m_oldSelector; 427}; 428 429// static 430CSSStyleRule* InspectorCSSAgent::asCSSStyleRule(CSSRule* rule) 431{ 432 if (rule->type() != CSSRule::STYLE_RULE) 433 return nullptr; 434 return static_cast<CSSStyleRule*>(rule); 435} 436 437InspectorCSSAgent::InspectorCSSAgent(InstrumentingAgents* instrumentingAgents, InspectorDOMAgent* domAgent) 438 : InspectorAgentBase(ASCIILiteral("CSS"), instrumentingAgents) 439 , m_domAgent(domAgent) 440 , m_lastStyleSheetId(1) 441{ 442 m_domAgent->setDOMListener(this); 443} 444 445InspectorCSSAgent::~InspectorCSSAgent() 446{ 447 ASSERT(!m_domAgent); 448 reset(); 449} 450 451void InspectorCSSAgent::didCreateFrontendAndBackend(Inspector::InspectorFrontendChannel* frontendChannel, InspectorBackendDispatcher* backendDispatcher) 452{ 453 m_frontendDispatcher = std::make_unique<InspectorCSSFrontendDispatcher>(frontendChannel); 454 m_backendDispatcher = InspectorCSSBackendDispatcher::create(backendDispatcher, this); 455} 456 457void InspectorCSSAgent::willDestroyFrontendAndBackend(InspectorDisconnectReason) 458{ 459 m_frontendDispatcher = nullptr; 460 m_backendDispatcher.clear(); 461 462 resetNonPersistentData(); 463} 464 465void InspectorCSSAgent::discardAgent() 466{ 467 m_domAgent->setDOMListener(nullptr); 468 m_domAgent = nullptr; 469} 470 471void InspectorCSSAgent::reset() 472{ 473 m_idToInspectorStyleSheet.clear(); 474 m_cssStyleSheetToInspectorStyleSheet.clear(); 475 m_nodeToInspectorStyleSheet.clear(); 476 m_documentToInspectorStyleSheet.clear(); 477 resetNonPersistentData(); 478} 479 480void InspectorCSSAgent::resetNonPersistentData() 481{ 482 m_namedFlowCollectionsRequested.clear(); 483 if (m_changeRegionOversetTask) 484 m_changeRegionOversetTask->reset(); 485 resetPseudoStates(); 486} 487 488void InspectorCSSAgent::enable(ErrorString*) 489{ 490 m_instrumentingAgents->setInspectorCSSAgent(this); 491} 492 493void InspectorCSSAgent::disable(ErrorString*) 494{ 495 m_instrumentingAgents->setInspectorCSSAgent(nullptr); 496} 497 498void InspectorCSSAgent::mediaQueryResultChanged() 499{ 500 if (m_frontendDispatcher) 501 m_frontendDispatcher->mediaQueryResultChanged(); 502} 503 504void InspectorCSSAgent::didCreateNamedFlow(Document* document, WebKitNamedFlow* namedFlow) 505{ 506 int documentNodeId = documentNodeWithRequestedFlowsId(document); 507 if (!documentNodeId) 508 return; 509 510 ErrorString errorString; 511 m_frontendDispatcher->namedFlowCreated(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId)); 512} 513 514void InspectorCSSAgent::willRemoveNamedFlow(Document* document, WebKitNamedFlow* namedFlow) 515{ 516 int documentNodeId = documentNodeWithRequestedFlowsId(document); 517 if (!documentNodeId) 518 return; 519 520 if (m_changeRegionOversetTask) 521 m_changeRegionOversetTask->unschedule(namedFlow); 522 523 m_frontendDispatcher->namedFlowRemoved(documentNodeId, namedFlow->name().string()); 524} 525 526void InspectorCSSAgent::didChangeRegionOverset(Document* document, WebKitNamedFlow* namedFlow) 527{ 528 int documentNodeId = documentNodeWithRequestedFlowsId(document); 529 if (!documentNodeId) 530 return; 531 532 if (!m_changeRegionOversetTask) 533 m_changeRegionOversetTask = std::make_unique<ChangeRegionOversetTask>(this); 534 m_changeRegionOversetTask->scheduleFor(namedFlow, documentNodeId); 535} 536 537void InspectorCSSAgent::regionOversetChanged(WebKitNamedFlow* namedFlow, int documentNodeId) 538{ 539 if (namedFlow->flowState() == WebKitNamedFlow::FlowStateNull) 540 return; 541 542 ErrorString errorString; 543 Ref<WebKitNamedFlow> protect(*namedFlow); 544 545 m_frontendDispatcher->regionOversetChanged(buildObjectForNamedFlow(&errorString, namedFlow, documentNodeId)); 546} 547 548void InspectorCSSAgent::didRegisterNamedFlowContentElement(Document* document, WebKitNamedFlow* namedFlow, Node* contentElement, Node* nextContentElement) 549{ 550 int documentNodeId = documentNodeWithRequestedFlowsId(document); 551 if (!documentNodeId) 552 return; 553 554 ErrorString errorString; 555 int contentElementNodeId = m_domAgent->pushNodeToFrontend(&errorString, documentNodeId, contentElement); 556 int nextContentElementNodeId = nextContentElement ? m_domAgent->pushNodeToFrontend(&errorString, documentNodeId, nextContentElement) : 0; 557 m_frontendDispatcher->registeredNamedFlowContentElement(documentNodeId, namedFlow->name().string(), contentElementNodeId, nextContentElementNodeId); 558} 559 560void InspectorCSSAgent::didUnregisterNamedFlowContentElement(Document* document, WebKitNamedFlow* namedFlow, Node* contentElement) 561{ 562 int documentNodeId = documentNodeWithRequestedFlowsId(document); 563 if (!documentNodeId) 564 return; 565 566 ErrorString errorString; 567 int contentElementNodeId = m_domAgent->pushNodeToFrontend(&errorString, documentNodeId, contentElement); 568 if (!contentElementNodeId) { 569 // We've already notified that the DOM node was removed from the DOM, so there's no need to send another event. 570 return; 571 } 572 m_frontendDispatcher->unregisteredNamedFlowContentElement(documentNodeId, namedFlow->name().string(), contentElementNodeId); 573} 574 575bool InspectorCSSAgent::forcePseudoState(Element* element, CSSSelector::PseudoClassType pseudoClassType) 576{ 577 if (m_nodeIdToForcedPseudoState.isEmpty()) 578 return false; 579 580 int nodeId = m_domAgent->boundNodeId(element); 581 if (!nodeId) 582 return false; 583 584 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId); 585 if (it == m_nodeIdToForcedPseudoState.end()) 586 return false; 587 588 unsigned forcedPseudoState = it->value; 589 switch (pseudoClassType) { 590 case CSSSelector::PseudoClassActive: 591 return forcedPseudoState & PseudoClassActive; 592 case CSSSelector::PseudoClassFocus: 593 return forcedPseudoState & PseudoClassFocus; 594 case CSSSelector::PseudoClassHover: 595 return forcedPseudoState & PseudoClassHover; 596 case CSSSelector::PseudoClassVisited: 597 return forcedPseudoState & PseudoClassVisited; 598 default: 599 return false; 600 } 601} 602 603void InspectorCSSAgent::getMatchedStylesForNode(ErrorString* errorString, int nodeId, const bool* includePseudo, const bool* includeInherited, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::RuleMatch>>& matchedCSSRules, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::PseudoIdMatches>>& pseudoIdMatches, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::InheritedStyleEntry>>& inheritedEntries) 604{ 605 Element* element = elementForId(errorString, nodeId); 606 if (!element) 607 return; 608 609 // Matched rules. 610 StyleResolver& styleResolver = element->document().ensureStyleResolver(); 611 auto matchedRules = styleResolver.styleRulesForElement(element, StyleResolver::AllCSSRules); 612 matchedCSSRules = buildArrayForMatchedRuleList(matchedRules, styleResolver, element); 613 614 // Pseudo elements. 615 if (!includePseudo || *includePseudo) { 616 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::PseudoIdMatches>> pseudoElements = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::PseudoIdMatches>::create(); 617 for (PseudoId pseudoId = FIRST_PUBLIC_PSEUDOID; pseudoId < AFTER_LAST_INTERNAL_PSEUDOID; pseudoId = static_cast<PseudoId>(pseudoId + 1)) { 618 auto matchedRules = styleResolver.pseudoStyleRulesForElement(element, pseudoId, StyleResolver::AllCSSRules); 619 if (!matchedRules.isEmpty()) { 620 RefPtr<Inspector::TypeBuilder::CSS::PseudoIdMatches> matches = Inspector::TypeBuilder::CSS::PseudoIdMatches::create() 621 .setPseudoId(static_cast<int>(pseudoId)) 622 .setMatches(buildArrayForMatchedRuleList(matchedRules, styleResolver, element)); 623 pseudoElements->addItem(matches.release()); 624 } 625 } 626 627 pseudoIdMatches = pseudoElements.release(); 628 } 629 630 // Inherited styles. 631 if (!includeInherited || *includeInherited) { 632 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::InheritedStyleEntry>> entries = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::InheritedStyleEntry>::create(); 633 Element* parentElement = element->parentElement(); 634 while (parentElement) { 635 StyleResolver& parentStyleResolver = parentElement->document().ensureStyleResolver(); 636 auto parentMatchedRules = parentStyleResolver.styleRulesForElement(parentElement, StyleResolver::AllCSSRules); 637 RefPtr<Inspector::TypeBuilder::CSS::InheritedStyleEntry> entry = Inspector::TypeBuilder::CSS::InheritedStyleEntry::create() 638 .setMatchedCSSRules(buildArrayForMatchedRuleList(parentMatchedRules, styleResolver, parentElement)); 639 if (parentElement->style() && parentElement->style()->length()) { 640 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(parentElement); 641 if (styleSheet) 642 entry->setInlineStyle(styleSheet->buildObjectForStyle(styleSheet->styleForId(InspectorCSSId(styleSheet->id(), 0)))); 643 } 644 645 entries->addItem(entry.release()); 646 parentElement = parentElement->parentElement(); 647 } 648 649 inheritedEntries = entries.release(); 650 } 651} 652 653void InspectorCSSAgent::getInlineStylesForNode(ErrorString* errorString, int nodeId, RefPtr<Inspector::TypeBuilder::CSS::CSSStyle>& inlineStyle, RefPtr<Inspector::TypeBuilder::CSS::CSSStyle>& attributesStyle) 654{ 655 Element* element = elementForId(errorString, nodeId); 656 if (!element) 657 return; 658 659 InspectorStyleSheetForInlineStyle* styleSheet = asInspectorStyleSheet(element); 660 if (!styleSheet) 661 return; 662 663 inlineStyle = styleSheet->buildObjectForStyle(element->style()); 664 RefPtr<Inspector::TypeBuilder::CSS::CSSStyle> attributes = buildObjectForAttributesStyle(element); 665 attributesStyle = attributes ? attributes.release() : nullptr; 666} 667 668void InspectorCSSAgent::getComputedStyleForNode(ErrorString* errorString, int nodeId, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSComputedStyleProperty>>& style) 669{ 670 Element* element = elementForId(errorString, nodeId); 671 if (!element) 672 return; 673 674 RefPtr<CSSComputedStyleDeclaration> computedStyleInfo = CSSComputedStyleDeclaration::create(element, true); 675 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), computedStyleInfo, nullptr); 676 style = inspectorStyle->buildArrayForComputedStyle(); 677} 678 679void InspectorCSSAgent::getAllStyleSheets(ErrorString*, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader>>& styleInfos) 680{ 681 styleInfos = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader>::create(); 682 Vector<Document*> documents = m_domAgent->documents(); 683 for (Vector<Document*>::iterator it = documents.begin(); it != documents.end(); ++it) { 684 StyleSheetList* list = (*it)->styleSheets(); 685 for (unsigned i = 0; i < list->length(); ++i) { 686 StyleSheet* styleSheet = list->item(i); 687 if (styleSheet->isCSSStyleSheet()) 688 collectStyleSheets(static_cast<CSSStyleSheet*>(styleSheet), styleInfos.get()); 689 } 690 } 691} 692 693void InspectorCSSAgent::getStyleSheet(ErrorString* errorString, const String& styleSheetId, RefPtr<Inspector::TypeBuilder::CSS::CSSStyleSheetBody>& styleSheetObject) 694{ 695 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 696 if (!inspectorStyleSheet) 697 return; 698 699 styleSheetObject = inspectorStyleSheet->buildObjectForStyleSheet(); 700} 701 702void InspectorCSSAgent::getStyleSheetText(ErrorString* errorString, const String& styleSheetId, String* result) 703{ 704 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 705 if (!inspectorStyleSheet) 706 return; 707 708 inspectorStyleSheet->getText(result); 709} 710 711void InspectorCSSAgent::setStyleSheetText(ErrorString* errorString, const String& styleSheetId, const String& text) 712{ 713 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, styleSheetId); 714 if (!inspectorStyleSheet) 715 return; 716 717 ExceptionCode ec = 0; 718 m_domAgent->history()->perform(std::make_unique<SetStyleSheetTextAction>(inspectorStyleSheet, text), ec); 719 *errorString = InspectorDOMAgent::toErrorString(ec); 720} 721 722void InspectorCSSAgent::setStyleText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, const String& text, RefPtr<Inspector::TypeBuilder::CSS::CSSStyle>& result) 723{ 724 InspectorCSSId compoundId(fullStyleId); 725 ASSERT(!compoundId.isEmpty()); 726 727 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 728 if (!inspectorStyleSheet) 729 return; 730 731 ExceptionCode ec = 0; 732 bool success = m_domAgent->history()->perform(std::make_unique<SetStyleTextAction>(inspectorStyleSheet, compoundId, text), ec); 733 if (success) 734 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId)); 735 *errorString = InspectorDOMAgent::toErrorString(ec); 736} 737 738void InspectorCSSAgent::setPropertyText(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, const String& text, bool overwrite, RefPtr<Inspector::TypeBuilder::CSS::CSSStyle>& result) 739{ 740 InspectorCSSId compoundId(fullStyleId); 741 ASSERT(!compoundId.isEmpty()); 742 743 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 744 if (!inspectorStyleSheet) 745 return; 746 747 ExceptionCode ec = 0; 748 bool success = m_domAgent->history()->perform(std::make_unique<SetPropertyTextAction>(inspectorStyleSheet, compoundId, propertyIndex, text, overwrite), ec); 749 if (success) 750 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId)); 751 *errorString = InspectorDOMAgent::toErrorString(ec); 752} 753 754void InspectorCSSAgent::toggleProperty(ErrorString* errorString, const RefPtr<InspectorObject>& fullStyleId, int propertyIndex, bool disable, RefPtr<Inspector::TypeBuilder::CSS::CSSStyle>& result) 755{ 756 InspectorCSSId compoundId(fullStyleId); 757 ASSERT(!compoundId.isEmpty()); 758 759 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 760 if (!inspectorStyleSheet) 761 return; 762 763 ExceptionCode ec = 0; 764 bool success = m_domAgent->history()->perform(std::make_unique<TogglePropertyAction>(inspectorStyleSheet, compoundId, propertyIndex, disable), ec); 765 if (success) 766 result = inspectorStyleSheet->buildObjectForStyle(inspectorStyleSheet->styleForId(compoundId)); 767 *errorString = InspectorDOMAgent::toErrorString(ec); 768} 769 770void InspectorCSSAgent::setRuleSelector(ErrorString* errorString, const RefPtr<InspectorObject>& fullRuleId, const String& selector, RefPtr<Inspector::TypeBuilder::CSS::CSSRule>& result) 771{ 772 InspectorCSSId compoundId(fullRuleId); 773 ASSERT(!compoundId.isEmpty()); 774 775 InspectorStyleSheet* inspectorStyleSheet = assertStyleSheetForId(errorString, compoundId.styleSheetId()); 776 if (!inspectorStyleSheet) 777 return; 778 779 ExceptionCode ec = 0; 780 bool success = m_domAgent->history()->perform(std::make_unique<SetRuleSelectorAction>(inspectorStyleSheet, compoundId, selector), ec); 781 782 if (success) 783 result = inspectorStyleSheet->buildObjectForRule(inspectorStyleSheet->ruleForId(compoundId)); 784 *errorString = InspectorDOMAgent::toErrorString(ec); 785} 786 787void InspectorCSSAgent::addRule(ErrorString* errorString, const int contextNodeId, const String& selector, RefPtr<Inspector::TypeBuilder::CSS::CSSRule>& result) 788{ 789 Node* node = m_domAgent->assertNode(errorString, contextNodeId); 790 if (!node) 791 return; 792 793 InspectorStyleSheet* inspectorStyleSheet = viaInspectorStyleSheet(&node->document(), true); 794 if (!inspectorStyleSheet) { 795 *errorString = "No target stylesheet found"; 796 return; 797 } 798 799 ExceptionCode ec = 0; 800 auto action = std::make_unique<AddRuleAction>(inspectorStyleSheet, selector); 801 AddRuleAction* rawAction = action.get(); 802 bool success = m_domAgent->history()->perform(WTF::move(action), ec); 803 if (!success) { 804 *errorString = InspectorDOMAgent::toErrorString(ec); 805 return; 806 } 807 808 InspectorCSSId ruleId = rawAction->newRuleId(); 809 CSSStyleRule* rule = inspectorStyleSheet->ruleForId(ruleId); 810 result = inspectorStyleSheet->buildObjectForRule(rule); 811} 812 813void InspectorCSSAgent::getSupportedCSSProperties(ErrorString*, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSPropertyInfo>>& cssProperties) 814{ 815 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSPropertyInfo>> properties = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSPropertyInfo>::create(); 816 for (int i = firstCSSProperty; i <= lastCSSProperty; ++i) { 817 CSSPropertyID id = convertToCSSPropertyID(i); 818 RefPtr<Inspector::TypeBuilder::CSS::CSSPropertyInfo> property = Inspector::TypeBuilder::CSS::CSSPropertyInfo::create() 819 .setName(getPropertyNameString(id)); 820 821 const StylePropertyShorthand& shorthand = shorthandForProperty(id); 822 if (!shorthand.length()) { 823 properties->addItem(property.release()); 824 continue; 825 } 826 RefPtr<Inspector::TypeBuilder::Array<String>> longhands = Inspector::TypeBuilder::Array<String>::create(); 827 for (unsigned j = 0; j < shorthand.length(); ++j) { 828 CSSPropertyID longhandID = shorthand.properties()[j]; 829 longhands->addItem(getPropertyNameString(longhandID)); 830 } 831 property->setLonghands(longhands); 832 properties->addItem(property.release()); 833 } 834 cssProperties = properties.release(); 835} 836 837void InspectorCSSAgent::forcePseudoState(ErrorString* errorString, int nodeId, const RefPtr<InspectorArray>& forcedPseudoClasses) 838{ 839 Element* element = m_domAgent->assertElement(errorString, nodeId); 840 if (!element) 841 return; 842 843 unsigned forcedPseudoState = computePseudoClassMask(forcedPseudoClasses.get()); 844 NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.find(nodeId); 845 unsigned currentForcedPseudoState = it == m_nodeIdToForcedPseudoState.end() ? 0 : it->value; 846 bool needStyleRecalc = forcedPseudoState != currentForcedPseudoState; 847 if (!needStyleRecalc) 848 return; 849 850 if (forcedPseudoState) 851 m_nodeIdToForcedPseudoState.set(nodeId, forcedPseudoState); 852 else 853 m_nodeIdToForcedPseudoState.remove(nodeId); 854 element->document().styleResolverChanged(RecalcStyleImmediately); 855} 856 857void InspectorCSSAgent::getNamedFlowCollection(ErrorString* errorString, int documentNodeId, RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::NamedFlow>>& result) 858{ 859 Document* document = m_domAgent->assertDocument(errorString, documentNodeId); 860 if (!document) 861 return; 862 863 m_namedFlowCollectionsRequested.add(documentNodeId); 864 865 Vector<RefPtr<WebKitNamedFlow>> namedFlowsVector = document->namedFlows()->namedFlows(); 866 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::NamedFlow>> namedFlows = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::NamedFlow>::create(); 867 868 for (Vector<RefPtr<WebKitNamedFlow>>::iterator it = namedFlowsVector.begin(); it != namedFlowsVector.end(); ++it) 869 namedFlows->addItem(buildObjectForNamedFlow(errorString, it->get(), documentNodeId)); 870 871 result = namedFlows.release(); 872} 873 874InspectorStyleSheetForInlineStyle* InspectorCSSAgent::asInspectorStyleSheet(Element* element) 875{ 876 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element); 877 if (it == m_nodeToInspectorStyleSheet.end()) { 878 CSSStyleDeclaration* style = element->isStyledElement() ? element->style() : nullptr; 879 if (!style) 880 return nullptr; 881 882 String newStyleSheetId = String::number(m_lastStyleSheetId++); 883 RefPtr<InspectorStyleSheetForInlineStyle> inspectorStyleSheet = InspectorStyleSheetForInlineStyle::create(m_domAgent->pageAgent(), newStyleSheetId, element, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Regular, this); 884 m_idToInspectorStyleSheet.set(newStyleSheetId, inspectorStyleSheet); 885 m_nodeToInspectorStyleSheet.set(element, inspectorStyleSheet); 886 return inspectorStyleSheet.get(); 887 } 888 889 return it->value.get(); 890} 891 892Element* InspectorCSSAgent::elementForId(ErrorString* errorString, int nodeId) 893{ 894 Node* node = m_domAgent->nodeForId(nodeId); 895 if (!node) { 896 *errorString = "No node with given id found"; 897 return nullptr; 898 } 899 if (!node->isElementNode()) { 900 *errorString = "Not an element node"; 901 return nullptr; 902 } 903 return toElement(node); 904} 905 906int InspectorCSSAgent::documentNodeWithRequestedFlowsId(Document* document) 907{ 908 int documentNodeId = m_domAgent->boundNodeId(document); 909 if (!documentNodeId || !m_namedFlowCollectionsRequested.contains(documentNodeId)) 910 return 0; 911 912 return documentNodeId; 913} 914 915void InspectorCSSAgent::collectStyleSheets(CSSStyleSheet* styleSheet, Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSStyleSheetHeader>* result) 916{ 917 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(static_cast<CSSStyleSheet*>(styleSheet)); 918 result->addItem(inspectorStyleSheet->buildObjectForStyleSheetInfo()); 919 for (unsigned i = 0, size = styleSheet->length(); i < size; ++i) { 920 CSSRule* rule = styleSheet->item(i); 921 if (rule->type() == CSSRule::IMPORT_RULE) { 922 CSSStyleSheet* importedStyleSheet = static_cast<CSSImportRule*>(rule)->styleSheet(); 923 if (importedStyleSheet) 924 collectStyleSheets(importedStyleSheet, result); 925 } 926 } 927} 928 929InspectorStyleSheet* InspectorCSSAgent::bindStyleSheet(CSSStyleSheet* styleSheet) 930{ 931 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_cssStyleSheetToInspectorStyleSheet.get(styleSheet); 932 if (!inspectorStyleSheet) { 933 String id = String::number(m_lastStyleSheetId++); 934 Document* document = styleSheet->ownerDocument(); 935 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, styleSheet, detectOrigin(styleSheet, document), InspectorDOMAgent::documentURLString(document), this); 936 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet); 937 m_cssStyleSheetToInspectorStyleSheet.set(styleSheet, inspectorStyleSheet); 938 } 939 return inspectorStyleSheet.get(); 940} 941 942InspectorStyleSheet* InspectorCSSAgent::viaInspectorStyleSheet(Document* document, bool createIfAbsent) 943{ 944 if (!document) { 945 ASSERT(!createIfAbsent); 946 return nullptr; 947 } 948 949 if (!document->isHTMLDocument() && !document->isSVGDocument()) 950 return nullptr; 951 952 RefPtr<InspectorStyleSheet> inspectorStyleSheet = m_documentToInspectorStyleSheet.get(document); 953 if (inspectorStyleSheet || !createIfAbsent) 954 return inspectorStyleSheet.get(); 955 956 ExceptionCode ec = 0; 957 RefPtr<Element> styleElement = document->createElement("style", ec); 958 if (!ec) 959 styleElement->setAttribute("type", "text/css", ec); 960 if (!ec) { 961 ContainerNode* targetNode; 962 // HEAD is absent in ImageDocuments, for example. 963 if (document->head()) 964 targetNode = document->head(); 965 else if (document->body()) 966 targetNode = document->body(); 967 else 968 return nullptr; 969 970 InlineStyleOverrideScope overrideScope(document); 971 targetNode->appendChild(styleElement, ec); 972 } 973 if (ec) 974 return nullptr; 975 976 CSSStyleSheet* cssStyleSheet = nullptr; 977 if (styleElement->isHTMLElement()) 978 cssStyleSheet = toHTMLStyleElement(styleElement.get())->sheet(); 979 else if (styleElement->isSVGElement()) 980 cssStyleSheet = toSVGStyleElement(styleElement.get())->sheet(); 981 982 if (!cssStyleSheet) 983 return nullptr; 984 985 String id = String::number(m_lastStyleSheetId++); 986 inspectorStyleSheet = InspectorStyleSheet::create(m_domAgent->pageAgent(), id, cssStyleSheet, Inspector::TypeBuilder::CSS::StyleSheetOrigin::Inspector, InspectorDOMAgent::documentURLString(document), this); 987 m_idToInspectorStyleSheet.set(id, inspectorStyleSheet); 988 m_cssStyleSheetToInspectorStyleSheet.set(cssStyleSheet, inspectorStyleSheet); 989 m_documentToInspectorStyleSheet.set(document, inspectorStyleSheet); 990 return inspectorStyleSheet.get(); 991} 992 993InspectorStyleSheet* InspectorCSSAgent::assertStyleSheetForId(ErrorString* errorString, const String& styleSheetId) 994{ 995 IdToInspectorStyleSheet::iterator it = m_idToInspectorStyleSheet.find(styleSheetId); 996 if (it == m_idToInspectorStyleSheet.end()) { 997 *errorString = "No style sheet with given id found"; 998 return nullptr; 999 } 1000 return it->value.get(); 1001} 1002 1003Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum InspectorCSSAgent::detectOrigin(CSSStyleSheet* pageStyleSheet, Document* ownerDocument) 1004{ 1005 Inspector::TypeBuilder::CSS::StyleSheetOrigin::Enum origin = Inspector::TypeBuilder::CSS::StyleSheetOrigin::Regular; 1006 if (pageStyleSheet && !pageStyleSheet->ownerNode() && pageStyleSheet->href().isEmpty()) 1007 origin = Inspector::TypeBuilder::CSS::StyleSheetOrigin::UserAgent; 1008 else if (pageStyleSheet && pageStyleSheet->ownerNode() && pageStyleSheet->ownerNode()->nodeName() == "#document") 1009 origin = Inspector::TypeBuilder::CSS::StyleSheetOrigin::User; 1010 else { 1011 InspectorStyleSheet* viaInspectorStyleSheetForOwner = viaInspectorStyleSheet(ownerDocument, false); 1012 if (viaInspectorStyleSheetForOwner && pageStyleSheet == viaInspectorStyleSheetForOwner->pageStyleSheet()) 1013 origin = Inspector::TypeBuilder::CSS::StyleSheetOrigin::Inspector; 1014 } 1015 return origin; 1016} 1017 1018PassRefPtr<Inspector::TypeBuilder::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(StyleRule* styleRule, StyleResolver& styleResolver) 1019{ 1020 if (!styleRule) 1021 return nullptr; 1022 1023 // StyleRules returned by StyleResolver::styleRulesForElement lack parent pointers since that infomation is not cheaply available. 1024 // Since the inspector wants to walk the parent chain, we construct the full wrappers here. 1025 CSSStyleRule* cssomWrapper = styleResolver.inspectorCSSOMWrappers().getWrapperForRuleInSheets(styleRule, styleResolver.document().styleSheetCollection()); 1026 if (!cssomWrapper) 1027 return nullptr; 1028 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(cssomWrapper->parentStyleSheet()); 1029 return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(cssomWrapper) : nullptr; 1030} 1031 1032PassRefPtr<Inspector::TypeBuilder::CSS::CSSRule> InspectorCSSAgent::buildObjectForRule(CSSStyleRule* rule) 1033{ 1034 if (!rule) 1035 return nullptr; 1036 1037 ASSERT(rule->parentStyleSheet()); 1038 InspectorStyleSheet* inspectorStyleSheet = bindStyleSheet(rule->parentStyleSheet()); 1039 return inspectorStyleSheet ? inspectorStyleSheet->buildObjectForRule(rule) : nullptr; 1040} 1041 1042PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>> InspectorCSSAgent::buildArrayForRuleList(CSSRuleList* ruleList) 1043{ 1044 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>> result = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::CSSRule>::create(); 1045 if (!ruleList) 1046 return result.release(); 1047 1048 for (unsigned i = 0, size = ruleList->length(); i < size; ++i) { 1049 CSSStyleRule* rule = asCSSStyleRule(ruleList->item(i)); 1050 RefPtr<Inspector::TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(rule); 1051 if (!ruleObject) 1052 continue; 1053 result->addItem(ruleObject); 1054 } 1055 return result.release(); 1056} 1057 1058PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::RuleMatch>> InspectorCSSAgent::buildArrayForMatchedRuleList(const Vector<RefPtr<StyleRule>>& matchedRules, StyleResolver& styleResolver, Element* element) 1059{ 1060 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::RuleMatch>> result = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::RuleMatch>::create(); 1061 1062 for (unsigned i = 0; i < matchedRules.size(); ++i) { 1063 if (!matchedRules[i]->isStyleRule()) 1064 continue; 1065 StyleRule* matchedStyleRule = static_cast<StyleRule*>(matchedRules[i].get()); 1066 RefPtr<Inspector::TypeBuilder::CSS::CSSRule> ruleObject = buildObjectForRule(matchedStyleRule, styleResolver); 1067 if (!ruleObject) 1068 continue; 1069 RefPtr<Inspector::TypeBuilder::Array<int>> matchingSelectors = Inspector::TypeBuilder::Array<int>::create(); 1070 const CSSSelectorList& selectorList = matchedStyleRule->selectorList(); 1071 long index = 0; 1072 for (const CSSSelector* selector = selectorList.first(); selector; selector = CSSSelectorList::next(selector)) { 1073 bool matched = element->matches(selector->selectorText(), IGNORE_EXCEPTION); 1074 if (matched) 1075 matchingSelectors->addItem(index); 1076 ++index; 1077 } 1078 RefPtr<Inspector::TypeBuilder::CSS::RuleMatch> match = Inspector::TypeBuilder::CSS::RuleMatch::create() 1079 .setRule(ruleObject) 1080 .setMatchingSelectors(matchingSelectors); 1081 result->addItem(match); 1082 } 1083 1084 return result.release(); 1085} 1086 1087PassRefPtr<Inspector::TypeBuilder::CSS::CSSStyle> InspectorCSSAgent::buildObjectForAttributesStyle(Element* element) 1088{ 1089 if (!element->isStyledElement()) 1090 return nullptr; 1091 1092 // FIXME: Ugliness below. 1093 StyleProperties* attributeStyle = const_cast<StyleProperties*>(toStyledElement(element)->presentationAttributeStyle()); 1094 if (!attributeStyle) 1095 return nullptr; 1096 1097 ASSERT_WITH_SECURITY_IMPLICATION(attributeStyle->isMutable()); 1098 MutableStyleProperties* mutableAttributeStyle = static_cast<MutableStyleProperties*>(attributeStyle); 1099 1100 RefPtr<InspectorStyle> inspectorStyle = InspectorStyle::create(InspectorCSSId(), mutableAttributeStyle->ensureCSSStyleDeclaration(), nullptr); 1101 return inspectorStyle->buildObjectForStyle(); 1102} 1103 1104PassRefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::Region>> InspectorCSSAgent::buildArrayForRegions(ErrorString* errorString, PassRefPtr<NodeList> regionList, int documentNodeId) 1105{ 1106 RefPtr<Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::Region>> regions = Inspector::TypeBuilder::Array<Inspector::TypeBuilder::CSS::Region>::create(); 1107 1108 for (unsigned i = 0; i < regionList->length(); ++i) { 1109 Inspector::TypeBuilder::CSS::Region::RegionOverset::Enum regionOverset; 1110 1111 switch (toElement(regionList->item(i))->regionOversetState()) { 1112 case RegionFit: 1113 regionOverset = Inspector::TypeBuilder::CSS::Region::RegionOverset::Fit; 1114 break; 1115 case RegionEmpty: 1116 regionOverset = Inspector::TypeBuilder::CSS::Region::RegionOverset::Empty; 1117 break; 1118 case RegionOverset: 1119 regionOverset = Inspector::TypeBuilder::CSS::Region::RegionOverset::Overset; 1120 break; 1121 case RegionUndefined: 1122 continue; 1123 default: 1124 ASSERT_NOT_REACHED(); 1125 continue; 1126 } 1127 1128 RefPtr<Inspector::TypeBuilder::CSS::Region> region = Inspector::TypeBuilder::CSS::Region::create() 1129 .setRegionOverset(regionOverset) 1130 // documentNodeId was previously asserted 1131 .setNodeId(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, regionList->item(i))); 1132 1133 regions->addItem(region); 1134 } 1135 1136 return regions.release(); 1137} 1138 1139PassRefPtr<Inspector::TypeBuilder::CSS::NamedFlow> InspectorCSSAgent::buildObjectForNamedFlow(ErrorString* errorString, WebKitNamedFlow* webkitNamedFlow, int documentNodeId) 1140{ 1141 RefPtr<NodeList> contentList = webkitNamedFlow->getContent(); 1142 RefPtr<Inspector::TypeBuilder::Array<int>> content = Inspector::TypeBuilder::Array<int>::create(); 1143 1144 for (unsigned i = 0; i < contentList->length(); ++i) { 1145 // documentNodeId was previously asserted 1146 content->addItem(m_domAgent->pushNodeToFrontend(errorString, documentNodeId, contentList->item(i))); 1147 } 1148 1149 RefPtr<Inspector::TypeBuilder::CSS::NamedFlow> namedFlow = Inspector::TypeBuilder::CSS::NamedFlow::create() 1150 .setDocumentNodeId(documentNodeId) 1151 .setName(webkitNamedFlow->name().string()) 1152 .setOverset(webkitNamedFlow->overset()) 1153 .setContent(content) 1154 .setRegions(buildArrayForRegions(errorString, webkitNamedFlow->getRegions(), documentNodeId)); 1155 1156 return namedFlow.release(); 1157} 1158 1159void InspectorCSSAgent::didRemoveDocument(Document* document) 1160{ 1161 if (document) 1162 m_documentToInspectorStyleSheet.remove(document); 1163} 1164 1165void InspectorCSSAgent::didRemoveDOMNode(Node* node) 1166{ 1167 if (!node) 1168 return; 1169 1170 int nodeId = m_domAgent->boundNodeId(node); 1171 if (nodeId) 1172 m_nodeIdToForcedPseudoState.remove(nodeId); 1173 1174 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(node); 1175 if (it == m_nodeToInspectorStyleSheet.end()) 1176 return; 1177 1178 m_idToInspectorStyleSheet.remove(it->value->id()); 1179 m_nodeToInspectorStyleSheet.remove(node); 1180} 1181 1182void InspectorCSSAgent::didModifyDOMAttr(Element* element) 1183{ 1184 if (!element) 1185 return; 1186 1187 NodeToInspectorStyleSheet::iterator it = m_nodeToInspectorStyleSheet.find(element); 1188 if (it == m_nodeToInspectorStyleSheet.end()) 1189 return; 1190 1191 it->value->didModifyElementAttribute(); 1192} 1193 1194void InspectorCSSAgent::styleSheetChanged(InspectorStyleSheet* styleSheet) 1195{ 1196 if (m_frontendDispatcher) 1197 m_frontendDispatcher->styleSheetChanged(styleSheet->id()); 1198} 1199 1200void InspectorCSSAgent::resetPseudoStates() 1201{ 1202 HashSet<Document*> documentsToChange; 1203 for (NodeIdToForcedPseudoState::iterator it = m_nodeIdToForcedPseudoState.begin(), end = m_nodeIdToForcedPseudoState.end(); it != end; ++it) { 1204 if (Element* element = toElement(m_domAgent->nodeForId(it->key))) 1205 documentsToChange.add(&element->document()); 1206 } 1207 1208 m_nodeIdToForcedPseudoState.clear(); 1209 for (HashSet<Document*>::iterator it = documentsToChange.begin(), end = documentsToChange.end(); it != end; ++it) 1210 (*it)->styleResolverChanged(RecalcStyleImmediately); 1211} 1212 1213} // namespace WebCore 1214 1215#endif // ENABLE(INSPECTOR) 1216