summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
Diffstat (limited to 'webkit')
-rw-r--r--webkit/build/port/port.vcproj4
-rw-r--r--webkit/config.h.in3
-rw-r--r--webkit/glue/chromium_bridge_impl.cc24
-rw-r--r--webkit/glue/glue_util.cc4
-rw-r--r--webkit/port/platform/GKURL.cpp414
-rw-r--r--webkit/port/platform/GKURL_unittest.cpp22
-rw-r--r--webkit/port/platform/GoogleURLPrivate.h112
-rw-r--r--webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj2
8 files changed, 386 insertions, 199 deletions
diff --git a/webkit/build/port/port.vcproj b/webkit/build/port/port.vcproj
index 9b1eb3c..14f8499 100644
--- a/webkit/build/port/port.vcproj
+++ b/webkit/build/port/port.vcproj
@@ -828,6 +828,10 @@
RelativePath="..\..\port\platform\GKURL.cpp"
>
</File>
+ <File
+ RelativePath="..\..\port\platform\GoogleURLPrivate.h"
+ >
+ </File>
<Filter
Name="chromium"
>
diff --git a/webkit/config.h.in b/webkit/config.h.in
index 015e9f0..45609d7 100644
--- a/webkit/config.h.in
+++ b/webkit/config.h.in
@@ -122,6 +122,9 @@
#endif
#if PLATFORM(CHROMIUM)
+
+#define WTF_USE_GOOGLEURL 1
+
#if !PLATFORM(DARWIN)
// Don't define SKIA on Mac. Undefine other things as well that might get set
// as side-effects.
diff --git a/webkit/glue/chromium_bridge_impl.cc b/webkit/glue/chromium_bridge_impl.cc
index 7422c0c..617ea08 100644
--- a/webkit/glue/chromium_bridge_impl.cc
+++ b/webkit/glue/chromium_bridge_impl.cc
@@ -156,7 +156,11 @@ void ChromiumBridge::clipboardWriteSelection(const String& html,
bool can_smart_copy_or_delete) {
ScopedClipboardWriterGlue scw(webkit_glue::ClipboardGetClipboard());
scw.WriteHTML(webkit_glue::StringToStdWString(html),
+#if USE(GOOGLEURL)
webkit_glue::CStringToStdString(url.utf8String()));
+#else
+ webkit_glue::StringToStdString(url.string()));
+#endif
scw.WriteText(webkit_glue::StringToStdWString(plain_text));
if (can_smart_copy_or_delete)
@@ -543,13 +547,29 @@ WebCore::LinkHash ChromiumBridge::visitedLinkHash(
url_canon::RawCanonOutput<2048> buffer;
url_parse::Parsed parsed;
+#if USE(GOOGLEURL)
const WebCore::CString& cstr = base.utf8String();
- if (!url_util::ResolveRelative(cstr.data(), cstr.length(), base.parsed(),
+ const char* data = cstr.data();
+ int length = cstr.length();
+ const url_parse::Parsed& src_parsed = base.parsed();
+#else
+ // When we're not using GoogleURL, first canonicalize it so we can resolve it
+ // below.
+ url_canon::RawCanonOutput<2048> src_canon;
+ url_parse::Parsed src_parsed;
+ WebCore::String str = base.string();
+ if (!url_util::Canonicalize(str.characters(), str.length(), NULL,
+ &src_canon, &src_parsed))
+ return false;
+ const char* data = src_canon.data();
+ int length = src_canon.length();
+#endif
+
+ if (!url_util::ResolveRelative(data, length, src_parsed,
attributeURL.characters(),
attributeURL.length(), NULL,
&buffer, &parsed))
return false; // Invalid resolved URL.
-
return webkit_glue::VisitedLinkHash(buffer.data(), buffer.length());
}
diff --git a/webkit/glue/glue_util.cc b/webkit/glue/glue_util.cc
index 5bbae41..997af01 100644
--- a/webkit/glue/glue_util.cc
+++ b/webkit/glue/glue_util.cc
@@ -73,7 +73,7 @@ WebCore::String StdStringToString(const std::string& str) {
// URL conversions -------------------------------------------------------------
GURL KURLToGURL(const WebCore::KURL& url) {
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
const WebCore::CString& spec = url.utf8String();
if (spec.isNull() || 0 == spec.length())
return GURL();
@@ -85,7 +85,7 @@ GURL KURLToGURL(const WebCore::KURL& url) {
WebCore::KURL GURLToKURL(const GURL& url) {
const std::string& spec = url.possibly_invalid_spec();
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
// Convert using the internal structures to avoid re-parsing.
return WebCore::KURL(spec.c_str(), static_cast<int>(spec.length()),
url.parsed_for_possibly_invalid_spec(), url.is_valid());
diff --git a/webkit/port/platform/GKURL.cpp b/webkit/port/platform/GKURL.cpp
index 281f513..045d06d 100644
--- a/webkit/port/platform/GKURL.cpp
+++ b/webkit/port/platform/GKURL.cpp
@@ -34,7 +34,7 @@
#include "TextEncoding.h"
#include "Vector.h"
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
#undef LOG
#include "base/string_util.h"
@@ -92,17 +92,26 @@ inline const url_parse::UTF16Char* CharactersOrEmpty(const String& str) {
&zero;
}
-inline bool IsUnicodeEncoding(const TextEncoding* encoding)
+inline bool IsUnicodeEncoding(const TextEncoding* encoding)
{
return encoding->encodingForFormSubmission() == UTF8Encoding();
}
} // namespace
-// KURL::URLString -------------------------------------------------------------
+// GoogleURLPrivate ------------------------------------------------------------
-KURL::URLString::URLString()
- : m_utf8IsASCII(true)
+GoogleURLPrivate::GoogleURLPrivate()
+ : m_isValid(false)
+ , m_utf8IsASCII(true)
+ , m_stringIsValid(false)
+{
+}
+
+GoogleURLPrivate::GoogleURLPrivate(const url_parse::Parsed& parsed, bool isValid)
+ : m_isValid(isValid)
+ , m_parsed(parsed)
+ , m_utf8IsASCII(true)
, m_stringIsValid(false)
{
}
@@ -110,7 +119,7 @@ KURL::URLString::URLString()
// Setters for the data. Using the ASCII version when you know the
// data is ASCII will be slightly more efficient. The UTF-8 version
// will always be correct if the caller is unsure.
-void KURL::URLString::setUtf8(const char* data, int data_len)
+void GoogleURLPrivate::setUtf8(const char* data, int data_len)
{
// The m_utf8IsASCII must always be correct since the DeprecatedString
// getter must create it with the proper constructor. This test can be
@@ -123,18 +132,142 @@ void KURL::URLString::setUtf8(const char* data, int data_len)
break;
}
}
-
+
m_utf8 = CString(data, data_len);
m_stringIsValid = false;
}
-void KURL::URLString::setAscii(const char* data, int data_len) {
+void GoogleURLPrivate::setAscii(const char* data, int data_len)
+{
m_utf8 = CString(data, data_len);
m_utf8IsASCII = true;
m_stringIsValid = false;
}
-const String& KURL::URLString::string() const
+void GoogleURLPrivate::init(const KURL& base,
+ const String& relative,
+ const TextEncoding* queryEncoding)
+{
+ init(base, relative.characters(), relative.length(), queryEncoding);
+}
+
+// Note: code mostly duplicated below.
+void GoogleURLPrivate::init(const KURL& base, const char* rel, int rel_len,
+ const TextEncoding* query_encoding)
+{
+ // As a performance optimization, we do not use the charset converter if
+ // encoding is UTF-8 or other Unicode encodings. Note that this is
+ // per HTML5 2.5.3 (resolving URL). The URL canonicalizer will be
+ // more efficient with no charset converter object because it
+ // can do UTF-8 internally with no extra copies.
+
+ // We feel free to make the charset converter object every time since it's
+ // just a wrapper around a reference.
+ WebCoreCharsetConverter charset_converter_object(query_encoding);
+ WebCoreCharsetConverter* charset_converter =
+ (!query_encoding || IsUnicodeEncoding(query_encoding)) ? 0 :
+ &charset_converter_object;
+
+ url_canon::RawCanonOutputT<char> output;
+ const CString& baseStr = base.m_url.utf8String();
+ m_isValid = url_util::ResolveRelative(baseStr.data(), baseStr.length(),
+ base.m_url.m_parsed, rel, rel_len,
+ charset_converter,
+ &output, &m_parsed);
+
+ // See TODO in GoogleURLPrivate in the header. If canonicalization has not
+ // changed the string, we can avoid an extra allocation by using assignment.
+ //
+ // When KURL encounters an error such that the URL is invalid and empty
+ // (for example, resolving a relative URL on a non-hierarchical base), it
+ // will produce an isNull URL, and calling setUtf8 will produce an empty
+ // non-null URL. This is unlikely to affect anything, but we preserve this
+ // just in case.
+ if (m_isValid || output.length()) {
+ // Without ref, the whole url is guaranteed to be ASCII-only.
+ if (m_parsed.ref.is_nonempty())
+ setUtf8(output.data(), output.length());
+ else
+ setAscii(output.data(), output.length());
+ } else {
+ // WebKit expects resolved URLs to be empty rather than NULL.
+ setUtf8("", 0);
+ }
+}
+
+// Note: code mostly duplicated above. See TODOs and comments there.
+void GoogleURLPrivate::init(const KURL& base, const UChar* rel, int rel_len,
+ const TextEncoding* query_encoding)
+{
+ WebCoreCharsetConverter charset_converter_object(query_encoding);
+ WebCoreCharsetConverter* charset_converter =
+ (!query_encoding || IsUnicodeEncoding(query_encoding)) ? 0 :
+ &charset_converter_object;
+
+ url_canon::RawCanonOutputT<char> output;
+ const CString& baseStr = base.m_url.utf8String();
+ m_isValid = url_util::ResolveRelative(baseStr.data(), baseStr.length(),
+ base.m_url.m_parsed, rel, rel_len,
+ charset_converter,
+ &output, &m_parsed);
+
+ if (m_isValid || output.length()) {
+ if (m_parsed.ref.is_nonempty())
+ setUtf8(output.data(), output.length());
+ else
+ setAscii(output.data(), output.length());
+ } else {
+ setUtf8("", 0);
+ }
+}
+
+void GoogleURLPrivate::copyTo(GoogleURLPrivate* dest) const
+{
+ dest->m_isValid = m_isValid;
+ dest->m_parsed = m_parsed;
+
+ // Don't copy the 16-bit string since that will be regenerated as needed.
+ dest->m_utf8 = CString(m_utf8.data(), m_utf8.length());
+ dest->m_utf8IsASCII = m_utf8IsASCII;
+ dest->m_stringIsValid = false;
+}
+
+String GoogleURLPrivate::componentString(const url_parse::Component& comp) const
+{
+ if (!m_isValid || comp.len <= 0) {
+ // KURL returns a NULL string if the URL is itself a NULL string, and an
+ // empty string for other nonexistant entities.
+ if (utf8String().isNull())
+ return String();
+ return String("", 0);
+ }
+ // begin and len are in terms of bytes which do not match
+ // if string() is UTF-16 and input contains non-ASCII characters.
+ // However, the only part in urlString that can contain non-ASCII
+ // characters is 'ref' at the end of the string. In that case,
+ // begin will always match the actual value and len (in terms of
+ // byte) will be longer than what's needed by 'mid'. However, mid
+ // truncates len to avoid go past the end of a string so that we can
+ // get away withtout doing anything here.
+ return string().substring(comp.begin, comp.len);
+}
+
+void GoogleURLPrivate::replaceComponents(const Replacements& replacements)
+{
+ url_canon::RawCanonOutputT<char> output;
+ url_parse::Parsed new_parsed;
+
+ m_isValid = url_util::ReplaceComponents(utf8String().data(),
+ utf8String().length(), m_parsed, replacements, NULL, &output, &new_parsed);
+
+ m_parsed = new_parsed;
+ if (m_parsed.ref.is_nonempty())
+ setUtf8(output.data(), output.length());
+ else
+ setAscii(output.data(), output.length());
+}
+
+const String& GoogleURLPrivate::string() const
{
if (!m_stringIsValid) {
// Must special case the NULL case, since constructing the
@@ -161,7 +294,7 @@ KURL::KURL(const char *url)
// FIXME(brettw) the Mac code checks for beginning with a slash and
// converting to a file: URL. We will want to add this as well once we
// can compile on a system like that.
- init(KURL(), url, strlen(url), NULL);
+ m_url.init(KURL(), url, strlen(url), NULL);
// The one-argument constructors should never generate a NULL string.
// This is a funny quirk of KURL (probably a bug) which we preserve.
@@ -177,12 +310,12 @@ KURL::KURL(const char *url)
KURL::KURL(const String& url)
{
if (!url.isNull()) {
- init(KURL(), url, NULL);
+ m_url.init(KURL(), url, NULL);
} else {
// WebKit expects us to preserve the nullness of strings when this
// constructor is used. In all other cases, it expects a non-null
// empty string, which is what init() will create.
- m_isValid = false;
+ m_url.m_isValid = false;
}
}
@@ -190,7 +323,7 @@ KURL::KURL(const String& url)
// This assumes UTF-8 encoding.
KURL::KURL(const KURL& base, const String& relative)
{
- init(base, relative, NULL);
+ m_url.init(base, relative, NULL);
}
// Constructs a new URL given a base URL and a possibly relative input URL.
@@ -199,20 +332,19 @@ KURL::KURL(const KURL& base,
const String& relative,
const TextEncoding& encoding)
{
- init(base, relative, &encoding.encodingForFormSubmission());
+ m_url.init(base, relative, &encoding.encodingForFormSubmission());
}
-KURL::KURL(const char* canonical_spec, int canonical_spec_len,
- const url_parse::Parsed& parsed, bool is_valid)
- : m_isValid(is_valid),
- m_parsed(parsed)
+KURL::KURL(const char* canonicalSpec, int canonicalSpecLen,
+ const url_parse::Parsed& parsed, bool isValid)
+ : m_url(parsed, isValid)
{
// We know the reference fragment is the only part that can be UTF-8, so
// we know it's ASCII when there is no ref.
if (parsed.ref.is_nonempty())
- m_url.setUtf8(canonical_spec, canonical_spec_len);
+ m_url.setUtf8(canonicalSpec, canonicalSpecLen);
else
- m_url.setAscii(canonical_spec, canonical_spec_len);
+ m_url.setAscii(canonicalSpec, canonicalSpecLen);
}
#if PLATFORM(CF)
@@ -228,116 +360,33 @@ CFURLRef KURL::createCFURL() const {
}
#endif
-String KURL::componentString(const url_parse::Component& comp) const
+KURL KURL::copy() const
{
- if (!m_isValid || comp.len <= 0) {
- // KURL returns a NULL string if the URL is itself a NULL string, and an
- // empty string for other nonexistant entities.
- if (isNull())
- return String();
- return String("", 0);
- }
- // begin and len are in terms of bytes which do not match
- // if urlString is UTF-16 and input contains non-ASCII characters.
- // However, the only part in urlString that can contain non-ASCII
- // characters is 'ref' at the end of the string. In that case,
- // begin will always match the actual value and len (in terms of
- // byte) will be longer than what's needed by 'mid'. However, mid
- // truncates len to avoid go past the end of a string so that we can
- // get away withtout doing anything here.
- return m_url.string().substring(comp.begin, comp.len);
+ KURL result = *this;
+ m_url.copyTo(&result.m_url);
+ return result;
}
-void KURL::init(const KURL& base,
- const String& relative,
- const TextEncoding* query_encoding)
+bool KURL::isNull() const
{
- init(base, relative.characters(), relative.length(), query_encoding);
+ return m_url.utf8String().isNull();
}
-// Note: code mostly duplicated below.
-void KURL::init(const KURL& base, const char* rel, int rel_len,
- const TextEncoding* query_encoding)
+bool KURL::isEmpty() const
{
- // As a performance optimization, we do not use the charset converter if
- // encoding is UTF-8 or other Unicode encodings. Note that this is
- // per HTML5 2.5.3 (resolving URL). The URL canonicalizer will be
- // more efficient with no charset converter object because it
- // can do UTF-8 internally with no extra copies.
-
- // We feel free to make the charset converter object every time since it's
- // just a wrapper around a reference.
- WebCoreCharsetConverter charset_converter_object(query_encoding);
- WebCoreCharsetConverter* charset_converter =
- (!query_encoding || IsUnicodeEncoding(query_encoding)) ? 0 :
- &charset_converter_object;
-
- url_canon::RawCanonOutputT<char> output;
- const CString& baseStr = base.m_url.utf8String();
- m_isValid = url_util::ResolveRelative(baseStr.data(), baseStr.length(),
- base.m_parsed, rel, rel_len,
- charset_converter,
- &output, &m_parsed);
-
- // See TODO in URLString in the header. If canonicalization has not changed
- // the string, we can avoid an extra allocation by using assignment.
- //
- // When KURL encounters an error such that the URL is invalid and empty
- // (for example, resolving a relative URL on a non-hierarchical base), it
- // will produce an isNull URL, and calling setUtf8 will produce an empty
- // non-null URL. This is unlikely to affect anything, but we preserve this
- // just in case.
- if (m_isValid || output.length()) {
- // Without ref, the whole url is guaranteed to be ASCII-only.
- if (m_parsed.ref.is_nonempty())
- m_url.setUtf8(output.data(), output.length());
- else
- m_url.setAscii(output.data(), output.length());
- } else {
- // WebKit expects resolved URLs to be empty rather than NULL.
- m_url.setUtf8("", 0);
- }
+ return m_url.utf8String().length() == 0;
}
-// Note: code mostly duplicated above. See TODOs and comments there.
-void KURL::init(const KURL& base, const UChar* rel, int rel_len,
- const TextEncoding* query_encoding)
+bool KURL::isValid() const
{
- WebCoreCharsetConverter charset_converter_object(query_encoding);
- WebCoreCharsetConverter* charset_converter =
- (!query_encoding || IsUnicodeEncoding(query_encoding)) ? 0 :
- &charset_converter_object;
-
- url_canon::RawCanonOutputT<char> output;
- const CString& baseStr = base.m_url.utf8String();
- m_isValid = url_util::ResolveRelative(baseStr.data(), baseStr.length(),
- base.m_parsed, rel, rel_len,
- charset_converter,
- &output, &m_parsed);
-
- if (m_isValid || output.length()) {
- if (m_parsed.ref.is_nonempty())
- m_url.setUtf8(output.data(), output.length());
- else
- m_url.setAscii(output.data(), output.length());
- } else {
- m_url.setUtf8("", 0);
- }
-}
-
-KURL KURL::copy() const
-{
- KURL result = *this;
- // TODO(brettw): http://crbug.com/4975 Make this a deep copy.
- // result.m_string = result.m_string.copy();
- return result;
+ return m_url.m_isValid;
}
bool KURL::hasPath() const
{
// Note that http://www.google.com/" has a path, the path is "/". This can
// return false only for invalid or nonstandard URLs.
- return m_parsed.path.len >= 0;
+ return m_url.m_parsed.path.len >= 0;
}
// We handle "parameters" separated be a semicolon, while the old KURL does
@@ -347,7 +396,7 @@ String KURL::lastPathComponent() const
// When the output ends in a slash, WebKit has different expectations than
// our library. For "/foo/bar/" the library will return the empty string,
// but WebKit wants "bar".
- url_parse::Component path = m_parsed.path;
+ url_parse::Component path = m_url.m_parsed.path;
if (path.len > 0 && m_url.utf8String().data()[path.end() - 1] == '/')
path.len--;
@@ -358,18 +407,18 @@ String KURL::lastPathComponent() const
// a null string when the path is empty, which we duplicate here.
if (!file.is_nonempty())
return String();
- return componentString(file);
+ return m_url.componentString(file);
}
String KURL::protocol() const
{
- return componentString(m_parsed.scheme);
+ return m_url.componentString(m_url.m_parsed.scheme);
}
String KURL::host() const
{
// Note: WebKit decode_string()s here.
- return componentString(m_parsed.host);
+ return m_url.componentString(m_url.m_parsed.host);
}
// Returns 0 when there is no port or it is invalid.
@@ -379,9 +428,9 @@ String KURL::host() const
// parsing, and return 0 from this port() function.
unsigned short int KURL::port() const
{
- if (!m_isValid || m_parsed.port.len <= 0)
+ if (!m_url.m_isValid || m_url.m_parsed.port.len <= 0)
return 0;
- int port = url_parse::ParsePort(m_url.utf8String().data(), m_parsed.port);
+ int port = url_parse::ParsePort(m_url.utf8String().data(), m_url.m_parsed.port);
if (port == url_parse::PORT_UNSPECIFIED)
return 0;
return static_cast<unsigned short>(port);
@@ -392,49 +441,49 @@ String KURL::pass() const
{
// Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns
// a null string when the password is empty, which we duplicate here.
- if (!m_parsed.password.is_nonempty())
+ if (!m_url.m_parsed.password.is_nonempty())
return String();
// Note: WebKit decode_string()s here.
- return componentString(m_parsed.password);
+ return m_url.componentString(m_url.m_parsed.password);
}
// Returns the empty string if there is no username.
String KURL::user() const
{
// Note: WebKit decode_string()s here.
- return componentString(m_parsed.username);
+ return m_url.componentString(m_url.m_parsed.username);
}
String KURL::ref() const
{
// Empty but present refs ("foo.com/bar#") should result in the empty
- // string, which componentString will produce. Nonexistant refs should be
+ // string, which m_url.componentString will produce. Nonexistant refs should be
// the NULL string.
- if (!m_parsed.ref.is_valid())
+ if (!m_url.m_parsed.ref.is_valid())
return String();
// Note: WebKit decode_string()s here.
- return componentString(m_parsed.ref);
+ return m_url.componentString(m_url.m_parsed.ref);
}
bool KURL::hasRef() const
{
// Note: WebKit decode_string()s here.
// FIXME(brettw) determine if they agree about an empty ref
- return m_parsed.ref.len >= 0;
+ return m_url.m_parsed.ref.len >= 0;
}
String KURL::query() const
{
- if (m_parsed.query.len >= 0) {
+ if (m_url.m_parsed.query.len >= 0) {
// KURL's query() includes the question mark, even though the reference
// doesn't. Move the query component backwards one to account for it
// (our library doesn't count the question mark).
- url_parse::Component query_comp = m_parsed.query;
+ url_parse::Component query_comp = m_url.m_parsed.query;
query_comp.begin--;
query_comp.len++;
- return componentString(query_comp);
+ return m_url.componentString(query_comp);
}
// Bug: https://bugs.webkit.org/show_bug.cgi?id=21015 this function returns
@@ -446,23 +495,23 @@ String KURL::query() const
String KURL::path() const
{
// Note: WebKit decode_string()s here.
- return componentString(m_parsed.path);
+ return m_url.componentString(m_url.m_parsed.path);
}
void KURL::setProtocol(const String& protocol)
{
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.SetScheme(CharactersOrEmpty(protocol),
url_parse::Component(0, protocol.length()));
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setHost(const String& host)
{
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.SetHost(CharactersOrEmpty(host),
url_parse::Component(0, host.length()));
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
// This function is used only in the JSC build.
@@ -470,9 +519,9 @@ void KURL::setHostAndPort(const String& s) {
String newhost = s.left(s.find(":"));
String newport = s.substring(s.find(":") + 1);
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
// Host can't be removed, so we always set.
- replacements.SetHost(CharactersOrEmpty(newhost),
+ replacements.SetHost(CharactersOrEmpty(newhost),
url_parse::Component(0, newhost.length()));
if (newport.isEmpty()) { // Port may be removed, so we support clearing.
@@ -481,12 +530,12 @@ void KURL::setHostAndPort(const String& s) {
replacements.SetPort(CharactersOrEmpty(newport),
url_parse::Component(0, newport.length()));
}
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setPort(unsigned short i)
{
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
String portStr;
if (i > 0) {
portStr = String::number(static_cast<int>(i));
@@ -498,66 +547,66 @@ void KURL::setPort(unsigned short i)
// Clear any existing port when it is set to 0.
replacements.ClearPort();
}
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setUser(const String& user)
{
// This function is commonly called to clear the username, which we
// normally don't have, so we optimize this case.
- if (user.isEmpty() && !m_parsed.username.is_valid())
+ if (user.isEmpty() && !m_url.m_parsed.username.is_valid())
return;
// The canonicalizer will clear any usernames that are empty, so we
// don't have to explicitly call ClearUsername() here.
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.SetUsername(CharactersOrEmpty(user),
url_parse::Component(0, user.length()));
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setPass(const String& pass)
{
// This function is commonly called to clear the password, which we
// normally don't have, so we optimize this case.
- if (pass.isEmpty() && !m_parsed.password.is_valid())
+ if (pass.isEmpty() && !m_url.m_parsed.password.is_valid())
return;
// The canonicalizer will clear any passwords that are empty, so we
// don't have to explicitly call ClearUsername() here.
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.SetPassword(CharactersOrEmpty(pass),
url_parse::Component(0, pass.length()));
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setRef(const String& ref)
{
// This function is commonly called to clear the ref, which we
// normally don't have, so we optimize this case.
- if (ref.isNull() && !m_parsed.ref.is_valid())
+ if (ref.isNull() && !m_url.m_parsed.ref.is_valid())
return;
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
if (ref.isNull()) {
replacements.ClearRef();
} else {
replacements.SetRef(CharactersOrEmpty(ref),
url_parse::Component(0, ref.length()));
}
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::removeRef()
{
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.ClearRef();
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setQuery(const String& query)
{
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
if (query.isNull()) {
// WebKit sets to NULL to clear any query.
replacements.ClearQuery();
@@ -575,17 +624,17 @@ void KURL::setQuery(const String& query)
replacements.SetQuery(CharactersOrEmpty(query),
url_parse::Component(0, query.length()));
}
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
void KURL::setPath(const String& path)
{
// Empty paths will be canonicalized to "/", so we don't have to worry
// about calling ClearPath().
- Replacements replacements;
+ GoogleURLPrivate::Replacements replacements;
replacements.SetPath(CharactersOrEmpty(path),
url_parse::Component(0, path.length()));
- replaceComponents(replacements);
+ m_url.replaceComponents(replacements);
}
// On Mac, this just seems to return the same URL, but with "/foo/bar" for
@@ -593,7 +642,7 @@ void KURL::setPath(const String& path)
// at least for now.
String KURL::prettyURL() const
{
- if (!m_isValid)
+ if (!m_url.m_isValid)
return String();
return m_url.string();
}
@@ -723,29 +772,14 @@ String decodeURLEscapeSequences(const String& str, const TextEncoding& encoding)
utf16.length());
}
-void KURL::replaceComponents(const Replacements& replacements)
-{
- url_canon::RawCanonOutputT<char> output;
- url_parse::Parsed new_parsed;
-
- m_isValid = url_util::ReplaceComponents(m_url.utf8String().data(),
- m_url.utf8String().length(), m_parsed, replacements, NULL, &output, &new_parsed);
-
- m_parsed = new_parsed;
- if (m_parsed.ref.is_nonempty())
- m_url.setUtf8(output.data(), output.length());
- else
- m_url.setAscii(output.data(), output.length());
-}
-
bool KURL::protocolIs(const char* protocol) const
{
AssertProtocolIsGood(protocol);
- if (m_parsed.scheme.len <= 0)
+ if (m_url.m_parsed.scheme.len <= 0)
return protocol == NULL;
return LowerCaseEqualsASCII(
- m_url.utf8String().data() + m_parsed.scheme.begin,
- m_url.utf8String().data() + m_parsed.scheme.end(),
+ m_url.utf8String().data() + m_url.m_parsed.scheme.begin,
+ m_url.utf8String().data() + m_url.m_parsed.scheme.end(),
protocol);
}
@@ -788,12 +822,12 @@ String encodeWithURLEscapeSequences(const String& notEncodedString)
bool KURL::isHierarchical() const
{
- if (!m_parsed.scheme.is_nonempty())
+ if (!m_url.m_parsed.scheme.is_nonempty())
return false;
return url_util::IsStandard(
- &m_url.utf8String().data()[m_parsed.scheme.begin],
+ &m_url.utf8String().data()[m_url.m_parsed.scheme.begin],
m_url.utf8String().length(),
- m_parsed.scheme);
+ m_url.m_parsed.scheme);
}
#ifndef NDEBUG
@@ -807,7 +841,7 @@ void KURL::invalidate()
{
// This is only called from the constructor so resetting the (automatically
// initialized) string and parsed structure would be a waste of time.
- m_isValid = false;
+ m_url.m_isValid = false;
}
// Equal up to reference fragments, if any.
@@ -817,12 +851,12 @@ bool equalIgnoringRef(const KURL& a, const KURL& b)
// begin (if it exists) points to the character *after* the '#', so we need
// to subtract one.
int a_len = a.m_url.utf8String().length();
- if (a.m_parsed.ref.len >= 0)
- a_len = a.m_parsed.ref.begin - 1;
+ if (a.m_url.m_parsed.ref.len >= 0)
+ a_len = a.m_url.m_parsed.ref.begin - 1;
int b_len = b.m_url.utf8String().length();
- if (b.m_parsed.ref.len >= 0)
- b_len = b.m_parsed.ref.begin - 1;
+ if (b.m_url.m_parsed.ref.len >= 0)
+ b_len = b.m_url.m_parsed.ref.begin - 1;
return a_len == b_len &&
strncmp(a.m_url.utf8String().data(), b.m_url.utf8String().data(), a_len) == 0;
@@ -830,32 +864,32 @@ bool equalIgnoringRef(const KURL& a, const KURL& b)
unsigned KURL::hostStart() const
{
- return m_parsed.CountCharactersBefore(url_parse::Parsed::HOST, false);
+ return m_url.m_parsed.CountCharactersBefore(url_parse::Parsed::HOST, false);
}
unsigned KURL::hostEnd() const
{
- return m_parsed.CountCharactersBefore(url_parse::Parsed::PORT, true);
+ return m_url.m_parsed.CountCharactersBefore(url_parse::Parsed::PORT, true);
}
unsigned KURL::pathStart() const
{
- return m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
+ return m_url.m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
}
unsigned KURL::pathEnd() const
{
- return m_parsed.CountCharactersBefore(url_parse::Parsed::QUERY, true);
+ return m_url.m_parsed.CountCharactersBefore(url_parse::Parsed::QUERY, true);
}
unsigned KURL::pathAfterLastSlash() const
{
// When there's no path, ask for what would be the beginning of it.
- if (!m_parsed.path.is_valid())
- return m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
+ if (!m_url.m_parsed.path.is_valid())
+ return m_url.m_parsed.CountCharactersBefore(url_parse::Parsed::PATH, false);
url_parse::Component filename;
- url_parse::ExtractFileName(m_url.utf8String().data(), m_parsed.path,
+ url_parse::ExtractFileName(m_url.utf8String().data(), m_url.m_parsed.path,
&filename);
return filename.begin;
}
@@ -895,4 +929,4 @@ inline bool KURL::protocolIs(const String& string, const char* protocol)
} // namespace WebCore
-#endif // USE_GOOGLE_URL_LIBRARY
+#endif // USE(GOOGLEURL)
diff --git a/webkit/port/platform/GKURL_unittest.cpp b/webkit/port/platform/GKURL_unittest.cpp
index bca7625..0ac8957 100644
--- a/webkit/port/platform/GKURL_unittest.cpp
+++ b/webkit/port/platform/GKURL_unittest.cpp
@@ -274,7 +274,7 @@ TEST(GKURL, Setters) {
}
// Tests that KURL::decodeURLEscapeSequences works as expected
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
TEST(GKURL, Decode) {
struct DecodeCase {
const char* input;
@@ -361,7 +361,7 @@ TEST(GKURL, ReplaceInvalid) {
gurl.setProtocol("http");
// GKURL will say that a URL with just a scheme is invalid, KURL will not.
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
EXPECT_FALSE(gurl.isValid());
#else
EXPECT_TRUE(gurl.isValid());
@@ -370,7 +370,7 @@ TEST(GKURL, ReplaceInvalid) {
// At this point, we do things slightly differently if there is only a scheme.
// We check the results here to make it more obvious what is going on, but it
// shouldn't be a big deal if these change.
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
EXPECT_STREQ("http:", gurl.string().utf8().data());
#else
EXPECT_STREQ("http:/", gurl.string().utf8().data());
@@ -392,7 +392,7 @@ TEST(GKURL, ReplaceInvalid) {
EXPECT_STREQ("http://www.google.com:8000/favicon.ico", gurl.string().utf8().data());
// Now let's test that giving an invalid replacement still fails.
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
gurl.setProtocol("f/sj#@");
EXPECT_FALSE(gurl.isValid());
#endif
@@ -502,7 +502,7 @@ TEST(GKURL, Empty) {
// Test non-hierarchical schemes resolving. The actual URLs will be different.
// WebKit's one will set the string to "something.gif" and we'll set it to an
// empty string. I think either is OK, so we just check our behavior.
-#ifdef USE_GOOGLE_URL_LIBRARY
+#if USE(GOOGLEURL)
WebCore::KURL gurl3(WebCore::KURL("data:foo"), "something.gif");
EXPECT_TRUE(gurl3.isEmpty());
EXPECT_FALSE(gurl3.isValid());
@@ -586,3 +586,15 @@ TEST(GKURL, Offsets) {
EXPECT_EQ(17u, gurl3.pathEnd());
EXPECT_EQ(11u, gurl3.pathAfterLastSlash());
}
+
+TEST(GKURL, DeepCopy) {
+ const char url[] = "http://www.google.com/";
+ WebCore::KURL src(url);
+ EXPECT_TRUE(src.string() == url); // This really just initializes the cache.
+ WebCore::KURL dest = src.copy();
+ EXPECT_TRUE(dest.string() == url); // This really just initializes the cache.
+
+ // The pointers should be different for both UTF-8 and UTF-16.
+ EXPECT_NE(dest.string().characters(), src.string().characters());
+ EXPECT_NE(dest.utf8String().data(), src.utf8String().data());
+}
diff --git a/webkit/port/platform/GoogleURLPrivate.h b/webkit/port/platform/GoogleURLPrivate.h
new file mode 100644
index 0000000..eb8e0601
--- /dev/null
+++ b/webkit/port/platform/GoogleURLPrivate.h
@@ -0,0 +1,112 @@
+// Copyright (c) 2008, Google Inc.
+// All rights reserved.
+//
+// Redistribution and use in source and binary forms, with or without
+// modification, are permitted provided that the following conditions are
+// met:
+//
+// * Redistributions of source code must retain the above copyright
+// notice, this list of conditions and the following disclaimer.
+// * Redistributions in binary form must reproduce the above
+// copyright notice, this list of conditions and the following disclaimer
+// in the documentation and/or other materials provided with the
+// distribution.
+// * Neither the name of Google Inc. nor the names of its
+// contributors may be used to endorse or promote products derived from
+// this software without specific prior written permission.
+//
+// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+#ifndef KURLGoogleURL_h
+#define KURLGoogleURL_h
+
+#include "CString.h"
+
+#include "googleurl/src/url_parse.h"
+#include "googleurl/src/url_canon.h"
+
+namespace WebCore {
+
+class KURL;
+class TextEncoding;
+
+// Wraps the internals related to using Google-URL as the bnackend for KURL.
+// This maintains the state and has auxiliary functions so that we don't need
+// to uglify KURL.h while allowing Google-URL to be evaluated.
+class GoogleURLPrivate {
+public:
+ GoogleURLPrivate();
+ GoogleURLPrivate(const url_parse::Parsed& parsed, bool isValid);
+
+ // Initializes the object. This will call through to one of the backend
+ // initializers below depending on whether the string's internal
+ // representation is 8 or 16 bit.
+ void init(const KURL& base, const String& relative,
+ const TextEncoding* queryEncoding);
+
+ // Backend initializers. The query encoding parameters are optional and can
+ // be NULL (this implies UTF-8). These initializers require that the object
+ // has just been created and the strings are NULL. Do not call on an
+ // already-constructed object.
+ void init(const KURL& base, const char* rel, int relLen,
+ const TextEncoding* queryEncoding);
+ void init(const KURL& base, const UChar* rel, int relLen,
+ const TextEncoding* queryEncoding);
+
+ // Does a deep copy to the given output object.
+ void copyTo(GoogleURLPrivate* dest) const;
+
+ // Returns the substring of the input identified by the given component.
+ String componentString(const url_parse::Component& comp) const;
+
+ // Replaces the given components, modifying the current URL. The current
+ // URL must be valid.
+ typedef url_canon::Replacements<url_parse::UTF16Char> Replacements;
+ void replaceComponents(const Replacements& replacements);
+
+ // Setters for the data. Using the ASCII version when you know the
+ // data is ASCII will be slightly more efficient. The UTF-8 version
+ // will always be correct if the caller is unsure.
+ void setUtf8(const char* data, int dataLen);
+ void setAscii(const char* data, int dataLen);
+
+ // TODO(brettw) we can support an additional optimization. Make this
+ // buffer support both optinal Strings and UTF-8 data. This way, we can use
+ // the optimization from the original KURL which uses = with the original
+ // string when canonicalization did not change it. This allows the strings
+ // to share a buffer internally, and saves a malloc.
+
+ // Getters for the data.
+ const CString& utf8String() const { return m_utf8; }
+ const String& string() const;
+
+ bool m_isValid;
+ url_parse::Parsed m_parsed; // Indexes into the UTF-8 version of the string.
+
+private:
+ CString m_utf8;
+
+ // Set to true when the caller set us using the ASCII setter. We can
+ // be more efficient when we know there is no UTF-8 to worry about.
+ // This flag is currently always correct, but should be changed to be a
+ // hint (see setUtf8).
+ bool m_utf8IsASCII;
+
+ mutable bool m_stringIsValid;
+ mutable String m_string;
+};
+
+} // namespace WebCore
+
+#endif // KURLGoogleURL_h
+
diff --git a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
index 0136adb..3adac5ea 100644
--- a/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
+++ b/webkit/tools/test_shell/mac/TestShell.xcodeproj/project.pbxproj
@@ -2169,6 +2169,7 @@
../../../../third_party/WebKit/WebCore/rendering/style,
../../../../third_party/WebKit/WebCore/svg,
../../../../third_party/WebKit/WebKit/mac/WebCoreSupport,
+ ../../../../webkit/port/platform,
"../../../../webkit/port/platform/image-decoders",
"../../../../webkit/port/platform/image-decoders/bmp",
"../../../../webkit/port/platform/image-decoders/png",
@@ -2230,6 +2231,7 @@
../../../../third_party/WebKit/WebCore/rendering/style,
../../../../third_party/WebKit/WebCore/svg,
../../../../third_party/WebKit/WebKit/mac/WebCoreSupport,
+ ../../../../webkit/port/platform,
"../../../../webkit/port/platform/image-decoders",
"../../../../webkit/port/platform/image-decoders/bmp",
"../../../../webkit/port/platform/image-decoders/png",