Change SDCHDictionaryFetcher to use URLRequest instead of URLFetcher.

Also shifts mechanism for minimizing interference with top-level traffic
from delaying dispatch to using the IDLE request priority.

BUG=387890
BUG=383404
[email protected]

Review URL: https://codereview.chromium.org/495523003

Cr-Commit-Position: refs/heads/master@{#294002}
diff --git a/net/base/sdch_manager.cc b/net/base/sdch_manager.cc
index bd68797..59589fb 100644
--- a/net/base/sdch_manager.cc
+++ b/net/base/sdch_manager.cc
@@ -400,107 +400,6 @@
   return true;
 }
 
-bool SdchManager::AddSdchDictionary(const std::string& dictionary_text,
-    const GURL& dictionary_url) {
-  DCHECK(CalledOnValidThread());
-  std::string client_hash;
-  std::string server_hash;
-  GenerateHash(dictionary_text, &client_hash, &server_hash);
-  if (dictionaries_.find(server_hash) != dictionaries_.end()) {
-    SdchErrorRecovery(DICTIONARY_ALREADY_LOADED);
-    return false;  // Already loaded.
-  }
-
-  std::string domain, path;
-  std::set<int> ports;
-  base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30));
-
-  if (dictionary_text.empty()) {
-    SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT);
-    return false;  // Missing header.
-  }
-
-  size_t header_end = dictionary_text.find("\n\n");
-  if (std::string::npos == header_end) {
-    SdchErrorRecovery(DICTIONARY_HAS_NO_HEADER);
-    return false;  // Missing header.
-  }
-  size_t line_start = 0;  // Start of line being parsed.
-  while (1) {
-    size_t line_end = dictionary_text.find('\n', line_start);
-    DCHECK(std::string::npos != line_end);
-    DCHECK_LE(line_end, header_end);
-
-    size_t colon_index = dictionary_text.find(':', line_start);
-    if (std::string::npos == colon_index) {
-      SdchErrorRecovery(DICTIONARY_HEADER_LINE_MISSING_COLON);
-      return false;  // Illegal line missing a colon.
-    }
-
-    if (colon_index > line_end)
-      break;
-
-    size_t value_start = dictionary_text.find_first_not_of(" \t",
-                                                           colon_index + 1);
-    if (std::string::npos != value_start) {
-      if (value_start >= line_end)
-        break;
-      std::string name(dictionary_text, line_start, colon_index - line_start);
-      std::string value(dictionary_text, value_start, line_end - value_start);
-      name = base::StringToLowerASCII(name);
-      if (name == "domain") {
-        domain = value;
-      } else if (name == "path") {
-        path = value;
-      } else if (name == "format-version") {
-        if (value != "1.0")
-          return false;
-      } else if (name == "max-age") {
-        int64 seconds;
-        base::StringToInt64(value, &seconds);
-        expiration = base::Time::Now() + base::TimeDelta::FromSeconds(seconds);
-      } else if (name == "port") {
-        int port;
-        base::StringToInt(value, &port);
-        if (port >= 0)
-          ports.insert(port);
-      }
-    }
-
-    if (line_end >= header_end)
-      break;
-    line_start = line_end + 1;
-  }
-
-  if (!IsInSupportedDomain(dictionary_url))
-    return false;
-
-  if (!Dictionary::CanSet(domain, path, ports, dictionary_url))
-    return false;
-
-  // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of
-  // useless dictionaries.  We should probably have a cache eviction plan,
-  // instead of just blocking additions.  For now, with the spec in flux, it
-  // is probably not worth doing eviction handling.
-  if (kMaxDictionarySize < dictionary_text.size()) {
-    SdchErrorRecovery(DICTIONARY_IS_TOO_LARGE);
-    return false;
-  }
-  if (kMaxDictionaryCount <= dictionaries_.size()) {
-    SdchErrorRecovery(DICTIONARY_COUNT_EXCEEDED);
-    return false;
-  }
-
-  UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size());
-  DVLOG(1) << "Loaded dictionary with client hash " << client_hash
-           << " and server hash " << server_hash;
-  Dictionary* dictionary =
-      new Dictionary(dictionary_text, header_end + 2, client_hash,
-                     dictionary_url, domain, path, expiration, ports);
-  dictionaries_[server_hash] = dictionary;
-  return true;
-}
-
 void SdchManager::GetVcdiffDictionary(
     const std::string& server_hash,
     const GURL& referring_url,
@@ -579,6 +478,107 @@
   allow_latency_experiment_.erase(it);
 }
 
