Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(451)

Side by Side Diff: chrome/browser/net/sdch_browsertest.cc

Issue 380003002: Improve testing for SDCH. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright 2014 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 // End-to-end SDCH tests. Uses the embedded test server to return SDCH
6 // results
7
8 #include "base/base64.h"
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/command_line.h"
12 #include "base/files/scoped_temp_dir.h"
13 #include "base/memory/weak_ptr.h"
14 #include "base/path_service.h"
15 #include "base/strings/string_util.h"
16 #include "base/strings/stringprintf.h"
17 #include "chrome/browser/browser_process.h"
18 #include "chrome/browser/browsing_data/browsing_data_helper.h"
19 #include "chrome/browser/browsing_data/browsing_data_remover.h"
20 #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
21 #include "chrome/browser/profiles/profile.h"
22 #include "chrome/browser/profiles/profile_manager.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_tabstrip.h"
25 #include "chrome/browser/ui/browser_window.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/common/chrome_paths.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/common/content_switches.h"
31 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/test_utils.h"
33 #include "crypto/sha2.h"
34 #include "net/base/sdch_manager.h"
35 #include "net/http/http_response_headers.h"
36 #include "net/test/embedded_test_server/embedded_test_server.h"
37 #include "net/test/embedded_test_server/http_request.h"
38 #include "net/test/embedded_test_server/http_response.h"
39 #include "net/url_request/url_fetcher.h"
40 #include "net/url_request/url_fetcher_delegate.h"
41 #include "net/url_request/url_request_context.h"
42 #include "net/url_request/url_request_context_getter.h"
43 #include "sdch/open-vcdiff/src/google/vcencoder.h"
44 #include "testing/gtest/include/gtest/gtest.h"
45
46 namespace {
47
48 typedef std::vector<net::test_server::HttpRequest> RequestVector;
49 typedef std::map<std::string, std::string> HttpRequestHeaderMap;
50
51 // Scanns in a case-insensitive way for |header| in |map|,
mef 2014/07/10 16:31:42 nit: Scanns.
52 // returning true if found and setting |*value| to the value
53 // of that header. Does not handle multiple instances of the same
54 // header.
55 bool RequestContainsHeader(const HttpRequestHeaderMap& map,
56 const char* header,
57 std::string* value) {
58 for (HttpRequestHeaderMap::const_iterator it = map.begin();
59 it != map.end(); ++it) {
mef 2014/07/10 16:31:42 I'm surprised that we don't have case-insensitive
60
61 if (!base::strcasecmp(it->first.c_str(), header)) {
62 *value = it->second;
63 return true;
64 }
65 }
66 return false;
67 }
68
69 bool ResponseContainsHeaderValue(const net::HttpResponseHeaders& headers,
70 const char* header,
71 const char* value) {
72 std::string iterated_value;
73 void *iter = NULL;
74 while (headers.EnumerateHeader(&iter, header, &iterated_value)) {
75 if (!base::strcasecmp(iterated_value.c_str(), value))
76 return true;
77 }
78 return false;
79 }
80
81 // Class that bundles responses for an EmbeddedTestServer().
82 // Dictionary is at <domain>/dict, data at <domain>/data.
83 // The data is sent SDCH encoded if that's allowed by protoocol.
84 class SdchResponseHandler {
85 public:
86 static const char kData[];
87 static const char kDictionaryContents[];
88
89 // Do initial preparation so that SDCH requests can be handled.
90 explicit SdchResponseHandler(std::string domain)
91 : cache_sdch_response_(false),
92 weak_ptr_factory_(this) {
93 // Dictionary
94 sdch_dictionary_contents_ = "Domain: ";
95 sdch_dictionary_contents_ += domain;
96 sdch_dictionary_contents_ += "\n\n";
97 sdch_dictionary_contents_ += kDictionaryContents;
98
99 // Dictionary hash for client and server.
100 char binary_hash[32];
101 crypto::SHA256HashString(sdch_dictionary_contents_, binary_hash,
102 sizeof(binary_hash));
103 base::Base64Encode(std::string(&binary_hash[0], 6),
104 &dictionary_client_hash_);
105 for (size_t i = 0; i < dictionary_client_hash_.size(); ++i) {
106 if (dictionary_client_hash_[i] == '+')
107 dictionary_client_hash_[i] = '-';
108 if (dictionary_client_hash_[i] == '/')
109 dictionary_client_hash_[i] = '_';
110 }
111 base::Base64Encode(std::string(&binary_hash[6], 6),
112 &dictionary_server_hash_);
113 for (size_t i = 0; i < dictionary_server_hash_.size(); ++i) {
114 if (dictionary_client_hash_[i] == '+')
115 dictionary_client_hash_[i] = '-';
116 if (dictionary_client_hash_[i] == '/')
117 dictionary_client_hash_[i] = '_';
118 }
119
120 // Encoded response.
121 open_vcdiff::HashedDictionary vcdiff_dictionary(
122 kDictionaryContents, strlen(kDictionaryContents));
123 bool result = vcdiff_dictionary.Init();
124 DCHECK(result);
125 open_vcdiff::VCDiffStreamingEncoder encoder(&vcdiff_dictionary, 0, false);
126 encoded_data_ = dictionary_server_hash_;
127 encoded_data_ += '\0';
128 result = encoder.StartEncoding(&encoded_data_);
129 DCHECK(result);
130 result = encoder.EncodeChunk(kData, strlen(kData), &encoded_data_);
131 DCHECK(result);
132 result = encoder.FinishEncoding(&encoded_data_);
133 DCHECK(result);
134 }
135
136 static bool AdvertisesSdchEncoding(const HttpRequestHeaderMap& map) {
137 std::string value;
138 if (!RequestContainsHeader(map, "accept-encoding", &value))
139 return false;
140 std::string::iterator word_start = value.begin();
141 do {
142 std::string::iterator it(word_start);
143 while (it != value.end() && IsAsciiAlpha(*it))
144 ++it;
145 if (it != word_start) {
146 if (!base::strcasecmp(std::string(word_start,it).c_str(), "sdch"))
147 return true;
148 }
149 while (it != value.end() && !IsAsciiAlpha(*it))
150 ++it;
151 word_start = it;
152 } while (word_start != value.end());
153 return false;
154 }
155
156 bool RespondWithSdchEncoding(const HttpRequestHeaderMap& map) {
157 std::string value;
158 if (!RequestContainsHeader(map, "avail-dictionary", &value))
159 return false;
160 return value == dictionary_client_hash_;
161 }
162
163 std::string DictionaryClientHash() const {
164 char binary_hash[32];
165 crypto::SHA256HashString(kDictionaryContents,
166 binary_hash, sizeof(binary_hash));
167 std::string client_hash;
168 // TODO(rdsmith): This doesn't appear to be from the spec; figure out
169 // where it comes from.
170 base::Base64Encode(std::string(&binary_hash[0], 6), &client_hash);
171 for (size_t i = 0; i < client_hash.size(); ++i) {
172 if (client_hash[i] == '+')
173 client_hash[i] = '-';
174 else if (client_hash[i] == '/')
175 client_hash[i] = '_';
176 }
177 return client_hash;
178 }
179
180 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
181 const net::test_server::HttpRequest& request) {
182 // We explicitly allow either GET or POST methods.
183 request_vector_.push_back(request);
184
185 scoped_ptr<net::test_server::BasicHttpResponse> response(
186 new net::test_server::BasicHttpResponse);
187 if (request.relative_url == "/data") {
188 if (RespondWithSdchEncoding(request.headers)) {
189 DCHECK_NE(encoded_data_, "");
190 response->set_content_type("text/html");
191 response->set_content(encoded_data_);
192 response->AddCustomHeader("Content-Encoding", "sdch");
193 // We allow tests to set caching on the sdch response,
194 // so that we can force an encoded response with no
195 // dictionary.
196 if (cache_sdch_response_)
197 response->AddCustomHeader("Cache-Control", "max-age=3600");
198 else
199 response->AddCustomHeader("Cache-Control", "no-store");
200 } else {
201 response->set_content_type("text/plain");
202 response->set_content(kData);
203 if (AdvertisesSdchEncoding(request.headers))
204 response->AddCustomHeader("Get-Dictionary", "/dict");
205 // We never cache the plain data response, to make it
206 // easy to refresh after we get the dictionary.
207 response->AddCustomHeader("Cache-Control", "no-store");
208 }
209 } else {
210 DCHECK_EQ(request.relative_url, "/dict");
211 DCHECK_NE(sdch_dictionary_contents_, "");
212 response->set_content_type("application/x-sdch-dictionary");
213 response->set_content(sdch_dictionary_contents_);
214 }
215 std::vector<base::Closure> callbacks;
216 callbacks.swap(callback_vector_);
217 for (std::vector<base::Closure>::iterator it = callbacks.begin();
218 it != callbacks.end(); ++it) {
219 it->Run();
220 }
221 return response.PassAs<net::test_server::HttpResponse>();
222 }
223
224 void WaitAndGetRequestVector(int num_requests,
225 base::Closure callback,
226 RequestVector* v) {
227 DCHECK_LT(0, num_requests);
228 if (static_cast<size_t>(num_requests) > request_vector_.size()) {
229 callback_vector_.push_back(
230 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
231 weak_ptr_factory_.GetWeakPtr(), num_requests,
232 callback, v));
233 return;
234 }
235 *v = request_vector_;
236 content::BrowserThread::PostTask(
237 content::BrowserThread::UI, FROM_HERE, callback);
238 }
239
240 void set_cache_sdch_response(bool cache_sdch_response) {
241 cache_sdch_response_ = cache_sdch_response;
242 }
243
244 private:
245 bool cache_sdch_response_;
246 std::string encoded_data_;
247 std::string sdch_dictionary_contents_;
248 std::string dictionary_client_hash_;
249 std::string dictionary_server_hash_;
250 RequestVector request_vector_;
251 std::vector<base::Closure> callback_vector_;
252 base::WeakPtrFactory<SdchResponseHandler> weak_ptr_factory_;
253 };
254
255 // Credit Alfred, Lord Tennyson
256 const char SdchResponseHandler::kData[] = "<html><body><pre>"
257 "There lies the port; the vessel puffs her sail:\n"
258 "There gloom the dark, broad seas. My mariners,\n"
259 "Souls that have toil'd, and wrought, and thought with me—\n"
260 "That ever with a frolic welcome took\n"
261 "The thunder and the sunshine, and opposed\n"
262 "Free hearts, free foreheads—you and I are old;\n"
263 "Old age hath yet his honour and his toil;\n"
264 "Death closes all: but something ere the end,\n"
265 "Some work of noble note, may yet be done,\n"
266 "Not unbecoming men that strove with Gods.\n"
267 "The lights begin to twinkle from the rocks:\n"
268 "The long day wanes: the slow moon climbs: the deep\n"
269 "Moans round with many voices. Come, my friends,\n"
270 "'T is not too late to seek a newer world.\n"
271 "Push off, and sitting well in order smite\n"
272 "The sounding furrows; for my purpose holds\n"
273 "To sail beyond the sunset, and the baths\n"
274 "Of all the western stars, until I die.\n"
275 "It may be that the gulfs will wash us down:\n"
276 "It may be we shall touch the Happy Isles,\n"
277 "And see the great Achilles, whom we knew.\n"
278 "Tho' much is taken, much abides; and tho'\n"
279 "We are not now that strength which in old days\n"
280 "Moved earth and heaven, that which we are, we are;\n"
281 "One equal temper of heroic hearts,\n"
282 "Made weak by time and fate, but strong in will\n"
283 "To strive, to seek, to find, and not to yield.\n"
284 "</pre></body></html>";
285
286 // Random selection of lines from above, to allow some encoding, but
287 // not a trivial encoding.
288 const char SdchResponseHandler::kDictionaryContents[] =
289 "The thunder and the sunshine, and opposed\n"
290 "To sail beyond the sunset, and the baths\n"
291 "Of all the western stars, until I die.\n"
292 "Made weak by time and fate, but strong in will\n"
293 "Moans round with many voices. Come, my friends,\n"
294 "The lights begin to twinkle from the rocks:";
295
296 class SdchBrowserTest : public InProcessBrowserTest, net::URLFetcherDelegate {
297 public:
298 static const char kTestHost[];
299
300 SdchBrowserTest()
301 : response_handler_(kTestHost),
302 url_request_context_getter_(NULL),
303 fetcher_response_code_(0),
304 url_fetch_complete_(false),
305 waiting_(false) {}
306
307 // ** Helper functions for fetching data.
308
309 void FetchUrlDetailed(GURL url, net::URLRequestContextGetter* getter,
310 bool use_post) {
311 url_fetch_complete_ = false;
312 fetcher_status_ = net::URLRequestStatus();
313 fetcher_response_code_ = 0;
314 fetcher_response_headers_ = NULL;
315 fetcher_response_contents_ = "";
316 fetcher_.reset(net::URLFetcher::Create(
317 url, use_post ? net::URLFetcher::POST : net::URLFetcher::GET, this));
318 if (use_post)
319 fetcher_->SetUploadData("text/plain", "Simple content");
320 fetcher_->SetRequestContext(getter);
321 fetcher_->Start();
322 if (!url_fetch_complete_) {
323 waiting_ = true;
324 content::RunMessageLoop();
325 waiting_ = false;
326 }
327 CHECK(url_fetch_complete_);
328 }
329 void FetchUrl(GURL url) {
330 FetchUrlDetailed(url, url_request_context_getter_, false);
331 }
332 int fetcher_response_code() { return fetcher_response_code_; }
333 const net::URLRequestStatus& fetcher_status() { return fetcher_status_; }
334 const net::HttpResponseHeaders* fetcher_response_headers() {
335 return fetcher_response_headers_;
336 }
337 std::string fetcher_response_contents() { return fetcher_response_contents_; }
338
339 GURL data_url() {
340 return GURL(base::StringPrintf(
341 "http://%s:%d/data", kTestHost, test_server_port()));
342 }
343
344 // Get the data from the server. Return value is success/failure of the
345 // data operation, |*sdch_encoding_used| indicates whether or not the
346 // data was retrieved with sdch encoding.
347 // This is done through FetchUrl(), so the various helper functions
348 // will have valid status if it returns successfully.
349 bool GetDataDetailed(net::URLRequestContextGetter* getter,
350 bool use_post,
351 bool* sdch_encoding_used) {
352 FetchUrlDetailed(data_url(), getter, use_post);
353 EXPECT_EQ(net::URLRequestStatus::SUCCESS, fetcher_status().status())
354 << "Error code is " << fetcher_status().error();
355 EXPECT_EQ(200, fetcher_response_code());
356 EXPECT_EQ(SdchResponseHandler::kData, fetcher_response_contents());
357
358 if (net::URLRequestStatus::SUCCESS != fetcher_status().status()
359 || 200 != fetcher_response_code()) {
360 *sdch_encoding_used = false;
361 return false;
362 }
363
364 *sdch_encoding_used = ResponseContainsHeaderValue(
365 *fetcher_response_headers(),
366 "Content-Encoding", "sdch");
367
368 if (SdchResponseHandler::kData != fetcher_response_contents())
369 return false;
370
371 return true;
372 }
373 bool GetData(bool* sdch_encoding_used) {
374 return GetDataDetailed(
375 url_request_context_getter_, false, sdch_encoding_used);
376 }
377
378 // ** Client information and control.
379
380 int GetNumberOfDictionaryFetches() {
381 int fetches = -1;
382 content::BrowserThread::PostTaskAndReply(
383 content::BrowserThread::IO, FROM_HERE,
384 base::Bind(&SdchBrowserTest::GetNumberOfDictionaryFetchesOnIOThread,
385 url_request_context_getter_,
386 &fetches),
387 base::MessageLoopForUI::current()->QuitClosure());
388 content::RunMessageLoop();
389 DCHECK_NE(-1, fetches);
390 return fetches;
391 }
392
393 void BrowsingDataRemoveAndWait(int remove_mask) {
394 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
395 browser()->profile(), BrowsingDataRemover::LAST_HOUR);
396 BrowsingDataRemoverCompletionObserver completion_observer(remover);
397 remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
398 completion_observer.BlockUntilCompletion();
399 }
400
401 // Something of a cheat; nuke the dictionaries off the SdchManager without
402 // touching the cache (which browsing data remover would do).
403 void NukeSdchDictionaries() {
404 content::BrowserThread::PostTaskAndReply(
405 content::BrowserThread::IO, FROM_HERE,
406 base::Bind(&SdchBrowserTest::NukeSdchDictionariesOnIOThread,
407 url_request_context_getter_),
408 base::MessageLoopForUI::current()->QuitClosure());
409 content::RunMessageLoop();
410 }
411
412 // Create a second profile to work within multi-profile.
413 Profile* CreateSecondProfile() {
414 base::FilePath user_data_dir;
415 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
416
417 if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
418 return NULL;
419
420 Profile* second_profile =
421 g_browser_process->profile_manager()->GetProfile(
422 second_profile_data_dir_.path());
423 if (!second_profile)
424 return NULL;
425
426 return second_profile;
427 }
428
429 Browser* CreateBrowserOnProfile(Profile* profile) {
430 Browser* new_browser =
431 new Browser(Browser::CreateParams(
432 profile, browser()->host_desktop_type()));
433 chrome::AddSelectedTabWithURL(new_browser,
434 GURL(url::kAboutBlankURL),
435 content::PAGE_TRANSITION_AUTO_TOPLEVEL);
436 content::WaitForLoadStop(
437 new_browser->tab_strip_model()->GetActiveWebContents());
438 new_browser->window()->Show();
439 return new_browser;
440 }
441
442 // ** Server information and control.
443
444 void WaitAndGetTestVector(int num_requests, RequestVector* result) {
445 content::BrowserThread::PostTask(
446 content::BrowserThread::IO, FROM_HERE,
447 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
448 base::Unretained(&response_handler_),
449 num_requests,
450 base::MessageLoopForUI::current()->QuitClosure(),
451 result));
452 content::RunMessageLoop();
453 }
454
455 int test_server_port() { return test_server_.port(); }
456
457 void SetSdchCacheability(bool cache_sdch_response) {
458 content::BrowserThread::PostTaskAndReply(
459 content::BrowserThread::IO, FROM_HERE,
460 base::Bind(&SdchResponseHandler::set_cache_sdch_response,
461 base::Unretained(&response_handler_),
462 cache_sdch_response),
463 base::MessageLoopForUI::current()->QuitClosure());
464 content::RunMessageLoop();
465 }
466
467 private:
468 // InProcessBrowserTest
469 virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
470 command_line->AppendSwitchASCII(
471 switches::kHostResolverRules,
472 "MAP " + std::string(kTestHost) + " 127.0.0.1");
473 }
474
475 virtual void SetUpOnMainThread() OVERRIDE {
476 test_server_.RegisterRequestHandler(
477 base::Bind(&SdchResponseHandler::HandleRequest,
478 base::Unretained(&response_handler_)));
479 CHECK(test_server_.InitializeAndWaitUntilReady());
480 url_request_context_getter_ = browser()->profile()->GetRequestContext();
481 }
482
483 virtual void TearDownOnMainThread() OVERRIDE {
484 CHECK(test_server_.ShutdownAndWaitUntilComplete());
485 }
486
487 static void NukeSdchDictionariesOnIOThread(
488 net::URLRequestContextGetter* context_getter) {
489 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
490 net::SdchManager* sdch_manager =
491 context_getter->GetURLRequestContext()->sdch_manager();
492 DCHECK(sdch_manager);
493 sdch_manager->ClearData();
494 }
495
496 static void GetNumberOfDictionaryFetchesOnIOThread(
497 net::URLRequestContextGetter* url_request_context_getter,
498 int* result) {
499 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
500 net::SdchManager* sdch_manager =
501 url_request_context_getter->GetURLRequestContext()->sdch_manager();
502 DCHECK(sdch_manager);
503 *result = sdch_manager->GetFetchesRequestedForTesting();
504 }
505
506 // URLFetcherDelegate
507 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
508 fetcher_status_ = source->GetStatus();
509 if (fetcher_status_.status() == net::URLRequestStatus::SUCCESS) {
510 fetcher_response_code_ = source->GetResponseCode();
511 fetcher_response_headers_ = source->GetResponseHeaders();
512 CHECK(source->GetResponseAsString(&fetcher_response_contents_));
513 }
514 url_fetch_complete_ = true;
515 if (waiting_)
516 base::MessageLoopForUI::current()->Quit();
517 }
518
519 SdchResponseHandler response_handler_;
520 net::test_server::EmbeddedTestServer test_server_;
521 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
522 scoped_ptr<net::URLFetcher> fetcher_;
523 net::URLRequestStatus fetcher_status_;
524 int fetcher_response_code_;
525 net::HttpResponseHeaders* fetcher_response_headers_;
526 std::string fetcher_response_contents_;
527 bool url_fetch_complete_;
528 bool waiting_;
529 base::ScopedTempDir second_profile_data_dir_;
530 };
531
532 const char SdchBrowserTest::kTestHost[] = "our.test.host.com";;
533
534 // Confirm the simplest SDCH pattern (get with no dictionary
535 // advertises dictionary, browser then gets dictionary, next
536 // get of original data uses dictionary) works.
537 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, Simple) {
538 bool sdch_encoding_used = true;
539 ASSERT_TRUE(GetData(&sdch_encoding_used));
540 EXPECT_FALSE(sdch_encoding_used);
541
542 // Confirm that we were told to get the dictionary
543 const net::HttpResponseHeaders* headers = fetcher_response_headers();
544 std::string value;
545 ASSERT_TRUE(headers->EnumerateHeader(NULL, "Get-Dictionary", &value));
546
547 // If the above didn't result in a dictionary fetch being queued, the
548 // rest of the test will time out. Avoid that.
549 ASSERT_EQ(1, GetNumberOfDictionaryFetches());
550
551 // Wait until the dictionary fetch actually happens.
552 RequestVector request_vector;
553 WaitAndGetTestVector(2, &request_vector);
554 ASSERT_EQ(request_vector[1].relative_url, "/dict");
555
556 // Do a round trip to the server ignoring the encoding, presuming
557 // that if we've gotten data to this thread, the dictionary's made
558 // it into the SdchManager.
559 ASSERT_TRUE(GetData(&sdch_encoding_used));
560
561 // Now data fetches should be SDCH encoded.
562 sdch_encoding_used = false;
563 ASSERT_TRUE(GetData(&sdch_encoding_used));
564 EXPECT_TRUE(sdch_encoding_used);
565 }
566
567 // Confirm that after getting a dictionary, calling the browsing
568 // data remover renders it unusable.
569 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, BrowsingDataRemover) {
570 bool sdch_encoding_used = true;
571 ASSERT_TRUE(GetData(&sdch_encoding_used));
572 EXPECT_FALSE(sdch_encoding_used);
573
574 // If the above didn't result in a dictionary fetch being queued, the
575 // rest of the test will time out. Avoid that.
576 ASSERT_EQ(1, GetNumberOfDictionaryFetches());
577
578 // Wait until the dictionary fetch actually happens.
579 RequestVector request_vector;
580 WaitAndGetTestVector(2, &request_vector);
581 ASSERT_EQ(request_vector[1].relative_url, "/dict");
582
583 // Do a round trip to the server ignoring the encoding, presuming
584 // that if we've gotten data to this thread, the dictionary's made
585 // it into the SdchManager.
586 ASSERT_TRUE(GetData(&sdch_encoding_used));
587
588 // Now data fetches should be SDCH encoded.
589 sdch_encoding_used = false;
590 ASSERT_TRUE(GetData(&sdch_encoding_used));
591 EXPECT_TRUE(sdch_encoding_used);
592
593 // Confirm browsing data remover without removing the cache leaves
594 // SDCH alone.
595 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_ALL &
596 ~BrowsingDataRemover::REMOVE_CACHE);
597 sdch_encoding_used = false;
598 ASSERT_TRUE(GetData(&sdch_encoding_used));
599 EXPECT_TRUE(sdch_encoding_used);
600
601 // Confirm browsing data remover removing the cache clears SDCH state.
602 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_CACHE);
603 sdch_encoding_used = false;
604 ASSERT_TRUE(GetData(&sdch_encoding_used));
605 EXPECT_FALSE(sdch_encoding_used);
606 }
607
608 // Confirm that receiving an SDCH response when we don't have the
609 // dictionary results in a meta-refresh.
610 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, MetaRefresh) {
611 bool sdch_encoding_used = true;
612 ASSERT_TRUE(GetData(&sdch_encoding_used));
613 EXPECT_FALSE(sdch_encoding_used);
614
615 // If the above didn't result in a dictionary fetch being queued, the
616 // rest of the test will time out. Avoid that.
617 ASSERT_EQ(1, GetNumberOfDictionaryFetches());
618
619 // Wait until the dictionary fetch actually happens.
620 RequestVector request_vector;
621 WaitAndGetTestVector(2, &request_vector);
622 ASSERT_EQ(request_vector[1].relative_url, "/dict");
623
624 // Do a round trip to the server ignoring the encoding, presuming
625 // that if we've gotten data to this thread, the dictionary's made
626 // it into the SdchManager.
627 ASSERT_TRUE(GetData(&sdch_encoding_used));
628
629 // We're now sure we have the dictionary. Get a copy of
630 // the encoded data into our cache.
631 SetSdchCacheability(true);
632 sdch_encoding_used = false;
633 ASSERT_TRUE(GetData(&sdch_encoding_used));
634 EXPECT_TRUE(sdch_encoding_used);
635 ASSERT_TRUE(ResponseContainsHeaderValue(*fetcher_response_headers(),
636 "Cache-Control",
637 "max-age=3600"));
638
639 // Confirm the request vector looks at this point as expected.
640 WaitAndGetTestVector(4, &request_vector);
641 ASSERT_EQ(4u, request_vector.size());
642 ASSERT_EQ(request_vector[2].relative_url, "/data");
643 ASSERT_EQ(request_vector[3].relative_url, "/data");
644
645 NukeSdchDictionaries();
646
647 // Try to fetch the data.
648 FetchUrl(data_url());
649 ASSERT_EQ(net::URLRequestStatus::SUCCESS, fetcher_status().status())
650 << "Error code is " << fetcher_status().error();
651 ASSERT_EQ(200, fetcher_response_code());
652 ASSERT_NE(SdchResponseHandler::kData, fetcher_response_contents());
653 // TODO(rdsmith): Interesting question as to whether the
654 // fake-out from the network stack in the case of a failed
655 // decode should claim to be "Content-Encoding: sdch" or not.
656 EXPECT_TRUE(ResponseContainsHeaderValue(*fetcher_response_headers(),
657 "Content-Encoding",
658 "sdch"))
659 << fetcher_response_contents();
660 std::string response_contents(fetcher_response_contents());
661 StringToLowerASCII(&response_contents);
662 EXPECT_NE(string::npos, response_contents.find("meta http-equiv=\"refresh\""))
663 << "Actual response is: " << response_contents;
664 }
665
666 // Confirm dictionaries not visible in other profiles.
667 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, Isolation) {
668 bool sdch_encoding_used = true;
669 ASSERT_TRUE(GetData(&sdch_encoding_used));
670 EXPECT_FALSE(sdch_encoding_used);
671
672 // Confirm that we were told to get the dictionary
673 const net::HttpResponseHeaders* headers = fetcher_response_headers();
674 std::string value;
675 ASSERT_TRUE(headers->EnumerateHeader(NULL, "Get-Dictionary", &value));
676
677 // If the above didn't result in a dictionary fetch being queued, the
678 // rest of the test will time out. Avoid that.
679 ASSERT_EQ(1, GetNumberOfDictionaryFetches());
680
681 // Wait until the dictionary fetch actually happens.
682 RequestVector request_vector;
683 WaitAndGetTestVector(2, &request_vector);
684 ASSERT_EQ(request_vector[1].relative_url, "/dict");
685
686 // Do a round trip to the server ignoring the encoding, presuming
687 // that if we've gotten data to this thread, the dictionary's made
688 // it into the SdchManager.
689 ASSERT_TRUE(GetData(&sdch_encoding_used));
690
691 // Now data fetches should be SDCH encoded.
692 sdch_encoding_used = false;
693 ASSERT_TRUE(GetData(&sdch_encoding_used));
694 EXPECT_TRUE(sdch_encoding_used);
695
696 // And data fetches from incognito or separate profiles should not be.
697 Browser* incognito_browser = CreateIncognitoBrowser();
698 sdch_encoding_used = true;
699 EXPECT_TRUE(GetDataDetailed(
700 incognito_browser->profile()->GetRequestContext(),
701 false,
702 &sdch_encoding_used));
703 EXPECT_FALSE(sdch_encoding_used);
704
705 Browser* new_browser = CreateBrowserOnProfile(CreateSecondProfile());
706 sdch_encoding_used = true;
707 EXPECT_TRUE(GetDataDetailed(
708 new_browser->profile()->GetRequestContext(),
709 false,
710 &sdch_encoding_used));
711 EXPECT_FALSE(sdch_encoding_used);
712 }
713
714 // Confirm we don't advertise dictionaries on posts.
715 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, NoPost) {
716 bool sdch_encoding_used = true;
717 ASSERT_TRUE(GetData(&sdch_encoding_used));
718 EXPECT_FALSE(sdch_encoding_used);
719
720 // Confirm that we were told to get the dictionary
721 const net::HttpResponseHeaders* headers = fetcher_response_headers();
722 std::string value;
723 ASSERT_TRUE(headers->EnumerateHeader(NULL, "Get-Dictionary", &value));
724
725 // If the above didn't result in a dictionary fetch being queued, the
726 // rest of the test will time out. Avoid that.
727 ASSERT_EQ(1, GetNumberOfDictionaryFetches());
728
729 // Wait until the dictionary fetch actually happens.
730 RequestVector request_vector;
731 WaitAndGetTestVector(2, &request_vector);
732 ASSERT_EQ(request_vector[1].relative_url, "/dict");
733
734 // Do a round trip to the server ignoring the encoding, presuming
735 // that if we've gotten data to this thread, the dictionary's made
736 // it into the SdchManager.
737 ASSERT_TRUE(GetData(&sdch_encoding_used));
738
739 // Now data fetches should be SDCH encoded.
740 sdch_encoding_used = false;
741 ASSERT_TRUE(GetData(&sdch_encoding_used));
742 EXPECT_TRUE(sdch_encoding_used);
743
744 // And data fetches using post should not be.
745 sdch_encoding_used = true;
746 EXPECT_TRUE(GetDataDetailed(
747 browser()->profile()->GetRequestContext(),
748 true,
749 &sdch_encoding_used));
750 EXPECT_FALSE(sdch_encoding_used);
751 }
752
753 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698