Integrate most of GoogleURL in WTFURL
[WebKit-https.git] / Source / WebCore / platform / KURLWTFURL.cpp
1 /*
2  * Copyright (C) 2012 Apple 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 COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "KURL.h"
28
29 #include <wtf/DataLog.h>
30
31 #if USE(WTFURL)
32
33 using namespace WTF;
34
35 namespace WebCore {
36
37 static const unsigned maximumValidPortNumber = 0xFFFE;
38 static const unsigned invalidPortNumber = 0xFFFF;
39
40 static inline void detach(RefPtr<KURLWTFURLImpl>& urlImpl)
41 {
42     if (!urlImpl)
43         return;
44
45     if (urlImpl->hasOneRef())
46         return;
47
48     urlImpl = urlImpl->copy();
49 }
50
51 KURL::KURL(ParsedURLStringTag, const String& urlString)
52     : m_urlImpl(adoptRef(new KURLWTFURLImpl()))
53 {
54     m_urlImpl->m_parsedURL = ParsedURL(urlString);
55
56     // FIXME: Frame::init() actually create empty URL, investigate why not just null URL.
57     // ASSERT(m_urlImpl->m_parsedURL.isValid());
58 }
59
60 KURL::KURL(const KURL& baseURL, const String& relative)
61     : m_urlImpl(adoptRef(new KURLWTFURLImpl()))
62 {
63     // FIXME: the case with a null baseURL is common. We should have a separate constructor in KURL.
64     // FIXME: the case of an empty Base is useless, we should get rid of empty URLs.
65     if (baseURL.isEmpty())
66         m_urlImpl->m_parsedURL = ParsedURL(relative);
67     else
68         m_urlImpl->m_parsedURL = ParsedURL(baseURL.m_urlImpl->m_parsedURL, relative);
69
70     if (!m_urlImpl->m_parsedURL.isValid())
71         m_urlImpl->m_invalidUrlString = relative;
72 }
73
74 KURL::KURL(const KURL& baseURL, const String& relative, const TextEncoding&)
75     : m_urlImpl(adoptRef(new KURLWTFURLImpl()))
76 {
77     // FIXME: handle the encoding.
78     if (baseURL.isEmpty())
79         m_urlImpl->m_parsedURL = ParsedURL(relative);
80     else
81         m_urlImpl->m_parsedURL = ParsedURL(baseURL.m_urlImpl->m_parsedURL, relative);
82
83     if (!m_urlImpl->m_parsedURL.isValid())
84         m_urlImpl->m_invalidUrlString = relative;
85 }
86
87 KURL KURL::copy() const
88 {
89     KURL other;
90     if (!isNull())
91         other.m_urlImpl = m_urlImpl->copy();
92     return other;
93 }
94
95 bool KURL::isNull() const
96 {
97     return !m_urlImpl;
98 }
99
100 // FIXME: Can we get rid of the concept of EmptyURL? Can an null URL be enough?
101 // If we cannot get rid of the concept, we should make a shared empty URL.
102 bool KURL::isEmpty() const
103 {
104     return !m_urlImpl
105            || (!m_urlImpl->m_parsedURL.isValid() && m_urlImpl->m_invalidUrlString.isEmpty());
106 }
107
108 bool KURL::isValid() const
109 {
110     if (!m_urlImpl)
111         return false;
112
113     bool isParsedURLValid = m_urlImpl->m_parsedURL.isValid();
114 #ifndef NDEBUG
115     if (isParsedURLValid)
116         ASSERT_WITH_MESSAGE(m_urlImpl->m_invalidUrlString.isNull(), "A valid URL must have a null invalidUrlString.");
117 #endif
118     return isParsedURLValid;
119 }
120
121 const String& KURL::string() const
122 {
123     if (isNull())
124         return emptyString();
125
126     if (isValid())
127         return m_urlImpl->m_parsedURL.spec().string();
128
129     return m_urlImpl->m_invalidUrlString;
130 }
131
132 String KURL::protocol() const
133 {
134     // Skip the ASSERT for now, SubframeLoader::requestFrame() does not check the validity of URLs.
135     // ASSERT(isValid());
136     if (!isValid())
137         return String();
138     return m_urlImpl->m_parsedURL.scheme();
139 }
140
141 String KURL::host() const
142 {
143     // Skip the ASSERT for now, HTMLAnchorElement::parseAttribute() does not check the validity of URLs.
144     // ASSERT(isValid());
145     if (!isValid())
146         return String();
147     return m_urlImpl->m_parsedURL.host();
148 }
149
150 bool KURL::hasPort() const
151 {
152     // This should be an ASSERT. HTMLAnchorElement::port() does not check the validity of the URL.
153     if (!isValid())
154         return false;
155
156     return !m_urlImpl->m_parsedURL.port().isNull();
157 }
158
159 unsigned short KURL::port() const
160 {
161     ASSERT(isValid());
162
163     String portString = m_urlImpl->m_parsedURL.port();
164     if (portString.isNull())
165         return 0;
166
167     bool ok = false;
168     unsigned portValue = portString.toUIntStrict(&ok);
169
170     if (!ok || portValue > maximumValidPortNumber)
171         return invalidPortNumber;
172
173     return static_cast<unsigned short>(portValue);
174 }
175
176 String KURL::user() const
177 {
178     // FIXME: this should be an ASSERT(), call site should not use invalid URLs.
179     if (!isValid())
180         return String();
181
182     return m_urlImpl->m_parsedURL.username();
183 }
184
185 String KURL::pass() const
186 {
187     // FIXME: this should be an ASSERT(), call site should not use invalid URLs.
188     if (!isValid())
189         return String();
190
191     return m_urlImpl->m_parsedURL.password();
192 }
193
194 bool KURL::hasPath() const
195 {
196     // FIXME: this should be an ASSERTION, call site should not use invalid URLs.
197     if (!isValid())
198         return false;
199
200     return !path().isEmpty();
201 }
202
203 String KURL::path() const
204 {
205     // FIXME: this should be an ASSERTION, HTMLAnchorElement should not use invalid URLs.
206     if (!isValid())
207         return String();
208
209     return m_urlImpl->m_parsedURL.path();
210 }
211
212 String KURL::lastPathComponent() const
213 {
214     ASSERT(isValid());
215
216     String pathString = path();
217     size_t index = pathString.reverseFind('/');
218
219     if (index == notFound)
220         return pathString;
221
222     return pathString.substring(index + 1);
223 }
224
225 String KURL::query() const
226 {
227     // FIXME: this should be an ASSERTION, HTMLAnchorElement should not use invalid URLs.
228     if (!isValid())
229         return String();
230
231     return m_urlImpl->m_parsedURL.query();
232 }
233
234 bool KURL::hasFragmentIdentifier() const
235 {
236     // Skip the ASSERT for now, ScriptElement::requestScript() create requests for invalid URLs.
237     // ASSERT(isValid());
238     if (!isValid())
239         return false;
240
241     return m_urlImpl->m_parsedURL.hasFragment();
242 }
243
244 String KURL::fragmentIdentifier() const
245 {
246     // Skip the ASSERT for now, ScriptElement::requestScript() create requests for invalid URLs.
247     // ASSERT(isValid());
248     if (!isValid())
249         return String();
250
251     return m_urlImpl->m_parsedURL.fragment();
252 }
253
254 // FIXME: track an fix the bad use of this method.
255 String KURL::baseAsString() const
256 {
257     ASSERT(isValid());
258     return m_urlImpl->m_parsedURL.baseAsString();
259 }
260
261 // FIXME: Get rid of this function from KURL.
262 String KURL::fileSystemPath() const
263 {
264     return string();
265 }
266
267 bool KURL::protocolIs(const char* testProtocol) const
268 {
269     if (!isValid())
270         return false;
271     return WebCore::protocolIs(protocol(), testProtocol);
272 }
273
274 bool KURL::protocolIsInHTTPFamily() const
275 {
276     return protocolIs("http") || protocolIs("https");
277 }
278
279 bool KURL::setProtocol(const String&)
280 {
281     detach(m_urlImpl);
282     // FIXME: Add WTFURL Implementation.
283     return false;
284 }
285
286 void KURL::setHost(const String&)
287 {
288     detach(m_urlImpl);
289     // FIXME: Add WTFURL Implementation.
290 }
291
292 void KURL::removePort()
293 {
294     detach(m_urlImpl);
295     // FIXME: Add WTFURL Implementation.
296 }
297
298 void KURL::setPort(unsigned short)
299 {
300     detach(m_urlImpl);
301     // FIXME: Add WTFURL Implementation.
302 }
303
304 void KURL::setHostAndPort(const String&)
305 {
306     detach(m_urlImpl);
307     // FIXME: Add WTFURL Implementation.
308 }
309
310 void KURL::setUser(const String&)
311 {
312     detach(m_urlImpl);
313     // FIXME: Add WTFURL Implementation.
314 }
315
316 void KURL::setPass(const String&)
317 {
318     detach(m_urlImpl);
319     // FIXME: Add WTFURL Implementation.
320 }
321
322 void KURL::setPath(const String&)
323 {
324     detach(m_urlImpl);
325     // FIXME: Add WTFURL Implementation.
326 }
327
328 void KURL::setQuery(const String&)
329 {
330     detach(m_urlImpl);
331     // FIXME: Add WTFURL Implementation.
332 }
333
334 void KURL::setFragmentIdentifier(const String&)
335 {
336     detach(m_urlImpl);
337     // FIXME: Add WTFURL Implementation.
338 }
339
340 void KURL::removeFragmentIdentifier()
341 {
342     if (!hasFragmentIdentifier())
343         return;
344
345     detach(m_urlImpl);
346     m_urlImpl->m_parsedURL = m_urlImpl->m_parsedURL.withoutFragment();
347 }
348
349 unsigned KURL::hostStart() const
350 {
351     // FIXME: Add WTFURL Implementation.
352     return 0;
353 }
354
355 unsigned KURL::hostEnd() const
356 {
357     // FIXME: Add WTFURL Implementation.
358     return 0;
359 }
360
361 unsigned KURL::pathStart() const
362 {
363     // FIXME: Add WTFURL Implementation.
364     return 0;
365 }
366
367 unsigned KURL::pathEnd() const
368 {
369     // FIXME: Add WTFURL Implementation.
370     return 0;
371 }
372
373 unsigned KURL::pathAfterLastSlash() const
374 {
375     // FIXME: Add WTFURL Implementation.
376     return 0;
377 }
378
379 #ifndef NDEBUG
380 void KURL::print() const
381 {
382     if (isValid())
383         m_urlImpl->m_parsedURL.print();
384     else {
385         if (isNull())
386             dataLog("Null KURL");
387         else if (isEmpty())
388             dataLog("Empty KURL");
389         else {
390             dataLog("Invalid KURL from string =");
391             m_urlImpl->m_invalidUrlString.show();
392         }
393     }
394 }
395 #endif
396
397 void KURL::invalidate()
398 {
399     m_urlImpl = nullptr;
400 }
401
402 bool KURL::isHierarchical() const
403 {
404     // FIXME: Add WTFURL Implementation.
405     return false;
406 }
407
408 bool protocolIs(const String&, const char*)
409 {
410     // FIXME: Add WTFURL Implementation.
411     return false;
412 }
413
414 bool equalIgnoringFragmentIdentifier(const KURL&, const KURL&)
415 {
416     // FIXME: Add WTFURL Implementation.
417     return false;
418 }
419
420 bool protocolHostAndPortAreEqual(const KURL& a, const KURL& b)
421 {
422     if (!a.isValid() || !b.isValid())
423         return false;
424
425     return a.protocol() == b.protocol()
426            && a.host() == b.host()
427            && a.port() == b.port();
428 }
429
430 String encodeWithURLEscapeSequences(const String&)
431 {
432     // FIXME: Add WTFURL Implementation.
433     return String();
434 }
435
436 String decodeURLEscapeSequences(const String&)
437 {
438     // FIXME: Add WTFURL Implementation.
439     return String();
440 }
441
442 String decodeURLEscapeSequences(const String&, const TextEncoding&)
443 {
444     // FIXME: Add WTFURL Implementation.
445     return String();
446 }
447
448 }
449
450 #endif // USE(WTFURL)