+void SdchManager::AddSdchDictionary(const std::string& dictionary_text,
+    const GURL& dictionary_url) {
+  DCHECK(CalledOnValidThread());
+  std::string client_hash;
+  std::string server_hash;
+  GenerateHash(dictionary_text, &client_hash, &server_hash);
+  if (dictionaries_.find(server_hash) != dictionaries_.end()) {
+    SdchErrorRecovery(DICTIONARY_ALREADY_LOADED);
+    return;                             // Already loaded.
+  }
+
+  std::string domain, path;
+  std::set<int> ports;
+  base::Time expiration(base::Time::Now() + base::TimeDelta::FromDays(30));
+
+  if (dictionary_text.empty()) {
+    SdchErrorRecovery(DICTIONARY_HAS_NO_TEXT);
+    return;                             // Missing header.
+  }
+
+  size_t header_end = dictionary_text.find("\n\n");
+  if (std::string::npos == header_end) {
+    SdchErrorRecovery(DICTIONARY_HAS_NO_HEADER);
+    return;                             // Missing header.
+  }
+  size_t line_start = 0;  // Start of line being parsed.
+  while (1) {
+    size_t line_end = dictionary_text.find('\n', line_start);
+    DCHECK(std::string::npos != line_end);
+    DCHECK_LE(line_end, header_end);
+
+    size_t colon_index = dictionary_text.find(':', line_start);
+    if (std::string::npos == colon_index) {
+      SdchErrorRecovery(DICTIONARY_HEADER_LINE_MISSING_COLON);
+      return;                         // Illegal line missing a colon.
+    }
+
+    if (colon_index > line_end)
+      break;
+
+    size_t value_start = dictionary_text.find_first_not_of(" \t",
+                                                           colon_index + 1);
+    if (std::string::npos != value_start) {
+      if (value_start >= line_end)
+        break;
+      std::string name(dictionary_text, line_start, colon_index - line_start);
+      std::string value(dictionary_text, value_start, line_end - value_start);
+      name = base::StringToLowerASCII(name);
+      if (name == "domain") {
+        domain = value;
+      } else if (name == "path") {
+        path = value;
+      } else if (name == "format-version") {
+        if (value != "1.0")
+          return;
+      } else if (name == "max-age") {
+        int64 seconds;
+        base::StringToInt64(value, &seconds);
+        expiration = base::Time::Now() + base::TimeDelta::FromSeconds(seconds);
+      } else if (name == "port") {
+        int port;
+        base::StringToInt(value, &port);
+        if (port >= 0)
+          ports.insert(port);
+      }
+    }
+
+    if (line_end >= header_end)
+      break;
+    line_start = line_end + 1;
+  }
+
+  if (!IsInSupportedDomain(dictionary_url))
+    return;
+
+  if (!Dictionary::CanSet(domain, path, ports, dictionary_url))
+    return;
+
+  // TODO(jar): Remove these hacks to preclude a DOS attack involving piles of
+  // useless dictionaries.  We should probably have a cache eviction plan,
+  // instead of just blocking additions.  For now, with the spec in flux, it
+  // is probably not worth doing eviction handling.
+  if (kMaxDictionarySize < dictionary_text.size()) {
+    SdchErrorRecovery(DICTIONARY_IS_TOO_LARGE);
+    return;
+  }
+  if (kMaxDictionaryCount <= dictionaries_.size()) {
+    SdchErrorRecovery(DICTIONARY_COUNT_EXCEEDED);
+    return;
+  }
+
+  UMA_HISTOGRAM_COUNTS("Sdch3.Dictionary size loaded", dictionary_text.size());
+  DVLOG(1) << "Loaded dictionary with client hash " << client_hash
+           << " and server hash " << server_hash;
+  Dictionary* dictionary =
+      new Dictionary(dictionary_text, header_end + 2, client_hash,
+                     dictionary_url, domain, path, expiration, ports);
+  dictionaries_[server_hash] = dictionary;
+  return;
+}
+
 // static
 void SdchManager::UrlSafeBase64Encode(const std::string& input,
                                       std::string* output) {