summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--chrome/browser/net/chrome_url_request_context.cc15
-rw-r--r--net/http/http_util.cc48
-rw-r--r--net/http/http_util.h22
-rw-r--r--net/http/http_util_unittest.cc18
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"));
+}
+