diff options
-rw-r--r-- | chrome/browser/net/chrome_url_request_context.cc | 15 | ||||
-rw-r--r-- | net/http/http_util.cc | 48 | ||||
-rw-r--r-- | net/http/http_util.h | 22 | ||||
-rw-r--r-- | net/http/http_util_unittest.cc | 18 |
4 files changed, 93 insertions, 10 deletions
diff --git a/chrome/browser/net/chrome_url_request_context.cc b/chrome/browser/net/chrome_url_request_context.cc index d834e57..4c877f5 100644 --- a/chrome/browser/net/chrome_url_request_context.cc +++ b/chrome/browser/net/chrome_url_request_context.cc @@ -15,6 +15,7 @@ #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "net/http/http_cache.h" +#include "net/http/http_util.h" #include "net/proxy/proxy_service.h" #include "webkit/glue/webkit_glue.h" @@ -95,12 +96,11 @@ ChromeURLRequestContext::ChromeURLRequestContext(Profile* profile) is_off_the_record_(profile->IsOffTheRecord()) { user_agent_ = webkit_glue::GetUserAgent(); - // set up Accept-Language and Accept-Charset header values - // TODO(jungshik) : This may slow down http requests. Perhaps, - // we have to come up with a better way to set up these values. - accept_language_ = WideToASCII(prefs_->GetString(prefs::kAcceptLanguages)); - accept_charset_ = WideToASCII(prefs_->GetString(prefs::kDefaultCharset)); - accept_charset_ += ",*,utf-8"; + // Set up Accept-Language and Accept-Charset header values + accept_language_ = net::HttpUtil::GenerateAcceptLanguageHeader( + WideToASCII(prefs_->GetString(prefs::kAcceptLanguages))); + accept_charset_ = net::HttpUtil::GenerateAcceptCharsetHeader( + WideToASCII(prefs_->GetString(prefs::kDefaultCharset))); cookie_policy_.SetType(net::CookiePolicy::FromInt( prefs_->GetInteger(prefs::kCookieBehavior))); @@ -183,7 +183,8 @@ FilePath ChromeURLRequestContext::GetPathForExtension(const std::string& id) { void ChromeURLRequestContext::OnAcceptLanguageChange(std::string accept_language) { DCHECK(MessageLoop::current() == ChromeThread::GetMessageLoop(ChromeThread::IO)); - accept_language_ = accept_language; + accept_language_ = + net::HttpUtil::GenerateAcceptLanguageHeader(accept_language); } void ChromeURLRequestContext::OnCookiePolicyChange(net::CookiePolicy::Type type) { diff --git a/net/http/http_util.cc b/net/http/http_util.cc index d69012c..95beb9c 100644 --- a/net/http/http_util.cc +++ b/net/http/http_util.cc @@ -57,7 +57,7 @@ std::string HttpUtil::PathForRequest(const GURL& url) { DCHECK(url.is_valid() && (url.SchemeIs("http") || url.SchemeIs("https"))); if (url.has_query()) return url.path() + "?" + url.query(); - return url.path(); + return url.path(); } // static @@ -430,7 +430,7 @@ std::string HttpUtil::AssembleRawHeaders(const char* input_begin, while (lines.GetNext()) { const char* line_begin = lines.token_begin(); const char* line_end = lines.token_end(); - + if (prev_line_continuable && IsLWS(*line_begin)) { // Join continuation; reduce the leading LWS to a single SP. raw_headers.push_back(' '); @@ -451,6 +451,50 @@ std::string HttpUtil::AssembleRawHeaders(const char* input_begin, return raw_headers; } +// TODO(jungshik): 1. If the list is 'fr-CA,fr-FR,en,de', we have to add +// 'fr' after 'fr-CA' with the same q-value as 'fr-CA' because +// web servers, in general, do not fall back to 'fr' and may end up picking +// 'en' which has a lower preference than 'fr-CA' and 'fr-FR'. +// 2. This function assumes that the input is a comma separated list +// without any whitespace. As long as it comes from the preference and +// a user does not manually edit the preference file, it's the case. Still, +// we may have to make it more robust. +std::string HttpUtil::GenerateAcceptLanguageHeader( + const std::string& raw_language_list) { + // We use integers for qvalue and qvalue decrement that are 10 times + // larger than actual values to avoid a problem with comparing + // two floating point numbers. + const unsigned int kQvalueDecrement10 = 2; + unsigned int qvalue10 = 10; + StringTokenizer t(raw_language_list, ","); + std::string lang_list_with_q; + while (t.GetNext()) { + std::string language = t.token(); + if (qvalue10 == 10) { + // q=1.0 is implicit. + lang_list_with_q = language; + } else { + DCHECK(qvalue10 >= 0 && qvalue10 < 10); + StringAppendF(&lang_list_with_q, ",%s;q=0.%d", language.c_str(), + qvalue10); + } + // It does not make sense to have 'q=0'. + if (qvalue10 > kQvalueDecrement10) + qvalue10 -= kQvalueDecrement10; + } + return lang_list_with_q; +} + +std::string HttpUtil::GenerateAcceptCharsetHeader(const std::string& charset) { + std::string charset_with_q = charset; + if (LowerCaseEqualsASCII(charset, "utf-8")) { + charset_with_q += ",*;q=0.5"; + } else { + charset_with_q += ",utf-8;q=0.7,*;q=0.3"; + } + return charset_with_q; +} + // BNF from section 4.2 of RFC 2616: // // message-header = field-name ":" [ field-value ] diff --git a/net/http/http_util.h b/net/http/http_util.h index d46ace4..9966c60 100644 --- a/net/http/http_util.h +++ b/net/http/http_util.h @@ -102,6 +102,28 @@ class HttpUtil { // the end-of-headers marker as defined by LocateEndOfHeaders. static std::string AssembleRawHeaders(const char* buf, int buf_len); + // Given a comma separated ordered list of language codes, return + // the list with a qvalue appended to each language. + // The way qvalues are assigned is rather simple. The qvalue + // starts with 1.0 and is decremented by 0.2 for each successive entry + // in the list until it reaches 0.2. All the entries after that are + // assigned the same qvalue of 0.2. Also, note that the 1st language + // will not have a qvalue added because the absence of a qvalue implicitly + // means q=1.0. + // + // When making a http request, this should be used to determine what + // to put in Accept-Language header. If a comma separated list of language + // codes *without* qvalue is sent, web servers regard all + // of them as having q=1.0 and pick one of them even though it may not + // be at the beginning of the list (see http://crbug.com/5899). + static std::string GenerateAcceptLanguageHeader( + const std::string& raw_language_list); + + // Given a charset, return the list with a qvalue. If charset is utf-8, + // it will return 'utf-8,*;q=0.5'. Otherwise (e.g. 'euc-jp'), it'll return + // 'euc-jp,utf-8;q=0.7,*;q=0.3'. + static std::string GenerateAcceptCharsetHeader(const std::string& charset); + // Used to iterate over the name/value pairs of HTTP headers. To iterate // over the values in a multi-value header, use ValuesIterator. // See AssembleRawHeaders for joining line continuations (this iterator diff --git a/net/http/http_util_unittest.cc b/net/http/http_util_unittest.cc index 4b27a0a..fab1953 100644 --- a/net/http/http_util_unittest.cc +++ b/net/http/http_util_unittest.cc @@ -326,7 +326,7 @@ TEST(HttpUtilTest, AssembleRawHeaders) { // Unterminated status line. { "HTTP/1.0 200 OK", - + "HTTP/1.0 200 OK||" }, @@ -475,3 +475,19 @@ TEST(HttpUtilTest, RequestUrlSanitize) { EXPECT_EQ(expected_path, HttpUtil::PathForRequest(url)); } } + +TEST(HttpUtilTest, GenerateAcceptLanguageHeader) { + EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6"), + HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de")); + EXPECT_EQ(std::string("en-US,fr;q=0.8,de;q=0.6,ko;q=0.4,zh-CN;q=0.2," + "ja;q=0.2"), + HttpUtil::GenerateAcceptLanguageHeader("en-US,fr,de,ko,zh-CN,ja")); +} + +TEST(HttpUtilTest, GenerateAcceptCharsetHeader) { + EXPECT_EQ(std::string("utf-8,*;q=0.5"), + HttpUtil::GenerateAcceptCharsetHeader("utf-8")); + EXPECT_EQ(std::string("EUC-JP,utf-8;q=0.7,*;q=0.3"), + HttpUtil::GenerateAcceptCharsetHeader("EUC-JP")); +} + |