Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(186)

Side by Side Diff: third_party/WebKit/Source/platform/weborigin/KURL.cpp

Issue 2463703002: Optimize KURL protocols (Closed)
Patch Set: add dchecks Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 /* 1 /*
2 * Copyright (C) 2004, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved. 2 * Copyright (C) 2004, 2007, 2008, 2011, 2012 Apple Inc. All rights reserved.
3 * Copyright (C) 2012 Research In Motion Limited. All rights reserved. 3 * Copyright (C) 2012 Research In Motion Limited. All rights reserved.
4 * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved. 4 * Copyright (C) 2008, 2009, 2011 Google Inc. All rights reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
(...skipping 16 matching lines...) Expand all
27 27
28 #include "platform/weborigin/KURL.h" 28 #include "platform/weborigin/KURL.h"
29 29
30 #include "platform/weborigin/KnownPorts.h" 30 #include "platform/weborigin/KnownPorts.h"
31 #include "url/url_util.h" 31 #include "url/url_util.h"
32 #include "wtf/MathExtras.h" 32 #include "wtf/MathExtras.h"
33 #include "wtf/PtrUtil.h" 33 #include "wtf/PtrUtil.h"
34 #include "wtf/StdLibExtras.h" 34 #include "wtf/StdLibExtras.h"
35 #include "wtf/text/CString.h" 35 #include "wtf/text/CString.h"
36 #include "wtf/text/StringHash.h" 36 #include "wtf/text/StringHash.h"
37 #include "wtf/text/StringStatics.h"
37 #include "wtf/text/StringUTF8Adaptor.h" 38 #include "wtf/text/StringUTF8Adaptor.h"
38 #include "wtf/text/TextEncoding.h" 39 #include "wtf/text/TextEncoding.h"
39 #include <algorithm> 40 #include <algorithm>
40 #ifndef NDEBUG 41 #ifndef NDEBUG
41 #include <stdio.h> 42 #include <stdio.h>
42 #endif 43 #endif
43 44
44 namespace blink { 45 namespace blink {
45 46
46 static const int maximumValidPortNumber = 0xFFFE; 47 static const int maximumValidPortNumber = 0xFFFE;
47 static const int invalidPortNumber = 0xFFFF; 48 static const int invalidPortNumber = 0xFFFF;
48 49
49 static void assertProtocolIsGood(const char* protocol) { 50 static void assertProtocolIsGood(const char* protocol) {
50 #if ENABLE(ASSERT) 51 #if ENABLE(ASSERT)
52 DCHECK_NE(protocol, "");
51 const char* p = protocol; 53 const char* p = protocol;
52 while (*p) { 54 while (*p) {
53 ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z')); 55 ASSERT(*p > ' ' && *p < 0x7F && !(*p >= 'A' && *p <= 'Z'));
54 ++p; 56 ++p;
55 } 57 }
56 #endif 58 #endif
57 } 59 }
58 60
59 // Note: You must ensure that |spec| is a valid canonicalized URL before calling 61 // Note: You must ensure that |spec| is a valid canonicalized URL before calling
60 // this function. 62 // this function.
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
234 init(base, relative, &encoding.encodingForFormSubmission()); 236 init(base, relative, &encoding.encodingForFormSubmission());
235 } 237 }
236 238
237 KURL::KURL(const AtomicString& canonicalString, 239 KURL::KURL(const AtomicString& canonicalString,
238 const url::Parsed& parsed, 240 const url::Parsed& parsed,
239 bool isValid) 241 bool isValid)
240 : m_isValid(isValid), 242 : m_isValid(isValid),
241 m_protocolIsInHTTPFamily(false), 243 m_protocolIsInHTTPFamily(false),
242 m_parsed(parsed), 244 m_parsed(parsed),
243 m_string(canonicalString) { 245 m_string(canonicalString) {
244 initProtocolIsInHTTPFamily(); 246 initProtocolMetadata();
245 initInnerURL(); 247 initInnerURL();
246 } 248 }
247 249
248 KURL::KURL(WTF::HashTableDeletedValueType) 250 KURL::KURL(WTF::HashTableDeletedValueType)
249 : m_isValid(false), 251 : m_isValid(false),
250 m_protocolIsInHTTPFamily(false), 252 m_protocolIsInHTTPFamily(false),
251 m_string(WTF::HashTableDeletedValue) {} 253 m_string(WTF::HashTableDeletedValue) {}
252 254
253 KURL::KURL(const KURL& other) 255 KURL::KURL(const KURL& other)
254 : m_isValid(other.m_isValid), 256 : m_isValid(other.m_isValid),
255 m_protocolIsInHTTPFamily(other.m_protocolIsInHTTPFamily), 257 m_protocolIsInHTTPFamily(other.m_protocolIsInHTTPFamily),
258 m_protocol(other.m_protocol),
256 m_parsed(other.m_parsed), 259 m_parsed(other.m_parsed),
257 m_string(other.m_string) { 260 m_string(other.m_string) {
258 if (other.m_innerURL.get()) 261 if (other.m_innerURL.get())
259 m_innerURL = WTF::wrapUnique(new KURL(other.m_innerURL->copy())); 262 m_innerURL = WTF::wrapUnique(new KURL(other.m_innerURL->copy()));
260 } 263 }
261 264
262 KURL::~KURL() {} 265 KURL::~KURL() {}
263 266
264 KURL& KURL::operator=(const KURL& other) { 267 KURL& KURL::operator=(const KURL& other) {
265 m_isValid = other.m_isValid; 268 m_isValid = other.m_isValid;
266 m_protocolIsInHTTPFamily = other.m_protocolIsInHTTPFamily; 269 m_protocolIsInHTTPFamily = other.m_protocolIsInHTTPFamily;
270 m_protocol = other.m_protocol;
267 m_parsed = other.m_parsed; 271 m_parsed = other.m_parsed;
268 m_string = other.m_string; 272 m_string = other.m_string;
269 if (other.m_innerURL) 273 if (other.m_innerURL)
270 m_innerURL = WTF::wrapUnique(new KURL(other.m_innerURL->copy())); 274 m_innerURL = WTF::wrapUnique(new KURL(other.m_innerURL->copy()));
271 else 275 else
272 m_innerURL.reset(); 276 m_innerURL.reset();
273 return *this; 277 return *this;
274 } 278 }
275 279
276 KURL KURL::copy() const { 280 KURL KURL::copy() const {
277 KURL result; 281 KURL result;
278 result.m_isValid = m_isValid; 282 result.m_isValid = m_isValid;
279 result.m_protocolIsInHTTPFamily = m_protocolIsInHTTPFamily; 283 result.m_protocolIsInHTTPFamily = m_protocolIsInHTTPFamily;
284 result.m_protocol = m_protocol.isolatedCopy();
280 result.m_parsed = m_parsed; 285 result.m_parsed = m_parsed;
281 result.m_string = m_string.isolatedCopy(); 286 result.m_string = m_string.isolatedCopy();
282 if (m_innerURL) 287 if (m_innerURL)
283 result.m_innerURL = WTF::wrapUnique(new KURL(m_innerURL->copy())); 288 result.m_innerURL = WTF::wrapUnique(new KURL(m_innerURL->copy()));
284 return result; 289 return result;
285 } 290 }
286 291
287 bool KURL::isNull() const { 292 bool KURL::isNull() const {
288 return m_string.isNull(); 293 return m_string.isNull();
289 } 294 }
(...skipping 15 matching lines...) Expand all
305 } 310 }
306 311
307 bool KURL::hasPath() const { 312 bool KURL::hasPath() const {
308 // Note that http://www.google.com/" has a path, the path is "/". This can 313 // Note that http://www.google.com/" has a path, the path is "/". This can
309 // return false only for invalid or nonstandard URLs. 314 // return false only for invalid or nonstandard URLs.
310 return m_parsed.path.len >= 0; 315 return m_parsed.path.len >= 0;
311 } 316 }
312 317
313 String KURL::lastPathComponent() const { 318 String KURL::lastPathComponent() const {
314 if (!m_isValid) 319 if (!m_isValid)
315 return stringForInvalidComponent(); 320 return stringViewForInvalidComponent().toString();
316 ASSERT(!m_string.isNull()); 321 ASSERT(!m_string.isNull());
317 322
318 // When the output ends in a slash, WebCore has different expectations than 323 // When the output ends in a slash, WebCore has different expectations than
319 // the GoogleURL library. For "/foo/bar/" the library will return the empty 324 // the GoogleURL library. For "/foo/bar/" the library will return the empty
320 // string, but WebCore wants "bar". 325 // string, but WebCore wants "bar".
321 url::Component path = m_parsed.path; 326 url::Component path = m_parsed.path;
322 if (path.len > 0 && m_string[path.end() - 1] == '/') 327 if (path.len > 0 && m_string[path.end() - 1] == '/')
323 path.len--; 328 path.len--;
324 329
325 url::Component file; 330 url::Component file;
326 if (m_string.is8Bit()) 331 if (m_string.is8Bit())
327 url::ExtractFileName(asURLChar8Subtle(m_string), path, &file); 332 url::ExtractFileName(asURLChar8Subtle(m_string), path, &file);
328 else 333 else
329 url::ExtractFileName(m_string.characters16(), path, &file); 334 url::ExtractFileName(m_string.characters16(), path, &file);
330 335
331 // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns 336 // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns
332 // a null string when the path is empty, which we duplicate here. 337 // a null string when the path is empty, which we duplicate here.
333 if (!file.is_nonempty()) 338 if (!file.is_nonempty())
334 return String(); 339 return String();
335 return componentString(file); 340 return componentString(file);
336 } 341 }
337 342
338 String KURL::protocol() const { 343 String KURL::protocol() const {
339 return componentString(m_parsed.scheme); 344 DCHECK_EQ(componentString(m_parsed.scheme), m_protocol);
345 return m_protocol;
340 } 346 }
341 347
342 String KURL::host() const { 348 String KURL::host() const {
343 return componentString(m_parsed.host); 349 return componentString(m_parsed.host);
344 } 350 }
345 351
346 // Returns 0 when there is no port. 352 // Returns 0 when there is no port.
347 // 353 //
348 // We treat URL's with out-of-range port numbers as invalid URLs, and they will 354 // We treat URL's with out-of-range port numbers as invalid URLs, and they will
349 // be rejected by the canonicalizer. KURL.cpp will allow them in parsing, but 355 // be rejected by the canonicalizer. KURL.cpp will allow them in parsing, but
350 // return invalidPortNumber from this port() function, so we mirror that 356 // return invalidPortNumber from this port() function, so we mirror that
351 // behavior here. 357 // behavior here.
352 unsigned short KURL::port() const { 358 unsigned short KURL::port() const {
353 if (!m_isValid || m_parsed.port.len <= 0) 359 if (!m_isValid || m_parsed.port.len <= 0)
354 return 0; 360 return 0;
355 ASSERT(!m_string.isNull()); 361 ASSERT(!m_string.isNull());
356 int port = m_string.is8Bit() 362 int port = m_string.is8Bit()
357 ? url::ParsePort(asURLChar8Subtle(m_string), m_parsed.port) 363 ? url::ParsePort(asURLChar8Subtle(m_string), m_parsed.port)
358 : url::ParsePort(m_string.characters16(), m_parsed.port); 364 : url::ParsePort(m_string.characters16(), m_parsed.port);
359 ASSERT(port != url::PORT_UNSPECIFIED); // Checked port.len <= 0 before. 365 ASSERT(port != url::PORT_UNSPECIFIED); // Checked port.len <= 0 before.
360 366
361 if (port == url::PORT_INVALID || 367 if (port == url::PORT_INVALID ||
362 port > maximumValidPortNumber) // Mimic KURL::port() 368 port > maximumValidPortNumber) // Mimic KURL::port()
363 port = invalidPortNumber; 369 port = invalidPortNumber;
364 370
365 return static_cast<unsigned short>(port); 371 return static_cast<unsigned short>(port);
366 } 372 }
367 373
374 // TODO(csharrison): Migrate pass() and user() to return a StringView. Most
375 // consumers just need to know if the string is empty.
376
368 String KURL::pass() const { 377 String KURL::pass() const {
369 // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns 378 // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns
370 // a null string when the password is empty, which we duplicate here. 379 // a null string when the password is empty, which we duplicate here.
371 if (!m_parsed.password.is_nonempty()) 380 if (!m_parsed.password.is_nonempty())
372 return String(); 381 return String();
373 return componentString(m_parsed.password); 382 return componentString(m_parsed.password);
374 } 383 }
375 384
376 String KURL::user() const { 385 String KURL::user() const {
377 return componentString(m_parsed.username); 386 return componentString(m_parsed.username);
(...skipping 382 matching lines...) Expand 10 before | Expand all | Expand 10 after
760 // non-Atomic input as Atomic here, we will render the (const) input string 769 // non-Atomic input as Atomic here, we will render the (const) input string
761 // thread unsafe. 770 // thread unsafe.
762 if (!relative.isNull() && relative.impl()->isAtomic() && 771 if (!relative.isNull() && relative.impl()->isAtomic() &&
763 StringView(output.data(), static_cast<unsigned>(output.length())) == 772 StringView(output.data(), static_cast<unsigned>(output.length())) ==
764 relative) { 773 relative) {
765 m_string = relative; 774 m_string = relative;
766 } else { 775 } else {
767 m_string = AtomicString::fromUTF8(output.data(), output.length()); 776 m_string = AtomicString::fromUTF8(output.data(), output.length());
768 } 777 }
769 778
770 initProtocolIsInHTTPFamily(); 779 initProtocolMetadata();
771 initInnerURL(); 780 initInnerURL();
772 DCHECK_EQ(protocol(), protocol().lower());
773 } 781 }
774 782
775 void KURL::initInnerURL() { 783 void KURL::initInnerURL() {
776 if (!m_isValid) { 784 if (!m_isValid) {
777 m_innerURL.reset(); 785 m_innerURL.reset();
778 return; 786 return;
779 } 787 }
780 if (url::Parsed* innerParsed = m_parsed.inner_parsed()) 788 if (url::Parsed* innerParsed = m_parsed.inner_parsed())
781 m_innerURL = WTF::wrapUnique(new KURL( 789 m_innerURL = WTF::wrapUnique(new KURL(
782 ParsedURLString, 790 ParsedURLString,
783 m_string.substring(innerParsed->scheme.begin, 791 m_string.substring(innerParsed->scheme.begin,
784 innerParsed->Length() - innerParsed->scheme.begin))); 792 innerParsed->Length() - innerParsed->scheme.begin)));
785 else 793 else
786 m_innerURL.reset(); 794 m_innerURL.reset();
787 } 795 }
788 796
789 template <typename CHAR> 797 void KURL::initProtocolMetadata() {
790 bool internalProtocolIs(const url::Component& scheme,
791 const CHAR* spec,
792 const char* protocol) {
793 const CHAR* begin = spec + scheme.begin;
794 const CHAR* end = begin + scheme.len;
795
796 while (begin != end && *protocol) {
797 ASSERT(toASCIILower(*protocol) == *protocol);
798 if (toASCIILower(*begin++) != *protocol++)
799 return false;
800 }
801
802 // Both strings are equal (ignoring case) if and only if all of the characters
803 // were equal, and the end of both has been reached.
804 return begin == end && !*protocol;
805 }
806
807 template <typename CHAR>
808 bool checkIfProtocolIsInHTTPFamily(const url::Component& scheme,
809 const CHAR* spec) {
810 if (scheme.len == 4)
811 return internalProtocolIs(scheme, spec, "http");
812 if (scheme.len == 5)
813 return internalProtocolIs(scheme, spec, "https");
814 if (scheme.len == 7)
815 return internalProtocolIs(scheme, spec, "http-so");
816 if (scheme.len == 8)
817 return internalProtocolIs(scheme, spec, "https-so");
818 return false;
819 }
820
821 void KURL::initProtocolIsInHTTPFamily() {
822 if (!m_isValid) { 798 if (!m_isValid) {
823 m_protocolIsInHTTPFamily = false; 799 m_protocolIsInHTTPFamily = false;
800 m_protocol = componentString(m_parsed.scheme);
824 return; 801 return;
825 } 802 }
826 803
827 ASSERT(!m_string.isNull()); 804 DCHECK(!m_string.isNull());
828 m_protocolIsInHTTPFamily = 805 StringView protocol = componentStringView(m_parsed.scheme);
829 m_string.is8Bit() ? checkIfProtocolIsInHTTPFamily(m_parsed.scheme, 806 m_protocolIsInHTTPFamily = true;
830 m_string.characters8()) 807 if (protocol == WTF::httpsAtom) {
831 : checkIfProtocolIsInHTTPFamily( 808 m_protocol = WTF::httpsAtom;
832 m_parsed.scheme, m_string.characters16()); 809 } else if (protocol == WTF::httpAtom) {
810 m_protocol = WTF::httpAtom;
811 } else {
812 m_protocol = AtomicString(protocol.toString());
813 m_protocolIsInHTTPFamily =
814 m_protocol == "http-so" || m_protocol == "https-so";
815 }
816 DCHECK_EQ(m_protocol, m_protocol.lower());
833 } 817 }
834 818
835 bool KURL::protocolIs(const char* protocol) const { 819 bool KURL::protocolIs(const char* protocol) const {
836 assertProtocolIsGood(protocol); 820 assertProtocolIsGood(protocol);
837 821
838 // JavaScript URLs are "valid" and should be executed even if KURL decides 822 // JavaScript URLs are "valid" and should be executed even if KURL decides
839 // they are invalid. The free function protocolIsJavaScript() should be used 823 // they are invalid. The free function protocolIsJavaScript() should be used
840 // instead. 824 // instead.
841 // FIXME: Chromium code needs to be fixed for this assert to be enabled. 825 // FIXME: Chromium code needs to be fixed for this assert to be enabled.
842 // ASSERT(strcmp(protocol, "javascript")); 826 // ASSERT(strcmp(protocol, "javascript"));
843 827 return m_protocol == protocol;
844 if (m_string.isNull() || m_parsed.scheme.len <= 0)
845 return *protocol == '\0';
846
847 return m_string.is8Bit()
848 ? internalProtocolIs(m_parsed.scheme, m_string.characters8(),
849 protocol)
850 : internalProtocolIs(m_parsed.scheme, m_string.characters16(),
851 protocol);
852 } 828 }
853 829
854 String KURL::stringForInvalidComponent() const { 830 StringView KURL::stringViewForInvalidComponent() const {
855 if (m_string.isNull()) 831 return m_string.isNull() ? StringView() : StringView("", 0);
856 return String();
857 return emptyString();
858 } 832 }
859 833
860 String KURL::componentString(const url::Component& component) const { 834 StringView KURL::componentStringView(const url::Component& component) const {
861 if (!m_isValid || component.len <= 0) 835 if (!m_isValid || component.len <= 0)
862 return stringForInvalidComponent(); 836 return stringViewForInvalidComponent();
863 // begin and len are in terms of bytes which do not match 837 // begin and len are in terms of bytes which do not match
864 // if string() is UTF-16 and input contains non-ASCII characters. 838 // if string() is UTF-16 and input contains non-ASCII characters.
865 // However, the only part in urlString that can contain non-ASCII 839 // However, the only part in urlString that can contain non-ASCII
866 // characters is 'ref' at the end of the string. In that case, 840 // characters is 'ref' at the end of the string. In that case,
867 // begin will always match the actual value and len (in terms of 841 // begin will always match the actual value and len (in terms of
868 // byte) will be longer than what's needed by 'mid'. However, mid 842 // byte) will be longer than what's needed by 'mid'. However, mid
869 // truncates len to avoid go past the end of a string so that we can 843 // truncates len to avoid go past the end of a string so that we can
870 // get away without doing anything here. 844 // get away without doing anything here.
871 return getString().substring(component.begin, component.len); 845
846 int maxLength = getString().length() - component.begin;
847 return StringView(getString(), component.begin,
848 component.len > maxLength ? maxLength : component.len);
849 }
850
851 String KURL::componentString(const url::Component& component) const {
852 return componentStringView(component).toString();
872 } 853 }
873 854
874 template <typename CHAR> 855 template <typename CHAR>
875 void KURL::replaceComponents(const url::Replacements<CHAR>& replacements) { 856 void KURL::replaceComponents(const url::Replacements<CHAR>& replacements) {
876 url::RawCanonOutputT<char> output; 857 url::RawCanonOutputT<char> output;
877 url::Parsed newParsed; 858 url::Parsed newParsed;
878 859
879 StringUTF8Adaptor utf8(m_string); 860 StringUTF8Adaptor utf8(m_string);
880 m_isValid = url::ReplaceComponents(utf8.data(), utf8.length(), m_parsed, 861 m_isValid = url::ReplaceComponents(utf8.data(), utf8.length(), m_parsed,
881 replacements, 0, &output, &newParsed); 862 replacements, 0, &output, &newParsed);
882 863
883 m_parsed = newParsed; 864 m_parsed = newParsed;
884 m_string = AtomicString::fromUTF8(output.data(), output.length()); 865 m_string = AtomicString::fromUTF8(output.data(), output.length());
866 initProtocolMetadata();
885 } 867 }
886 868
887 bool KURL::isSafeToSendToAnotherThread() const { 869 bool KURL::isSafeToSendToAnotherThread() const {
888 return m_string.isSafeToSendToAnotherThread() && 870 return m_string.isSafeToSendToAnotherThread() &&
889 (!m_innerURL || m_innerURL->isSafeToSendToAnotherThread()); 871 (!m_innerURL || m_innerURL->isSafeToSendToAnotherThread());
890 } 872 }
891 873
892 } // namespace blink 874 } // namespace blink
OLDNEW
« no previous file with comments | « third_party/WebKit/Source/platform/weborigin/KURL.h ('k') | third_party/WebKit/Source/platform/weborigin/KURLTest.cpp » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698