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

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

Issue 2463703002: Optimize KURL protocols (Closed)
Patch Set: simplify 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 = wrapUnique(new KURL(other.m_innerURL->copy())); 262 m_innerURL = 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 = wrapUnique(new KURL(other.m_innerURL->copy())); 274 m_innerURL = 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 = wrapUnique(new KURL(m_innerURL->copy())); 288 result.m_innerURL = 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 39 matching lines...) Expand 10 before | Expand all | Expand 10 after
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 return m_protocol;
340 } 345 }
341 346
342 String KURL::host() const { 347 String KURL::host() const {
343 return componentString(m_parsed.host); 348 return componentString(m_parsed.host);
344 } 349 }
345 350
346 // Returns 0 when there is no port. 351 // Returns 0 when there is no port.
347 // 352 //
348 // We treat URL's with out-of-range port numbers as invalid URLs, and they will 353 // 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 354 // be rejected by the canonicalizer. KURL.cpp will allow them in parsing, but
350 // return invalidPortNumber from this port() function, so we mirror that 355 // return invalidPortNumber from this port() function, so we mirror that
351 // behavior here. 356 // behavior here.
352 unsigned short KURL::port() const { 357 unsigned short KURL::port() const {
353 if (!m_isValid || m_parsed.port.len <= 0) 358 if (!m_isValid || m_parsed.port.len <= 0)
354 return 0; 359 return 0;
355 ASSERT(!m_string.isNull()); 360 ASSERT(!m_string.isNull());
356 int port = m_string.is8Bit() 361 int port = m_string.is8Bit()
357 ? url::ParsePort(asURLChar8Subtle(m_string), m_parsed.port) 362 ? url::ParsePort(asURLChar8Subtle(m_string), m_parsed.port)
358 : url::ParsePort(m_string.characters16(), m_parsed.port); 363 : url::ParsePort(m_string.characters16(), m_parsed.port);
359 ASSERT(port != url::PORT_UNSPECIFIED); // Checked port.len <= 0 before. 364 ASSERT(port != url::PORT_UNSPECIFIED); // Checked port.len <= 0 before.
360 365
361 if (port == url::PORT_INVALID || 366 if (port == url::PORT_INVALID ||
362 port > maximumValidPortNumber) // Mimic KURL::port() 367 port > maximumValidPortNumber) // Mimic KURL::port()
363 port = invalidPortNumber; 368 port = invalidPortNumber;
364 369
365 return static_cast<unsigned short>(port); 370 return static_cast<unsigned short>(port);
366 } 371 }
367 372
373 // TODO(csharrison): Migrate pass() and user() to return a StringView. Most
374 // consumers just need to know if the string is empty.
375
368 String KURL::pass() const { 376 String KURL::pass() const {
369 // Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns 377 // 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. 378 // a null string when the password is empty, which we duplicate here.
371 if (!m_parsed.password.is_nonempty()) 379 if (!m_parsed.password.is_nonempty())
372 return String(); 380 return String();
373 return componentString(m_parsed.password); 381 return componentString(m_parsed.password);
374 } 382 }
375 383
376 String KURL::user() const { 384 String KURL::user() const {
377 return componentString(m_parsed.username); 385 return componentString(m_parsed.username);
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 if (!url::CanonicalizeScheme(newProtocolUTF8.data(), 434 if (!url::CanonicalizeScheme(newProtocolUTF8.data(),
427 url::Component(0, newProtocolUTF8.length()), 435 url::Component(0, newProtocolUTF8.length()),
428 &canonProtocol, &protocolComponent) || 436 &canonProtocol, &protocolComponent) ||
429 !protocolComponent.is_nonempty()) 437 !protocolComponent.is_nonempty())
430 return false; 438 return false;
431 439
432 url::Replacements<char> replacements; 440 url::Replacements<char> replacements;
433 replacements.SetScheme(charactersOrEmpty(newProtocolUTF8), 441 replacements.SetScheme(charactersOrEmpty(newProtocolUTF8),
434 url::Component(0, newProtocolUTF8.length())); 442 url::Component(0, newProtocolUTF8.length()));
435 replaceComponents(replacements); 443 replaceComponents(replacements);
444 initProtocolMetadata();
436 445
437 // isValid could be false but we still return true here. This is because 446 // isValid could be false but we still return true here. This is because
438 // WebCore or JS scripts can build up a URL by setting individual 447 // WebCore or JS scripts can build up a URL by setting individual
439 // components, and a JS exception is based on the return value of this 448 // components, and a JS exception is based on the return value of this
440 // function. We want to throw the exception and stop the script only when 449 // function. We want to throw the exception and stop the script only when
441 // its trying to set a bad protocol, and not when it maybe just hasn't 450 // its trying to set a bad protocol, and not when it maybe just hasn't
442 // finished building up its final scheme. 451 // finished building up its final scheme.
443 return true; 452 return true;
444 } 453 }
445 454
(...skipping 314 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()); 781 DCHECK_EQ(protocol(), protocol().lower());
773 } 782 }
774 783
775 void KURL::initInnerURL() { 784 void KURL::initInnerURL() {
776 if (!m_isValid) { 785 if (!m_isValid) {
777 m_innerURL.reset(); 786 m_innerURL.reset();
778 return; 787 return;
779 } 788 }
780 if (url::Parsed* innerParsed = m_parsed.inner_parsed()) 789 if (url::Parsed* innerParsed = m_parsed.inner_parsed())
781 m_innerURL = wrapUnique(new KURL( 790 m_innerURL = wrapUnique(new KURL(
782 ParsedURLString, 791 ParsedURLString,
783 m_string.substring(innerParsed->scheme.begin, 792 m_string.substring(innerParsed->scheme.begin,
784 innerParsed->Length() - innerParsed->scheme.begin))); 793 innerParsed->Length() - innerParsed->scheme.begin)));
785 else 794 else
786 m_innerURL.reset(); 795 m_innerURL.reset();
787 } 796 }
788 797
789 template <typename CHAR> 798 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");
esprehn 2016/12/12 22:18:46 This was all case insensitive before.
Charlie Harrison 2016/12/12 22:26:06 We should always have a canonical, lowercase schem
Charlie Harrison 2016/12/13 16:03:22 Actually, we have a DCHECK_EQ(protocol(), protocol
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) { 799 if (!m_isValid) {
823 m_protocolIsInHTTPFamily = false; 800 m_protocolIsInHTTPFamily = false;
824 return; 801 return;
825 } 802 }
826 803
827 ASSERT(!m_string.isNull()); 804 ASSERT(!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";
esprehn 2016/12/12 22:18:46 What strange protocols are these?
Charlie Harrison 2016/12/12 22:26:06 suborigin protocols: https://w3c.github.io/webapps
815 }
833 } 816 }
834 817
835 bool KURL::protocolIs(const char* protocol) const { 818 bool KURL::protocolIs(const char* protocol) const {
836 assertProtocolIsGood(protocol); 819 assertProtocolIsGood(protocol);
837 820
838 // JavaScript URLs are "valid" and should be executed even if KURL decides 821 // JavaScript URLs are "valid" and should be executed even if KURL decides
839 // they are invalid. The free function protocolIsJavaScript() should be used 822 // they are invalid. The free function protocolIsJavaScript() should be used
840 // instead. 823 // instead.
841 // FIXME: Chromium code needs to be fixed for this assert to be enabled. 824 // FIXME: Chromium code needs to be fixed for this assert to be enabled.
842 // ASSERT(strcmp(protocol, "javascript")); 825 // ASSERT(strcmp(protocol, "javascript"));
843 826 return m_protocol == protocol;
esprehn 2016/12/12 22:18:46 internalProtocolIs was case insensitive, are you s
Charlie Harrison 2016/12/12 22:26:06 assertProtocolIsGood checks that the input protoco
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 } 827 }
853 828
854 String KURL::stringForInvalidComponent() const { 829 String KURL::stringForInvalidComponent() const {
855 if (m_string.isNull()) 830 if (m_string.isNull())
856 return String(); 831 return String();
857 return emptyString(); 832 return emptyString();
858 } 833 }
859 834
860 String KURL::componentString(const url::Component& component) const { 835 StringView KURL::componentStringView(const url::Component& component) const {
861 if (!m_isValid || component.len <= 0) 836 if (!m_isValid || component.len <= 0)
862 return stringForInvalidComponent(); 837 return stringForInvalidComponent();
863 // begin and len are in terms of bytes which do not match 838 // begin and len are in terms of bytes which do not match
864 // if string() is UTF-16 and input contains non-ASCII characters. 839 // if string() is UTF-16 and input contains non-ASCII characters.
865 // However, the only part in urlString that can contain non-ASCII 840 // However, the only part in urlString that can contain non-ASCII
866 // characters is 'ref' at the end of the string. In that case, 841 // 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 842 // 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 843 // 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 844 // truncates len to avoid go past the end of a string so that we can
870 // get away without doing anything here. 845 // get away without doing anything here.
871 return getString().substring(component.begin, component.len); 846
847 int maxLength = getString().length() - component.begin;
848 return StringView(getString(), component.begin,
849 component.len > maxLength ? maxLength : component.len);
850 }
851
852 String KURL::componentString(const url::Component& component) const {
853 return componentStringView(component).toString();
872 } 854 }
873 855
874 template <typename CHAR> 856 template <typename CHAR>
875 void KURL::replaceComponents(const url::Replacements<CHAR>& replacements) { 857 void KURL::replaceComponents(const url::Replacements<CHAR>& replacements) {
876 url::RawCanonOutputT<char> output; 858 url::RawCanonOutputT<char> output;
877 url::Parsed newParsed; 859 url::Parsed newParsed;
878 860
879 StringUTF8Adaptor utf8(m_string); 861 StringUTF8Adaptor utf8(m_string);
880 m_isValid = url::ReplaceComponents(utf8.data(), utf8.length(), m_parsed, 862 m_isValid = url::ReplaceComponents(utf8.data(), utf8.length(), m_parsed,
881 replacements, 0, &output, &newParsed); 863 replacements, 0, &output, &newParsed);
882 864
883 m_parsed = newParsed; 865 m_parsed = newParsed;
884 m_string = AtomicString::fromUTF8(output.data(), output.length()); 866 m_string = AtomicString::fromUTF8(output.data(), output.length());
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