1 /* 2 * Copyright (C) 2011 Adobe Systems Incorporated. All rights reserved. 3 * Copyright (C) 2012 Apple Inc. All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 9 * 1. Redistributions of source code must retain the above 10 * copyright notice, this list of conditions and the following 11 * disclaimer. 12 * 2. Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials 15 * provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDER "AS IS" AND ANY 18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE 21 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, 22 * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR 26 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include "config.h" 32 #include "core/css/CSSGroupingRule.h" 33 34 #include "bindings/v8/ExceptionState.h" 35 #include "core/css/parser/BisonCSSParser.h" 36 #include "core/css/CSSRuleList.h" 37 #include "core/css/CSSStyleSheet.h" 38 #include "core/dom/ExceptionCode.h" 39 #include "core/frame/UseCounter.h" 40 #include "wtf/text/StringBuilder.h" 41 42 namespace WebCore { 43 44 CSSGroupingRule::CSSGroupingRule(StyleRuleGroup* groupRule, CSSStyleSheet* parent) 45 : CSSRule(parent) 46 , m_groupRule(groupRule) 47 , m_childRuleCSSOMWrappers(groupRule->childRules().size()) 48 { 49 } 50 51 CSSGroupingRule::~CSSGroupingRule() 52 { 53 #if !ENABLE(OILPAN) 54 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); 55 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { 56 if (m_childRuleCSSOMWrappers[i]) 57 m_childRuleCSSOMWrappers[i]->setParentRule(0); 58 } 59 #endif 60 } 61 62 unsigned CSSGroupingRule::insertRule(const String& ruleString, unsigned index, ExceptionState& exceptionState) 63 { 64 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); 65 66 if (index > m_groupRule->childRules().size()) { 67 exceptionState.throwDOMException(IndexSizeError, "the index " + String::number(index) + " must be less than or equal to the length of the rule list."); 68 return 0; 69 } 70 71 CSSStyleSheet* styleSheet = parentStyleSheet(); 72 CSSParserContext context(parserContext(), UseCounter::getFrom(styleSheet)); 73 BisonCSSParser parser(context); 74 RefPtrWillBeRawPtr<StyleRuleBase> newRule = parser.parseRule(styleSheet ? styleSheet->contents() : 0, ruleString); 75 if (!newRule) { 76 exceptionState.throwDOMException(SyntaxError, "the rule '" + ruleString + "' is invalid and cannot be parsed."); 77 return 0; 78 } 79 80 if (newRule->isImportRule()) { 81 // FIXME: an HierarchyRequestError should also be thrown for a @charset or a nested 82 // @media rule. They are currently not getting parsed, resulting in a SyntaxError 83 // to get raised above. 84 exceptionState.throwDOMException(HierarchyRequestError, "'@import' rules cannot be inserted inside a group rule."); 85 return 0; 86 } 87 CSSStyleSheet::RuleMutationScope mutationScope(this); 88 89 m_groupRule->wrapperInsertRule(index, newRule); 90 91 m_childRuleCSSOMWrappers.insert(index, RefPtrWillBeMember<CSSRule>(nullptr)); 92 return index; 93 } 94 95 void CSSGroupingRule::deleteRule(unsigned index, ExceptionState& exceptionState) 96 { 97 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); 98 99 if (index >= m_groupRule->childRules().size()) { 100 exceptionState.throwDOMException(IndexSizeError, "the index " + String::number(index) + " is greated than the length of the rule list."); 101 return; 102 } 103 104 CSSStyleSheet::RuleMutationScope mutationScope(this); 105 106 m_groupRule->wrapperRemoveRule(index); 107 108 if (m_childRuleCSSOMWrappers[index]) 109 m_childRuleCSSOMWrappers[index]->setParentRule(0); 110 m_childRuleCSSOMWrappers.remove(index); 111 } 112 113 void CSSGroupingRule::appendCSSTextForItems(StringBuilder& result) const 114 { 115 unsigned size = length(); 116 for (unsigned i = 0; i < size; ++i) { 117 result.appendLiteral(" "); 118 result.append(item(i)->cssText()); 119 result.append('\n'); 120 } 121 } 122 123 unsigned CSSGroupingRule::length() const 124 { 125 return m_groupRule->childRules().size(); 126 } 127 128 CSSRule* CSSGroupingRule::item(unsigned index) const 129 { 130 if (index >= length()) 131 return 0; 132 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size()); 133 RefPtrWillBeMember<CSSRule>& rule = m_childRuleCSSOMWrappers[index]; 134 if (!rule) 135 rule = m_groupRule->childRules()[index]->createCSSOMWrapper(const_cast<CSSGroupingRule*>(this)); 136 return rule.get(); 137 } 138 139 CSSRuleList* CSSGroupingRule::cssRules() const 140 { 141 if (!m_ruleListCSSOMWrapper) 142 m_ruleListCSSOMWrapper = LiveCSSRuleList<CSSGroupingRule>::create(const_cast<CSSGroupingRule*>(this)); 143 return m_ruleListCSSOMWrapper.get(); 144 } 145 146 void CSSGroupingRule::reattach(StyleRuleBase* rule) 147 { 148 ASSERT(rule); 149 m_groupRule = static_cast<StyleRuleGroup*>(rule); 150 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) { 151 if (m_childRuleCSSOMWrappers[i]) 152 m_childRuleCSSOMWrappers[i]->reattach(m_groupRule->childRules()[i].get()); 153 } 154 } 155 156 void CSSGroupingRule::trace(Visitor* visitor) 157 { 158 CSSRule::trace(visitor); 159 #if ENABLE(OILPAN) 160 visitor->trace(m_childRuleCSSOMWrappers); 161 #endif 162 visitor->trace(m_groupRule); 163 visitor->trace(m_ruleListCSSOMWrapper); 164 } 165 166 } // namespace WebCore 167