OLD | NEW |
---|---|
(Empty) | |
1 /* | |
2 * Copyright (c) 2014, Opera Software ASA. 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 * 3. Neither the name of Opera Software ASA nor the names of its | |
13 * contributors may be used to endorse or promote products derived | |
14 * from this software without specific prior written permission. | |
15 * | |
16 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | |
17 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | |
18 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS | |
19 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE | |
20 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, | |
21 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES | |
22 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | |
23 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | |
25 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) | |
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED | |
27 * OF THE POSSIBILITY OF SUCH DAMAGE. | |
28 */ | |
29 | |
30 #include "config.h" | |
31 #include "core/dom/DOMURLSearchParams.h" | |
32 | |
33 #include "core/dom/DOMURLUtils.h" | |
34 #include "platform/weborigin/KURL.h" | |
35 #include "wtf/text/StringBuilder.h" | |
36 #include "wtf/text/TextEncoding.h" | |
37 | |
38 namespace WebCore { | |
39 | |
40 DOMURLSearchParams::DOMURLSearchParams() | |
41 : m_urlObject(0) | |
42 , m_isUpdating(false) | |
43 { | |
44 ScriptWrappable::init(this); | |
45 } | |
46 | |
47 void DOMURLSearchParams::ref() | |
48 { | |
49 if (m_urlObject) | |
50 m_urlObject->refURLUtils(); | |
51 } | |
52 | |
53 void DOMURLSearchParams::deref() | |
54 { | |
55 if (m_urlObject) | |
56 m_urlObject->derefURLUtils(); | |
57 } | |
58 | |
59 void DOMURLSearchParams::runUpdateSteps() | |
60 { | |
61 if (m_urlObject) { | |
62 m_isUpdating = true; | |
63 DOMURLUtils::setSearch(m_urlObject, toString()); | |
64 m_isUpdating = false; | |
65 } | |
66 } | |
67 | |
68 static String decodeString(String input) | |
69 { | |
70 return decodeURLEscapeSequences(input.replace('+', ' ')); | |
71 } | |
72 | |
73 void DOMURLSearchParams::setInput(const String& queryString) | |
74 { | |
75 if (m_isUpdating) | |
76 return; | |
77 | |
78 m_params.clear(); | |
79 unsigned start = 0; | |
80 unsigned queryStringLength = queryString.length(); | |
81 while (start < queryStringLength) { | |
82 size_t nameStart = start; | |
83 size_t nameValueEnd = queryString.find('&', start); | |
84 if (nameValueEnd == kNotFound) | |
85 nameValueEnd = queryStringLength; | |
86 | |
87 if (nameValueEnd > start) { | |
88 size_t endOfName = queryString.find('=', start); | |
89 | |
90 if (endOfName == kNotFound || endOfName > nameValueEnd) | |
91 endOfName = nameValueEnd; | |
92 | |
93 String name = decodeString(queryString.substring(nameStart, endOfNam e - nameStart)); | |
94 | |
95 bool validUTF8 = true; | |
96 if (!name.isEmpty()) { | |
97 name = name.utf8(StrictUTF8Conversion).data(); | |
98 validUTF8 = !name.isEmpty(); | |
99 } | |
100 | |
101 String value; | |
102 if (validUTF8 && endOfName != nameValueEnd) { | |
103 value = decodeString(queryString.substring(endOfName + 1, nameVa lueEnd - endOfName - 1)); | |
104 if (!value.isEmpty()) { | |
105 value = value.utf8(StrictUTF8Conversion).data(); | |
106 validUTF8 = !value.isEmpty(); | |
107 } | |
108 } | |
109 if (validUTF8 && value.isNull()) | |
110 value = ""; | |
111 | |
112 if (validUTF8) | |
113 m_params.append(std::make_pair(name, value)); | |
114 } | |
115 start = nameValueEnd + 1; | |
116 } | |
117 } | |
118 | |
119 PassRefPtr<DOMURLSearchParams> DOMURLSearchParams::create(const String& queryStr ing) | |
120 { | |
121 RefPtr<DOMURLSearchParams> searchParams = adoptRef(new DOMURLSearchParams()) ; | |
arv (Not doing code reviews)
2014/01/21 14:40:33
We usually create a matching constructor and then
sof
2014/01/21 21:16:47
That's quite doable..and done.
| |
122 if (queryString.isEmpty()) | |
123 return searchParams.release(); | |
124 | |
125 searchParams->setInput(queryString); | |
126 return searchParams.release(); | |
127 } | |
128 | |
129 PassRefPtr<DOMURLSearchParams> DOMURLSearchParams::create(DOMURLSearchParams* in it) | |
130 { | |
131 RefPtr<DOMURLSearchParams> searchParams = adoptRef(new DOMURLSearchParams()) ; | |
132 if (!init) | |
arv (Not doing code reviews)
2014/01/21 14:40:33
Can this happen? Should we throw an exception if s
sof
2014/01/21 21:16:47
Typically yes, a TypeError due to failed object co
| |
133 return searchParams.release(); | |
134 | |
135 searchParams->m_params = init->m_params; | |
136 return searchParams.release(); | |
137 } | |
138 | |
139 static String encodeString(const String& input) | |
140 { | |
141 String escaped = encodeWithURLEscapeSequences(input); | |
142 // Encode "%20" as "*"; as required and much prettier. | |
arv (Not doing code reviews)
2014/01/21 14:40:33
Useless comment
sof
2014/01/21 21:16:47
Gone.
| |
143 return escaped.replace("%20", "+"); | |
144 } | |
145 | |
146 String DOMURLSearchParams::toString() const | |
147 { | |
148 StringBuilder result; | |
149 bool isFirst = true; | |
150 for (Vector<std::pair<String, String> >::const_iterator it = m_params.begin( ); it != m_params.end(); ++it) { | |
arv (Not doing code reviews)
2014/01/21 14:40:33
for (int i = 0; i < m_params.size(); ++i) {
ends
sof
2014/01/21 21:16:47
Yep, thanks
| |
151 String name = encodeString(it->first); | |
152 if (!name.isEmpty()) { | |
153 if (!isFirst) | |
154 result.append('&'); | |
155 else | |
156 isFirst = false; | |
157 | |
158 result.append(name); | |
159 String value = encodeString(it->second); | |
160 if (!value.isEmpty()) { | |
arv (Not doing code reviews)
2014/01/21 14:40:33
This does not look correct to me. We should always
sof
2014/01/21 21:16:47
Oops, quite right. Fixed + adjusted expected test
| |
161 result.append('='); | |
162 result.append(value); | |
163 } | |
164 } | |
165 } | |
166 return result.toString(); | |
167 } | |
168 | |
169 void DOMURLSearchParams::appendNameValue(const String& name, const String& value ) | |
170 { | |
171 m_params.append(std::make_pair(name, value)); | |
172 runUpdateSteps(); | |
173 } | |
174 | |
175 void DOMURLSearchParams::deleteAllWithName(const String& name) | |
176 { | |
177 for (unsigned i = 0; i < m_params.size();) { | |
178 if (m_params[i].first == name) | |
179 m_params.remove(i); | |
180 else | |
181 i++; | |
182 } | |
183 runUpdateSteps(); | |
184 } | |
185 | |
186 String DOMURLSearchParams::getFirstValue(const String& name) const | |
187 { | |
188 for (Vector<std::pair<String, String> >::const_iterator it = m_params.begin( ); it != m_params.end(); ++it) { | |
189 if (it->first == name) | |
190 return it->second; | |
191 } | |
192 return String(); | |
193 } | |
194 | |
195 Vector<String> DOMURLSearchParams::getAllValues(const String& name) const | |
196 { | |
197 Vector<String> result; | |
198 for (Vector<std::pair<String, String> >::const_iterator it = m_params.begin( ); it != m_params.end(); ++it) { | |
199 if (it->first == name) | |
200 result.append(it->second); | |
201 } | |
202 return result; | |
203 } | |
204 | |
205 bool DOMURLSearchParams::hasName(const String& name) const | |
206 { | |
207 for (Vector<std::pair<String, String> >::const_iterator it = m_params.begin( ); it != m_params.end(); ++it) { | |
208 if (it->first == name) | |
209 return true; | |
210 } | |
211 return false; | |
212 } | |
213 | |
214 void DOMURLSearchParams::setNameValue(const String& name, const String& value) | |
215 { | |
216 bool foundMatch = false; | |
217 for (unsigned i = 0; i < m_params.size();) { | |
218 if (m_params[i].first == name) { | |
219 if (!foundMatch) { | |
220 m_params[i++].second = value; | |
221 foundMatch = true; | |
222 } else { | |
223 m_params.remove(i); | |
224 } | |
225 } else { | |
226 i++; | |
227 } | |
228 } | |
229 if (!foundMatch) | |
230 appendNameValue(name, value); | |
231 else | |
232 runUpdateSteps(); | |
233 } | |
234 | |
235 } // namespace WebCore | |
OLD | NEW |