| OLD | NEW | 
|---|
| (Empty) |  | 
|  | 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 
|  | 2 // Use of this source code is governed by a BSD-style license that can be | 
|  | 3 // found in the LICENSE file. | 
|  | 4 | 
|  | 5 #include "net/test/embedded_test_server/request_helpers.h" | 
|  | 6 | 
|  | 7 #include <stdlib.h> | 
|  | 8 #include <ctime> | 
|  | 9 #include <map> | 
|  | 10 #include <sstream> | 
|  | 11 #include <string> | 
|  | 12 | 
|  | 13 #include "base/base64.h" | 
|  | 14 #include "base/files/file_path.h" | 
|  | 15 #include "base/files/file_util.h" | 
|  | 16 #include "base/format_macros.h" | 
|  | 17 #include "base/md5.h" | 
|  | 18 #include "base/path_service.h" | 
|  | 19 #include "base/strings/string_split.h" | 
|  | 20 #include "base/strings/string_util.h" | 
|  | 21 #include "base/strings/stringprintf.h" | 
|  | 22 #include "base/thread_task_runner_handle.h" | 
|  | 23 #include "base/threading/thread_restrictions.h" | 
|  | 24 #include "base/time/time.h" | 
|  | 25 #include "net/base/escape.h" | 
|  | 26 #include "net/base/url_util.h" | 
|  | 27 #include "net/test/embedded_test_server/embedded_test_server.h" | 
|  | 28 #include "net/test/embedded_test_server/http_request.h" | 
|  | 29 #include "net/test/embedded_test_server/http_response.h" | 
|  | 30 | 
|  | 31 #define NOT_HANDLED scoped_ptr<HttpResponse>() | 
|  | 32 | 
|  | 33 net::UnescapeRule::Type UNESCAPE_ALL = | 
|  | 34     net::UnescapeRule::SPACES | net::UnescapeRule::URL_SPECIAL_CHARS | | 
|  | 35     net::UnescapeRule::SPOOFING_AND_CONTROL_CHARS | | 
|  | 36     net::UnescapeRule::REPLACE_PLUS_WITH_SPACE; | 
|  | 37 | 
|  | 38 namespace net { | 
|  | 39 namespace test_server { | 
|  | 40 | 
|  | 41 void CustomHttpResponse::SendResponse(SendCallback send, | 
|  | 42                                       SendDoneCallback done) { | 
|  | 43   std::string response; | 
|  | 44   if (headers_.size() != 0 || contents_.size() != 0) | 
|  | 45     response = headers_ + "\r\n" + contents_; | 
|  | 46   send.Run(response, done); | 
|  | 47 } | 
|  | 48 | 
|  | 49 bool ShouldHandle(const HttpRequest& request, std::string url) { | 
|  | 50   if (request.relative_url.compare(0, url.size(), url) == 0) { | 
|  | 51     if (request.relative_url.size() == url.size()) | 
|  | 52       return true; | 
|  | 53     std::string endings("/?;#"); | 
|  | 54     if (endings.find(request.relative_url.at(url.size())) != std::string::npos) | 
|  | 55       return true; | 
|  | 56   } | 
|  | 57   return false; | 
|  | 58 } | 
|  | 59 | 
|  | 60 GURL ToGURL(const HttpRequest& request) { | 
|  | 61   return GURL("http://localhost" + request.relative_url); | 
|  | 62 } | 
|  | 63 | 
|  | 64 RequestQuery ParseQuery(GURL url) { | 
|  | 65   RequestQuery queries; | 
|  | 66 | 
|  | 67   for (QueryIterator it(url); !it.IsAtEnd(); it.Advance()) { | 
|  | 68     queries[net::UnescapeURLComponent(it.GetKey(), UNESCAPE_ALL)].push_back( | 
|  | 69         it.GetUnescapedValue()); | 
|  | 70   } | 
|  | 71   return queries; | 
|  | 72 } | 
|  | 73 | 
|  | 74 // Handles |request| by serving a file from under |server_root|. | 
|  | 75 scoped_ptr<HttpResponse> HandleFileRequest(const base::FilePath& server_root, | 
|  | 76                                            const HttpRequest& request) { | 
|  | 77   // This is a test-only server. Ignore I/O thread restrictions. | 
|  | 78   base::ThreadRestrictions::ScopedAllowIO allow_io; | 
|  | 79 | 
|  | 80   std::string relative_url(request.relative_url); | 
|  | 81 | 
|  | 82   // A proxy request will have an absolute path. Simulate the proxy by stripping | 
|  | 83   // the scheme, host, and port. | 
|  | 84   GURL request_gurl = ToGURL(request); | 
|  | 85   relative_url = request_gurl.path(); | 
|  | 86 | 
|  | 87   std::string files_prefix("/files/"); | 
|  | 88   if (relative_url.compare(0, files_prefix.size(), files_prefix) == 0) { | 
|  | 89     LOG(ERROR) << "Using old-style /files/ for: " << relative_url; | 
|  | 90     relative_url = relative_url.substr(files_prefix.size() - 1); | 
|  | 91   } | 
|  | 92 | 
|  | 93   std::string post_prefix("/post/"); | 
|  | 94   if (relative_url.compare(0, post_prefix.size(), post_prefix) == 0) { | 
|  | 95     relative_url = relative_url.substr(post_prefix.size() - 1); | 
|  | 96     if (request.method != METHOD_POST) | 
|  | 97       return NOT_HANDLED; | 
|  | 98   } | 
|  | 99 | 
|  | 100   RequestQuery query = ParseQuery(request_gurl); | 
|  | 101 | 
|  | 102   if (query.find("expected_body") != query.end()) { | 
|  | 103     if (request.content.find(query["expected_body"].front()) == | 
|  | 104         std::string::npos) { | 
|  | 105       scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | 
|  | 106       not_found_response->set_code(HTTP_NOT_FOUND); | 
|  | 107       return not_found_response.Pass(); | 
|  | 108     } | 
|  | 109   } | 
|  | 110 | 
|  | 111   if (query.find("expected_headers") != query.end()) { | 
|  | 112     std::vector<std::string> headers = query["expected_headers"]; | 
|  | 113     for (size_t i = 0; i < headers.size(); ++i) { | 
|  | 114       std::string key = headers[i].substr(0, headers[i].find(":")); | 
|  | 115       std::string value = headers[i].substr(headers[i].find(":") + 1); | 
|  | 116       if (request.headers.find(key) == request.headers.end() || | 
|  | 117           request.headers.at(key) != value) { | 
|  | 118         scoped_ptr<BasicHttpResponse> not_found_response(new BasicHttpResponse); | 
|  | 119         not_found_response->set_code(HTTP_NOT_FOUND); | 
|  | 120         return not_found_response.Pass(); | 
|  | 121       } | 
|  | 122     } | 
|  | 123   } | 
|  | 124 | 
|  | 125   // Trim the first byte ('/'). | 
|  | 126   std::string request_path = relative_url.substr(1); | 
|  | 127   base::FilePath file_path(server_root.AppendASCII(request_path)); | 
|  | 128   std::string file_contents; | 
|  | 129   if (!base::ReadFileToString(file_path, &file_contents)) { | 
|  | 130     file_path = file_path.AppendASCII("index.html"); | 
|  | 131     if (!base::ReadFileToString(file_path, &file_contents)) | 
|  | 132       return NOT_HANDLED; | 
|  | 133   } | 
|  | 134 | 
|  | 135   if (query.find("replace_text") != query.end()) { | 
|  | 136     std::vector<std::string> replacements = query["replace_text"]; | 
|  | 137     for (size_t i = 0; i < replacements.size(); ++i) { | 
|  | 138       std::string find, with; | 
|  | 139       base::Base64Decode(replacements[i].substr(0, replacements[i].find(":")), | 
|  | 140                          &find); | 
|  | 141       base::Base64Decode(replacements[i].substr(replacements[i].find(":") + 1), | 
|  | 142                          &with); | 
|  | 143       base::ReplaceSubstringsAfterOffset(&file_contents, 0, find, with); | 
|  | 144     } | 
|  | 145   } | 
|  | 146 | 
|  | 147   base::FilePath headers_path( | 
|  | 148       file_path.AddExtension(FILE_PATH_LITERAL("mock-http-headers"))); | 
|  | 149 | 
|  | 150   if (base::PathExists(headers_path)) { | 
|  | 151     std::string headers_contents; | 
|  | 152 | 
|  | 153     if (!base::ReadFileToString(headers_path, &headers_contents)) | 
|  | 154       return NOT_HANDLED; | 
|  | 155 | 
|  | 156     if (request.method == METHOD_HEAD) | 
|  | 157       file_contents = ""; | 
|  | 158 | 
|  | 159     scoped_ptr<CustomHttpResponse> http_response( | 
|  | 160         new CustomHttpResponse(headers_contents, file_contents)); | 
|  | 161     return http_response.Pass(); | 
|  | 162   } | 
|  | 163 | 
|  | 164   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 165   http_response->set_code(HTTP_OK); | 
|  | 166 | 
|  | 167   if (request.headers.find("Range") != request.headers.end()) { | 
|  | 168     std::string range_header = request.headers.at("Range"); | 
|  | 169     if (range_header.compare(0, 6, "bytes=") == 0) { | 
|  | 170       range_header = range_header.substr(6); | 
|  | 171 | 
|  | 172       size_t start = 0; | 
|  | 173       size_t end = file_contents.size(); | 
|  | 174       size_t delim = range_header.find("-"); | 
|  | 175 | 
|  | 176       if (delim == std::string::npos) { | 
|  | 177         start = std::atoi(range_header.c_str()); | 
|  | 178       } else if (delim == range_header.size() - 1) { | 
|  | 179         start = std::atoi(range_header.substr(0, delim).c_str()); | 
|  | 180       } else if (delim == 0) { | 
|  | 181         start = end - std::atoi(range_header.substr(1).c_str()); | 
|  | 182       } else { | 
|  | 183         start = std::atoi(range_header.substr(0, delim).c_str()); | 
|  | 184         end = std::atoi(range_header.substr(delim + 1).c_str()); | 
|  | 185       } | 
|  | 186 | 
|  | 187       http_response->set_code(HTTP_PARTIAL_CONTENT); | 
|  | 188       http_response->AddCustomHeader( | 
|  | 189           "Content-Range", | 
|  | 190           base::StringPrintf("bytes %" PRIuS "-%" PRIuS "/%" PRIuS, start, | 
|  | 191                              end - 1, file_contents.size())); | 
|  | 192 | 
|  | 193       file_contents = file_contents.substr(start, end - start); | 
|  | 194     } | 
|  | 195   } | 
|  | 196 | 
|  | 197   base::FilePath::StringType ext = file_path.FinalExtension(); | 
|  | 198   if (ext == FILE_PATH_LITERAL(".crx")) | 
|  | 199     http_response->set_content_type("application/x-chrome-extension"); | 
|  | 200   else if (ext == FILE_PATH_LITERAL(".exe")) | 
|  | 201     http_response->set_content_type("application/octet-stream"); | 
|  | 202   else if (ext == FILE_PATH_LITERAL(".gif")) | 
|  | 203     http_response->set_content_type("image/gif"); | 
|  | 204   else if (ext == FILE_PATH_LITERAL(".jpeg") || | 
|  | 205            ext == FILE_PATH_LITERAL(".jpg")) | 
|  | 206     http_response->set_content_type("image/jpeg"); | 
|  | 207   else if (ext == FILE_PATH_LITERAL(".js")) | 
|  | 208     http_response->set_content_type("application/javascript"); | 
|  | 209   else if (ext == FILE_PATH_LITERAL(".json")) | 
|  | 210     http_response->set_content_type("application/json"); | 
|  | 211   else if (ext == FILE_PATH_LITERAL(".pdf")) | 
|  | 212     http_response->set_content_type("application/pdf"); | 
|  | 213   else if (ext == FILE_PATH_LITERAL(".txt")) | 
|  | 214     http_response->set_content_type("text/plain"); | 
|  | 215   else if (ext == FILE_PATH_LITERAL(".wav")) | 
|  | 216     http_response->set_content_type("audio/wav"); | 
|  | 217   else if (ext == FILE_PATH_LITERAL(".xml")) | 
|  | 218     http_response->set_content_type("text/xml"); | 
|  | 219   else if (ext == FILE_PATH_LITERAL(".html") || | 
|  | 220            ext == FILE_PATH_LITERAL(".htm")) | 
|  | 221     http_response->set_content_type("text/html"); | 
|  | 222 | 
|  | 223   http_response->AddCustomHeader("Accept-Ranges", "bytes"); | 
|  | 224   http_response->AddCustomHeader("ETag", "'" + file_path.MaybeAsASCII() + "'"); | 
|  | 225   http_response->set_content(file_contents); | 
|  | 226   return http_response.Pass(); | 
|  | 227 } | 
|  | 228 | 
|  | 229 scoped_ptr<HttpResponse> HandleRedirectConnect(const HttpRequest& request) { | 
|  | 230   if (request.headers.find("Host") == request.headers.end() || | 
|  | 231       request.headers.at("Host") != "www.redirect.com" || | 
|  | 232       request.method != METHOD_CONNECT) | 
|  | 233     return NOT_HANDLED; | 
|  | 234 | 
|  | 235   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 236   http_response->set_code(HTTP_FOUND); | 
|  | 237   http_response->AddCustomHeader("Location", | 
|  | 238                                  "http://www.destination.com/foo.js"); | 
|  | 239   return http_response.Pass(); | 
|  | 240 } | 
|  | 241 | 
|  | 242 scoped_ptr<HttpResponse> HandleServerAuthConnect(const HttpRequest& request) { | 
|  | 243   if (request.headers.find("Host") == request.headers.end() || | 
|  | 244       request.headers.at("Host") != "www.server-auth.com" || | 
|  | 245       request.method != METHOD_CONNECT) | 
|  | 246     return NOT_HANDLED; | 
|  | 247 | 
|  | 248   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 249   http_response->set_code(HTTP_UNAUTHORIZED); | 
|  | 250   http_response->AddCustomHeader("WWW-Authenticate", | 
|  | 251                                  "Basic realm=\"WallyWorld\""); | 
|  | 252   return http_response.Pass(); | 
|  | 253 } | 
|  | 254 | 
|  | 255 scoped_ptr<HttpResponse> HandleDefaultConnect(const HttpRequest& request) { | 
|  | 256   if (request.method != METHOD_CONNECT) | 
|  | 257     return NOT_HANDLED; | 
|  | 258 | 
|  | 259   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 260   http_response->set_code(HTTP_BAD_REQUEST); | 
|  | 261   http_response->set_content( | 
|  | 262       "Your client has issued a malformed or illegal request."); | 
|  | 263   http_response->set_content_type("text/html"); | 
|  | 264   return http_response.Pass(); | 
|  | 265 } | 
|  | 266 | 
|  | 267 scoped_ptr<HttpResponse> HandleCacheControl(std::string url, | 
|  | 268                                             std::string value, | 
|  | 269                                             const HttpRequest& request) { | 
|  | 270   if (!ShouldHandle(request, url)) | 
|  | 271     return NOT_HANDLED; | 
|  | 272 | 
|  | 273   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 274   http_response->set_code(HTTP_OK); | 
|  | 275   std::stringstream time; | 
|  | 276   time << std::time(0); | 
|  | 277   http_response->set_content("<html><head><title>" + time.str() + | 
|  | 278                              "</title></head></html>"); | 
|  | 279   http_response->set_content_type("text/html"); | 
|  | 280   http_response->AddCustomHeader("Cache-Control", value); | 
|  | 281   return http_response.Pass(); | 
|  | 282 } | 
|  | 283 | 
|  | 284 scoped_ptr<HttpResponse> HandleCacheExpires(const HttpRequest& request) { | 
|  | 285   if (!ShouldHandle(request, "/cache/expires")) | 
|  | 286     return NOT_HANDLED; | 
|  | 287 | 
|  | 288   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 289   http_response->set_code(HTTP_OK); | 
|  | 290   std::stringstream time; | 
|  | 291   time << std::time(0); | 
|  | 292   http_response->set_content("<html><head><title>" + time.str() + | 
|  | 293                              "</title></head></html>"); | 
|  | 294   http_response->set_content_type("text/html"); | 
|  | 295   http_response->AddCustomHeader("Expires", "Thu, 1 Jan 2099 00:00:00 GMT"); | 
|  | 296   return http_response.Pass(); | 
|  | 297 } | 
|  | 298 | 
|  | 299 scoped_ptr<HttpResponse> HandleEchoHeader(std::string url, | 
|  | 300                                           std::string value, | 
|  | 301                                           const HttpRequest& request) { | 
|  | 302   if (!ShouldHandle(request, url)) | 
|  | 303     return NOT_HANDLED; | 
|  | 304 | 
|  | 305   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 306   http_response->set_code(HTTP_OK); | 
|  | 307 | 
|  | 308   GURL request_gurl = ToGURL(request); | 
|  | 309   if (request_gurl.has_query()) { | 
|  | 310     std::string header_name = request_gurl.query(); | 
|  | 311     http_response->AddCustomHeader("Vary", header_name); | 
|  | 312     if (request.headers.find(header_name) != request.headers.end()) | 
|  | 313       http_response->set_content(request.headers.at(header_name)); | 
|  | 314     else | 
|  | 315       http_response->set_content("None"); | 
|  | 316   } | 
|  | 317 | 
|  | 318   http_response->set_content_type("text/plain"); | 
|  | 319   http_response->AddCustomHeader("Cache-Control", value); | 
|  | 320   return http_response.Pass(); | 
|  | 321 } | 
|  | 322 | 
|  | 323 scoped_ptr<HttpResponse> HandleEcho(const HttpRequest& request) { | 
|  | 324   if (!ShouldHandle(request, "/echo")) | 
|  | 325     return NOT_HANDLED; | 
|  | 326 | 
|  | 327   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 328   http_response->set_code(HTTP_OK); | 
|  | 329 | 
|  | 330   GURL request_gurl = ToGURL(request); | 
|  | 331   if (request_gurl.has_query()) { | 
|  | 332     RequestQuery query = ParseQuery(request_gurl); | 
|  | 333     if (query.find("status") != query.end()) | 
|  | 334       http_response->set_code(static_cast<HttpStatusCode>( | 
|  | 335           std::atoi(query["status"].front().c_str()))); | 
|  | 336   } | 
|  | 337 | 
|  | 338   http_response->set_content_type("text/html"); | 
|  | 339   if (request.method != METHOD_POST && request.method != METHOD_PUT) | 
|  | 340     http_response->set_content("Echo"); | 
|  | 341   else | 
|  | 342     http_response->set_content(request.content); | 
|  | 343   return http_response.Pass(); | 
|  | 344 } | 
|  | 345 | 
|  | 346 scoped_ptr<HttpResponse> HandleEchoTitle(const HttpRequest& request) { | 
|  | 347   if (!ShouldHandle(request, "/echotitle")) | 
|  | 348     return NOT_HANDLED; | 
|  | 349 | 
|  | 350   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 351   http_response->set_code(HTTP_OK); | 
|  | 352   http_response->set_content_type("text/html"); | 
|  | 353   http_response->set_content("<html><head><title>" + request.content + | 
|  | 354                              "</title></head></html>"); | 
|  | 355   return http_response.Pass(); | 
|  | 356 } | 
|  | 357 | 
|  | 358 scoped_ptr<HttpResponse> HandleEchoAll(const HttpRequest& request) { | 
|  | 359   if (!ShouldHandle(request, "/echoall")) | 
|  | 360     return NOT_HANDLED; | 
|  | 361 | 
|  | 362   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 363   http_response->set_code(HTTP_OK); | 
|  | 364 | 
|  | 365   std::string body; | 
|  | 366   body += | 
|  | 367       "<html><head><style>" | 
|  | 368       "pre { border: 1px solid black; margin: 5px; padding: 5px }" | 
|  | 369       "</style></head><body>" | 
|  | 370       "<div style=\"float: right\">" | 
|  | 371       "<a href=\"/echo\">back to referring page</a></div>" | 
|  | 372       "<h1>Request Body:</h1><pre>"; | 
|  | 373 | 
|  | 374   if (request.has_content) { | 
|  | 375     std::vector<std::string> qs = base::SplitString( | 
|  | 376         request.content, "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 
|  | 377     for (size_t i = 0; i < qs.size(); ++i) { | 
|  | 378       body += qs[i] + "\n"; | 
|  | 379     } | 
|  | 380   } | 
|  | 381 | 
|  | 382   body += | 
|  | 383       "</pre>" | 
|  | 384       "<h1>Request Headers:</h1><pre>" + | 
|  | 385       request.all_headers + | 
|  | 386       "</pre>" | 
|  | 387       "</body></html>"; | 
|  | 388 | 
|  | 389   http_response->set_content_type("text/html"); | 
|  | 390   http_response->set_content(body); | 
|  | 391   return http_response.Pass(); | 
|  | 392 } | 
|  | 393 | 
|  | 394 scoped_ptr<HttpResponse> HandleSetCookie(const HttpRequest& request) { | 
|  | 395   if (!ShouldHandle(request, "/set-cookie")) | 
|  | 396     return NOT_HANDLED; | 
|  | 397 | 
|  | 398   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 399   http_response->set_code(HTTP_OK); | 
|  | 400   http_response->set_content_type("text/html"); | 
|  | 401   std::string content; | 
|  | 402   GURL request_gurl = ToGURL(request); | 
|  | 403   if (request_gurl.has_query()) { | 
|  | 404     std::vector<std::string> cookies = base::SplitString( | 
|  | 405         request_gurl.query(), "&", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 
|  | 406     for (size_t i = 0; i < cookies.size(); ++i) { | 
|  | 407       http_response->AddCustomHeader("Set-Cookie", cookies[i]); | 
|  | 408       content += cookies[i]; | 
|  | 409     } | 
|  | 410   } | 
|  | 411 | 
|  | 412   http_response->set_content(content); | 
|  | 413   return http_response.Pass(); | 
|  | 414 } | 
|  | 415 | 
|  | 416 scoped_ptr<HttpResponse> HandleSetManyCookies(const HttpRequest& request) { | 
|  | 417   if (!ShouldHandle(request, "/set-many-cookies")) | 
|  | 418     return NOT_HANDLED; | 
|  | 419 | 
|  | 420   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 421   http_response->set_code(HTTP_OK); | 
|  | 422   http_response->set_content_type("text/html"); | 
|  | 423   std::string content; | 
|  | 424 | 
|  | 425   GURL request_gurl = ToGURL(request); | 
|  | 426   size_t num = 0; | 
|  | 427   if (request_gurl.has_query()) { | 
|  | 428     num = std::atoi(request_gurl.query().c_str()); | 
|  | 429   } | 
|  | 430 | 
|  | 431   for (size_t i = 0; i < num; ++i) { | 
|  | 432     http_response->AddCustomHeader("Set-Cookie", "a="); | 
|  | 433   } | 
|  | 434 | 
|  | 435   http_response->set_content( | 
|  | 436       base::StringPrintf("%" PRIuS " cookies were sent", num)); | 
|  | 437   return http_response.Pass(); | 
|  | 438 } | 
|  | 439 | 
|  | 440 scoped_ptr<HttpResponse> HandleExpectAndSetCookie(const HttpRequest& request) { | 
|  | 441   if (!ShouldHandle(request, "/expect-and-set-cookie")) | 
|  | 442     return NOT_HANDLED; | 
|  | 443 | 
|  | 444   std::vector<std::string> sentCookies; | 
|  | 445   if (request.headers.find("Cookie") != request.headers.end()) { | 
|  | 446     std::vector<std::string> cookies = | 
|  | 447         base::SplitString(request.headers.at("Cookie"), ";", | 
|  | 448                           base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 
|  | 449     for (size_t i = 0; i < cookies.size(); ++i) { | 
|  | 450       sentCookies.push_back(cookies[i]); | 
|  | 451     } | 
|  | 452   } | 
|  | 453   bool gotExpected = true; | 
|  | 454 | 
|  | 455   GURL request_gurl = ToGURL(request); | 
|  | 456   RequestQuery qs = ParseQuery(request_gurl); | 
|  | 457   if (qs.find("expect") != qs.end()) { | 
|  | 458     std::vector<std::string> expected = qs.at("expect"); | 
|  | 459     for (size_t i = 0; i < expected.size(); ++i) { | 
|  | 460       bool found = false; | 
|  | 461       for (size_t j = 0; j < sentCookies.size(); ++j) { | 
|  | 462         if (expected[i] == sentCookies[j]) | 
|  | 463           found = true; | 
|  | 464       } | 
|  | 465       gotExpected &= found; | 
|  | 466     } | 
|  | 467   } | 
|  | 468 | 
|  | 469   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 470   http_response->set_code(HTTP_OK); | 
|  | 471   http_response->set_content_type("text/html"); | 
|  | 472   if (gotExpected) { | 
|  | 473     std::vector<std::string> setCookies = qs.at("set"); | 
|  | 474     for (size_t i = 0; i < setCookies.size(); ++i) { | 
|  | 475       http_response->AddCustomHeader( | 
|  | 476           "Set-Cookie", net::UnescapeURLComponent(setCookies[i], UNESCAPE_ALL)); | 
|  | 477     } | 
|  | 478   } | 
|  | 479 | 
|  | 480   std::string content; | 
|  | 481   if (qs.find("data") != qs.end()) { | 
|  | 482     std::vector<std::string> data = qs.at("data"); | 
|  | 483     for (size_t i = 0; i < data.size(); ++i) { | 
|  | 484       content += data[i]; | 
|  | 485     } | 
|  | 486   } | 
|  | 487 | 
|  | 488   http_response->set_content(content); | 
|  | 489   return http_response.Pass(); | 
|  | 490 } | 
|  | 491 | 
|  | 492 scoped_ptr<HttpResponse> HandleSetHeader(const HttpRequest& request) { | 
|  | 493   if (!ShouldHandle(request, "/set-header")) | 
|  | 494     return NOT_HANDLED; | 
|  | 495 | 
|  | 496   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 497   http_response->set_code(HTTP_OK); | 
|  | 498   http_response->set_content_type("text/html"); | 
|  | 499 | 
|  | 500   std::string content; | 
|  | 501 | 
|  | 502   GURL request_gurl = ToGURL(request); | 
|  | 503   if (request_gurl.has_query()) { | 
|  | 504     RequestQuery headers = ParseQuery(request_gurl); | 
|  | 505     for (RequestQuery::iterator it = headers.begin(); it != headers.end(); | 
|  | 506          ++it) { | 
|  | 507       std::string header = it->first; | 
|  | 508       std::string key = header.substr(0, header.find(": ")); | 
|  | 509       std::string value = header.substr(header.find(": ") + 2); | 
|  | 510       http_response->AddCustomHeader(key, value); | 
|  | 511       content += header; | 
|  | 512     } | 
|  | 513   } | 
|  | 514 | 
|  | 515   http_response->set_content(content); | 
|  | 516   return http_response.Pass(); | 
|  | 517 } | 
|  | 518 | 
|  | 519 scoped_ptr<HttpResponse> HandleNoContent(const HttpRequest& request) { | 
|  | 520   if (!ShouldHandle(request, "/nocontent")) | 
|  | 521     return NOT_HANDLED; | 
|  | 522 | 
|  | 523   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 524   http_response->set_code(HTTP_NO_CONTENT); | 
|  | 525   return http_response.Pass(); | 
|  | 526 } | 
|  | 527 | 
|  | 528 scoped_ptr<HttpResponse> HandleCloseSocket(const HttpRequest& request) { | 
|  | 529   if (!ShouldHandle(request, "/close-socket")) | 
|  | 530     return NOT_HANDLED; | 
|  | 531 | 
|  | 532   scoped_ptr<CustomHttpResponse> http_response(new CustomHttpResponse("", "")); | 
|  | 533   return http_response.Pass(); | 
|  | 534 } | 
|  | 535 | 
|  | 536 scoped_ptr<HttpResponse> HandleAuthBasic(const HttpRequest& request) { | 
|  | 537   if (!ShouldHandle(request, "/auth-basic")) | 
|  | 538     return NOT_HANDLED; | 
|  | 539 | 
|  | 540   std::string username, userpass, password, b64str; | 
|  | 541   std::string expectedPassword = "secret"; | 
|  | 542   std::string realm = "testrealm"; | 
|  | 543   bool setCookie = false; | 
|  | 544 | 
|  | 545   GURL request_gurl = ToGURL(request); | 
|  | 546   RequestQuery query = ParseQuery(request_gurl); | 
|  | 547 | 
|  | 548   if (query.find("set-cookie-if-challenged") != query.end()) | 
|  | 549     setCookie = true; | 
|  | 550   if (query.find("password") != query.end()) | 
|  | 551     expectedPassword = query.at("password").front(); | 
|  | 552   if (query.find("realm") != query.end()) | 
|  | 553     realm = query.at("realm").front(); | 
|  | 554 | 
|  | 555   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 556   bool authed = false; | 
|  | 557   std::string error; | 
|  | 558   std::string auth; | 
|  | 559   if (request.headers.find("Authorization") == request.headers.end()) { | 
|  | 560     error = "Missing Authorization Header"; | 
|  | 561   } else { | 
|  | 562     auth = request.headers.at("Authorization"); | 
|  | 563     b64str = auth.substr(std::string("Basic ").size()); | 
|  | 564     base::Base64Decode(b64str, &userpass); | 
|  | 565     username = userpass.substr(0, userpass.find(":")); | 
|  | 566     password = userpass.substr(userpass.find(":") + 1); | 
|  | 567     if (password == expectedPassword) | 
|  | 568       authed = true; | 
|  | 569     else | 
|  | 570       error = "Invalid Credentials"; | 
|  | 571   } | 
|  | 572 | 
|  | 573   if (!authed) { | 
|  | 574     http_response->set_code(HTTP_UNAUTHORIZED); | 
|  | 575     http_response->set_content_type("text/html"); | 
|  | 576     http_response->AddCustomHeader("WWW-Authenticate", | 
|  | 577                                    "Basic realm=\"" + realm + "\""); | 
|  | 578     if (setCookie) | 
|  | 579       http_response->AddCustomHeader("Set-Cookie", "got_challenged=true"); | 
|  | 580     http_response->set_content(base::StringPrintf( | 
|  | 581         "<html><head><title>Denied: %s</title></head>" | 
|  | 582         "<body>auth=%s<p>b64str=%s<p>username: %s<p>userpass: %s<p>" | 
|  | 583         "password: %s<p>You sent:<br>%s<p></body></html>", | 
|  | 584         error.c_str(), auth.c_str(), b64str.c_str(), username.c_str(), | 
|  | 585         userpass.c_str(), password.c_str(), request.all_headers.c_str())); | 
|  | 586     return http_response.Pass(); | 
|  | 587   } | 
|  | 588 | 
|  | 589   if (request.headers.find("If-None-Match") != request.headers.end() && | 
|  | 590       request.headers.at("If-None-Match") == "abc") { | 
|  | 591     http_response->set_code(HTTP_NOT_MODIFIED); | 
|  | 592     return http_response.Pass(); | 
|  | 593   } | 
|  | 594 | 
|  | 595   base::FilePath file_path = | 
|  | 596       base::FilePath().AppendASCII(request.relative_url.substr(1)); | 
|  | 597   if (file_path.FinalExtension() == FILE_PATH_LITERAL("gif")) { | 
|  | 598     base::FilePath server_root; | 
|  | 599     PathService::Get(base::DIR_SOURCE_ROOT, &server_root); | 
|  | 600     base::FilePath gif_path = | 
|  | 601         server_root.AppendASCII("chrome/test/data/google/logo.gif"); | 
|  | 602     std::string gif_data; | 
|  | 603     base::ReadFileToString(gif_path, &gif_data); | 
|  | 604     http_response->set_content_type("image/gif"); | 
|  | 605     http_response->set_content(gif_data); | 
|  | 606   } else { | 
|  | 607     http_response->set_content_type("text/html"); | 
|  | 608     http_response->set_content( | 
|  | 609         base::StringPrintf("<html><head><title>%s/%s</title></head>" | 
|  | 610                            "<body>auth=%s<p>You sent:<br>%s<p></body></html>", | 
|  | 611                            username.c_str(), password.c_str(), auth.c_str(), | 
|  | 612                            request.all_headers.c_str())); | 
|  | 613   } | 
|  | 614 | 
|  | 615   http_response->set_code(HTTP_OK); | 
|  | 616   http_response->AddCustomHeader("Cache-Control", "max-age=60000"); | 
|  | 617   http_response->AddCustomHeader("Etag", "abc"); | 
|  | 618   return http_response.Pass(); | 
|  | 619 } | 
|  | 620 | 
|  | 621 scoped_ptr<HttpResponse> HandleAuthDigest(const HttpRequest& request) { | 
|  | 622   if (!ShouldHandle(request, "/auth-digest")) | 
|  | 623     return NOT_HANDLED; | 
|  | 624 | 
|  | 625   std::string nonce = base::MD5String( | 
|  | 626       base::StringPrintf("privatekey%s", request.relative_url.c_str())); | 
|  | 627   std::string opaque = base::MD5String("opaque"); | 
|  | 628   std::string password = "secret"; | 
|  | 629   std::string realm = "testrealm"; | 
|  | 630 | 
|  | 631   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 632   bool authed = false; | 
|  | 633   std::string error; | 
|  | 634   std::string auth; | 
|  | 635   std::string digestStr = "Digest"; | 
|  | 636   std::string username; | 
|  | 637   if (request.headers.find("Authorization") == request.headers.end()) { | 
|  | 638     error = "no auth"; | 
|  | 639   } else if (request.headers.at("Authorization").substr(0, digestStr.size()) != | 
|  | 640              digestStr) { | 
|  | 641     error = "not digest"; | 
|  | 642   } else { | 
|  | 643     auth = request.headers.at("Authorization"); | 
|  | 644 | 
|  | 645     std::map<std::string, std::string> authPairs; | 
|  | 646     std::vector<std::string> authVector = base::SplitString( | 
|  | 647         auth, ", ", base::KEEP_WHITESPACE, base::SPLIT_WANT_ALL); | 
|  | 648     for (size_t i = 0; i < authVector.size(); ++i) { | 
|  | 649       std::string key = authVector[i].substr(0, authVector[i].find("=")); | 
|  | 650       std::string value = authVector[i].substr(authVector[i].find("=") + 1); | 
|  | 651       if (value.substr(0, 1) == "\"" && value.substr(value.size() - 1) == "\"") | 
|  | 652         value = value.substr(1, value.size() - 2); | 
|  | 653       authPairs[key] = value; | 
|  | 654     } | 
|  | 655 | 
|  | 656     if (authPairs["nonce"] != nonce) { | 
|  | 657       error = "wrong nonce"; | 
|  | 658     } else if (authPairs["opaque"] != opaque) { | 
|  | 659       error = "wrong opaque"; | 
|  | 660     } else { | 
|  | 661       username = authPairs["username"]; | 
|  | 662 | 
|  | 663       std::string hA1 = base::MD5String( | 
|  | 664           base::StringPrintf("%s:%s:%s", authPairs["username"].c_str(), | 
|  | 665                              realm.c_str(), password.c_str())); | 
|  | 666       std::string hA2 = base::MD5String(base::StringPrintf( | 
|  | 667           "%s:%s", request.method_string.c_str(), authPairs["uri"].c_str())); | 
|  | 668 | 
|  | 669       std::string response; | 
|  | 670       if (authPairs.find("qop") != authPairs.end() && | 
|  | 671           authPairs.find("nc") != authPairs.end() && | 
|  | 672           authPairs.find("cnonce") != authPairs.end()) { | 
|  | 673         response = base::MD5String(base::StringPrintf( | 
|  | 674             "%s:%s:%s:%s:%s:%s", hA1.c_str(), nonce.c_str(), | 
|  | 675             authPairs["nc"].c_str(), authPairs["cnonce"].c_str(), | 
|  | 676             authPairs["qop"].c_str(), hA2.c_str())); | 
|  | 677       } else { | 
|  | 678         response = base::MD5String(base::StringPrintf( | 
|  | 679             "%s:%s:%s", hA1.c_str(), nonce.c_str(), hA2.c_str())); | 
|  | 680       } | 
|  | 681 | 
|  | 682       if (authPairs["response"] == response) | 
|  | 683         authed = true; | 
|  | 684       else | 
|  | 685         error = "wrong password"; | 
|  | 686     } | 
|  | 687   } | 
|  | 688 | 
|  | 689   if (!authed) { | 
|  | 690     http_response->set_code(HTTP_UNAUTHORIZED); | 
|  | 691     http_response->set_content_type("text/html"); | 
|  | 692     std::string authHeader = base::StringPrintf( | 
|  | 693         "Digest realm=\"%s\", " | 
|  | 694         "domain=\"/\", qop=\"auth\", algorithm=MD5, nonce=\"%s\", " | 
|  | 695         "opaque=\"%s\"", | 
|  | 696         realm.c_str(), nonce.c_str(), opaque.c_str()); | 
|  | 697     http_response->AddCustomHeader("WWW-Authenticate", authHeader); | 
|  | 698     http_response->set_content(base::StringPrintf( | 
|  | 699         "<html><head><title>Denied: %s</title></head>" | 
|  | 700         "<body>auth=%s<p>" | 
|  | 701         "You sent:<br>%s<p>We are replying:<br>%s<p></body></html>", | 
|  | 702         error.c_str(), auth.c_str(), request.all_headers.c_str(), | 
|  | 703         authHeader.c_str())); | 
|  | 704     return http_response.Pass(); | 
|  | 705   } | 
|  | 706 | 
|  | 707   http_response->set_content_type("text/html"); | 
|  | 708   http_response->set_content( | 
|  | 709       base::StringPrintf("<html><head><title>%s/%s</title></head>" | 
|  | 710                          "<body>auth=%s<p></body></html>", | 
|  | 711                          username.c_str(), password.c_str(), auth.c_str())); | 
|  | 712 | 
|  | 713   return http_response.Pass(); | 
|  | 714 } | 
|  | 715 | 
|  | 716 scoped_ptr<HttpResponse> HandleServerRedirect(const HttpRequest& request) { | 
|  | 717   if (!ShouldHandle(request, "/server-redirect")) | 
|  | 718     return NOT_HANDLED; | 
|  | 719 | 
|  | 720   GURL request_gurl = ToGURL(request); | 
|  | 721   std::string dest = | 
|  | 722       net::UnescapeURLComponent(request_gurl.query(), UNESCAPE_ALL); | 
|  | 723 | 
|  | 724   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 725   http_response->set_code(HTTP_MOVED_PERMANENTLY); | 
|  | 726   http_response->AddCustomHeader("Location", dest); | 
|  | 727   http_response->set_content_type("text/html"); | 
|  | 728   http_response->set_content(base::StringPrintf( | 
|  | 729       "<html><head></head><body>Redirecting to %s</body></html>", | 
|  | 730       dest.c_str())); | 
|  | 731   return http_response.Pass(); | 
|  | 732 } | 
|  | 733 | 
|  | 734 scoped_ptr<HttpResponse> HandleCrossSiteRedirect(EmbeddedTestServer* server, | 
|  | 735                                                  const HttpRequest& request) { | 
|  | 736   if (!ShouldHandle(request, "/cross-site")) | 
|  | 737     return NOT_HANDLED; | 
|  | 738 | 
|  | 739   std::string destAll = net::UnescapeURLComponent( | 
|  | 740       request.relative_url.substr(std::string("/cross-site").size() + 1), | 
|  | 741       UNESCAPE_ALL); | 
|  | 742 | 
|  | 743   std::string dest = base::StringPrintf( | 
|  | 744       "//%s:%hu/%s", destAll.substr(0, destAll.find("/")).c_str(), | 
|  | 745       server->port(), destAll.substr(destAll.find("/") + 1).c_str()); | 
|  | 746 | 
|  | 747   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 748   http_response->set_code(HTTP_MOVED_PERMANENTLY); | 
|  | 749   http_response->AddCustomHeader("Location", dest); | 
|  | 750   http_response->set_content_type("text/html"); | 
|  | 751   http_response->set_content(base::StringPrintf( | 
|  | 752       "<html><head></head><body>Redirecting to %s</body></html>", | 
|  | 753       dest.c_str())); | 
|  | 754   return http_response.Pass(); | 
|  | 755 } | 
|  | 756 | 
|  | 757 scoped_ptr<HttpResponse> HandleClientRedirect(const HttpRequest& request) { | 
|  | 758   if (!ShouldHandle(request, "/client-redirect")) | 
|  | 759     return NOT_HANDLED; | 
|  | 760 | 
|  | 761   GURL request_gurl = ToGURL(request); | 
|  | 762   std::string dest = | 
|  | 763       net::UnescapeURLComponent(request_gurl.query(), UNESCAPE_ALL); | 
|  | 764 | 
|  | 765   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 766   http_response->set_code(HTTP_OK); | 
|  | 767   http_response->set_content_type("text/html"); | 
|  | 768   http_response->set_content(base::StringPrintf( | 
|  | 769       "<html><head><meta http-equiv=\"refresh\" content=\"0;url=%s\"></head>" | 
|  | 770       "<body>Redirecting to %s</body></html>", | 
|  | 771       dest.c_str(), dest.c_str())); | 
|  | 772   return http_response.Pass(); | 
|  | 773 } | 
|  | 774 | 
|  | 775 scoped_ptr<HttpResponse> HandleDefaultResponse(const HttpRequest& request) { | 
|  | 776   if (!ShouldHandle(request, "/defaultresponse")) | 
|  | 777     return NOT_HANDLED; | 
|  | 778 | 
|  | 779   scoped_ptr<BasicHttpResponse> http_response(new BasicHttpResponse); | 
|  | 780   http_response->set_code(HTTP_OK); | 
|  | 781   http_response->set_content_type("text/html"); | 
|  | 782   http_response->set_content("Default response given for path: " + | 
|  | 783                              request.relative_url); | 
|  | 784   return http_response.Pass(); | 
|  | 785 } | 
|  | 786 | 
|  | 787 class DelayedHttpResponse : public BasicHttpResponse { | 
|  | 788  public: | 
|  | 789   DelayedHttpResponse(double delay) : delay_(delay) {} | 
|  | 790 | 
|  | 791   void SendResponse(SendCallback send, SendDoneCallback done) override { | 
|  | 792     base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( | 
|  | 793         FROM_HERE, base::Bind(send, ToResponseString(), done), | 
|  | 794         base::TimeDelta::FromSecondsD(delay_)); | 
|  | 795   } | 
|  | 796 | 
|  | 797  private: | 
|  | 798   double delay_; | 
|  | 799 }; | 
|  | 800 | 
|  | 801 scoped_ptr<HttpResponse> HandleSlowServer(const HttpRequest& request) { | 
|  | 802   if (!ShouldHandle(request, "/slow")) | 
|  | 803     return NOT_HANDLED; | 
|  | 804 | 
|  | 805   double delay = 1.0f; | 
|  | 806 | 
|  | 807   GURL request_gurl = ToGURL(request); | 
|  | 808   if (request_gurl.has_query()) { | 
|  | 809     delay = std::atof(request_gurl.query().c_str()); | 
|  | 810   } | 
|  | 811 | 
|  | 812   scoped_ptr<BasicHttpResponse> http_response(new DelayedHttpResponse(delay)); | 
|  | 813   http_response->set_code(HTTP_OK); | 
|  | 814   http_response->set_content_type("text/plain"); | 
|  | 815   http_response->set_content(base::StringPrintf("waited %.1f seconds", delay)); | 
|  | 816   return http_response.Pass(); | 
|  | 817 } | 
|  | 818 | 
|  | 819 void RegisterDefaultHandlers(EmbeddedTestServer* server) { | 
|  | 820   server->RegisterDefaultHandler(base::Bind(&HandleRedirectConnect)); | 
|  | 821   server->RegisterDefaultHandler(base::Bind(&HandleServerAuthConnect)); | 
|  | 822   server->RegisterDefaultHandler(base::Bind(&HandleDefaultConnect)); | 
|  | 823 | 
|  | 824   server->RegisterDefaultHandler( | 
|  | 825       base::Bind(&HandleCacheControl, "/nocachetime/maxage", "max-age=0")); | 
|  | 826   server->RegisterDefaultHandler( | 
|  | 827       base::Bind(&HandleCacheControl, "/nocachetime", "no-cache")); | 
|  | 828   server->RegisterDefaultHandler( | 
|  | 829       base::Bind(&HandleCacheControl, "/cachetime", "max-age=60")); | 
|  | 830   server->RegisterDefaultHandler(base::Bind(&HandleCacheExpires)); | 
|  | 831   server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | 
|  | 832                                             "/cache/proxy-revalidate", | 
|  | 833                                             "max-age=60, proxy-revalidate")); | 
|  | 834   server->RegisterDefaultHandler( | 
|  | 835       base::Bind(&HandleCacheControl, "/cache/private", "max-age=3, private")); | 
|  | 836   server->RegisterDefaultHandler( | 
|  | 837       base::Bind(&HandleCacheControl, "/cache/public", "max-age=3, public")); | 
|  | 838   server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | 
|  | 839                                             "/cache/s-maxage", | 
|  | 840                                             "public, s-maxage=60, max-age=0")); | 
|  | 841   server->RegisterDefaultHandler(base::Bind( | 
|  | 842       &HandleCacheControl, "/cache/must-revalidate", "must-revalidate")); | 
|  | 843   server->RegisterDefaultHandler(base::Bind(&HandleCacheControl, | 
|  | 844                                             "/cache/must-revalidate/max-age", | 
|  | 845                                             "max-age=60, must-revalidate")); | 
|  | 846   server->RegisterDefaultHandler( | 
|  | 847       base::Bind(&HandleCacheControl, "/cache/no-store", "no-store")); | 
|  | 848   server->RegisterDefaultHandler(base::Bind( | 
|  | 849       &HandleCacheControl, "/cache/no-store/max-age", "max-age=60, no-store")); | 
|  | 850   server->RegisterDefaultHandler( | 
|  | 851       base::Bind(&HandleCacheControl, "/cache/no-transform", "no-transform")); | 
|  | 852 | 
|  | 853   server->RegisterDefaultHandler( | 
|  | 854       base::Bind(&HandleEchoHeader, "/echoheader", "no-cache")); | 
|  | 855   server->RegisterDefaultHandler( | 
|  | 856       base::Bind(&HandleEchoHeader, "/echoheadercache", "max-age=60000")); | 
|  | 857   server->RegisterDefaultHandler(base::Bind(&HandleEcho)); | 
|  | 858   server->RegisterDefaultHandler(base::Bind(&HandleEchoTitle)); | 
|  | 859   server->RegisterDefaultHandler(base::Bind(&HandleEchoAll)); | 
|  | 860 | 
|  | 861   server->RegisterDefaultHandler(base::Bind(&HandleSetCookie)); | 
|  | 862   server->RegisterDefaultHandler(base::Bind(&HandleSetManyCookies)); | 
|  | 863   server->RegisterDefaultHandler(base::Bind(&HandleExpectAndSetCookie)); | 
|  | 864   server->RegisterDefaultHandler(base::Bind(&HandleSetHeader)); | 
|  | 865   server->RegisterDefaultHandler(base::Bind(&HandleNoContent)); | 
|  | 866   server->RegisterDefaultHandler(base::Bind(&HandleCloseSocket)); | 
|  | 867   server->RegisterDefaultHandler(base::Bind(&HandleAuthBasic)); | 
|  | 868   server->RegisterDefaultHandler(base::Bind(&HandleAuthDigest)); | 
|  | 869   server->RegisterDefaultHandler(base::Bind(&HandleServerRedirect)); | 
|  | 870   server->RegisterDefaultHandler(base::Bind(&HandleCrossSiteRedirect, server)); | 
|  | 871   server->RegisterDefaultHandler(base::Bind(&HandleClientRedirect)); | 
|  | 872   server->RegisterDefaultHandler(base::Bind(&HandleDefaultResponse)); | 
|  | 873   server->RegisterDefaultHandler(base::Bind(&HandleSlowServer)); | 
|  | 874 | 
|  | 875   // TODO(svaldez): HandleDownload | 
|  | 876   // TODO(svaldez): HandleDownloadFinish | 
|  | 877   // TODO(svaldez): HandleZipFile | 
|  | 878   // TODO(svaldez): HandleRangeReset | 
|  | 879   // TODO(svaldez): HandleSSLManySmallRecords | 
|  | 880   // TODO(svaldez): HandleChunkedServer | 
|  | 881   // TODO(svaldez): HandleGetSSLSessionCache | 
|  | 882   // TODO(svaldez): HandleGetChannelID | 
|  | 883   // TODO(svaldez): HandleGetClientCert | 
|  | 884   // TODO(svaldez): HandleClientCipherList | 
|  | 885   // TODO(svaldez): HandleEchoMultipartPost | 
|  | 886 } | 
|  | 887 | 
|  | 888 void GetFilePathWithReplacements(const std::string& original_file_path, | 
|  | 889                                  const base::StringPairs& text_to_replace, | 
|  | 890                                  std::string* replacement_path) { | 
|  | 891   std::string new_file_path = original_file_path; | 
|  | 892   bool first_query_parameter = true; | 
|  | 893   const base::StringPairs::const_iterator end = text_to_replace.end(); | 
|  | 894   for (base::StringPairs::const_iterator it = text_to_replace.begin(); | 
|  | 895        it != end; ++it) { | 
|  | 896     const std::string& old_text = it->first; | 
|  | 897     const std::string& new_text = it->second; | 
|  | 898     std::string base64_old; | 
|  | 899     std::string base64_new; | 
|  | 900     base::Base64Encode(old_text, &base64_old); | 
|  | 901     base::Base64Encode(new_text, &base64_new); | 
|  | 902     if (first_query_parameter) { | 
|  | 903       new_file_path += "?"; | 
|  | 904       first_query_parameter = false; | 
|  | 905     } else { | 
|  | 906       new_file_path += "&"; | 
|  | 907     } | 
|  | 908     new_file_path += "replace_text="; | 
|  | 909     new_file_path += base64_old; | 
|  | 910     new_file_path += ":"; | 
|  | 911     new_file_path += base64_new; | 
|  | 912   } | 
|  | 913 | 
|  | 914   *replacement_path = new_file_path; | 
|  | 915 } | 
|  | 916 | 
|  | 917 }  // namespace test_server | 
|  | 918 }  // namespace net | 
| OLD | NEW | 
|---|