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
33#include "CSSGroupingRule.h"
34
35#include "CSSParser.h"
36#include "CSSRuleList.h"
37#include "CSSStyleSheet.h"
38#include "StyleRule.h"
39#include <wtf/text/StringBuilder.h>
40
41namespace WebCore {
42
43CSSGroupingRule::CSSGroupingRule(StyleRuleGroup& groupRule, CSSStyleSheet* parent)
44 : CSSRule(parent)
45 , m_groupRule(groupRule)
46 , m_childRuleCSSOMWrappers(groupRule.childRules().size())
47{
48}
49
50CSSGroupingRule::~CSSGroupingRule()
51{
52 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size());
53 for (unsigned i = 0; i < m_childRuleCSSOMWrappers.size(); ++i) {
54 if (m_childRuleCSSOMWrappers[i])
55 m_childRuleCSSOMWrappers[i]->setParentRule(0);
56 }
57}
58
59ExceptionOr<unsigned> CSSGroupingRule::insertRule(const String& ruleString, unsigned index)
60{
61 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size());
62
63 if (index > m_groupRule->childRules().size()) {
64 // IndexSizeError: Raised if the specified index is not a valid insertion point.
65 return Exception { IndexSizeError };
66 }
67
68 CSSStyleSheet* styleSheet = parentStyleSheet();
69 RefPtr<StyleRuleBase> newRule = CSSParser::parseRule(parserContext(), styleSheet ? &styleSheet->contents() : nullptr, ruleString);
70 if (!newRule) {
71 // SyntaxError: Raised if the specified rule has a syntax error and is unparsable.
72 return Exception { SyntaxError };
73 }
74
75 if (newRule->isImportRule() || newRule->isNamespaceRule()) {
76 // FIXME: an HierarchyRequestError should also be thrown for a @charset or a nested
77 // @media rule. They are currently not getting parsed, resulting in a SyntaxError
78 // to get raised above.
79
80 // HierarchyRequestError: Raised if the rule cannot be inserted at the specified
81 // index, e.g., if an @import rule is inserted after a standard rule set or other
82 // at-rule.
83 return Exception { HierarchyRequestError };
84 }
85 CSSStyleSheet::RuleMutationScope mutationScope(this);
86
87 m_groupRule->wrapperInsertRule(index, newRule.releaseNonNull());
88
89 m_childRuleCSSOMWrappers.insert(index, RefPtr<CSSRule>());
90 return index;
91}
92
93ExceptionOr<void> CSSGroupingRule::deleteRule(unsigned index)
94{
95 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size());
96
97 if (index >= m_groupRule->childRules().size()) {
98 // IndexSizeError: Raised if the specified index does not correspond to a
99 // rule in the media rule list.
100 return Exception { IndexSizeError };
101 }
102
103 CSSStyleSheet::RuleMutationScope mutationScope(this);
104
105 m_groupRule->wrapperRemoveRule(index);
106
107 if (m_childRuleCSSOMWrappers[index])
108 m_childRuleCSSOMWrappers[index]->setParentRule(0);
109 m_childRuleCSSOMWrappers.remove(index);
110
111 return { };
112}
113
114void CSSGroupingRule::appendCssTextForItems(StringBuilder& result) const
115{
116 unsigned size = length();
117 for (unsigned i = 0; i < size; ++i) {
118 result.appendLiteral(" ");
119 result.append(item(i)->cssText());
120 result.append('\n');
121 }
122}
123
124unsigned CSSGroupingRule::length() const
125{
126 return m_groupRule->childRules().size();
127}
128
129CSSRule* CSSGroupingRule::item(unsigned index) const
130{
131 if (index >= length())
132 return nullptr;
133 ASSERT(m_childRuleCSSOMWrappers.size() == m_groupRule->childRules().size());
134 RefPtr<CSSRule>& rule = m_childRuleCSSOMWrappers[index];
135 if (!rule)
136 rule = m_groupRule->childRules()[index]->createCSSOMWrapper(const_cast<CSSGroupingRule*>(this));
137 return rule.get();
138}
139
140CSSRuleList& CSSGroupingRule::cssRules() const
141{
142 if (!m_ruleListCSSOMWrapper)
143 m_ruleListCSSOMWrapper = std::make_unique<LiveCSSRuleList<CSSGroupingRule>>(const_cast<CSSGroupingRule&>(*this));
144 return *m_ruleListCSSOMWrapper;
145}
146
147void CSSGroupingRule::reattach(StyleRuleBase& rule)
148{
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.get().childRules()[i]);
153 }
154}
155
156} // namespace WebCore
157