Upstream version 10.39.225.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / net / sdch_browsertest.cc
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/run_loop.h"
16 #include "base/strings/string_tokenizer.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/stringprintf.h"
19 #include "chrome/browser/browser_process.h"
20 #include "chrome/browser/browsing_data/browsing_data_helper.h"
21 #include "chrome/browser/browsing_data/browsing_data_remover.h"
22 #include "chrome/browser/browsing_data/browsing_data_remover_test_util.h"
23 #include "chrome/browser/profiles/profile.h"
24 #include "chrome/browser/profiles/profile_manager.h"
25 #include "chrome/browser/ui/browser.h"
26 #include "chrome/browser/ui/browser_tabstrip.h"
27 #include "chrome/browser/ui/browser_window.h"
28 #include "chrome/browser/ui/tabs/tab_strip_model.h"
29 #include "chrome/common/chrome_paths.h"
30 #include "chrome/test/base/in_process_browser_test.h"
31 #include "content/public/browser/browser_thread.h"
32 #include "content/public/common/content_switches.h"
33 #include "content/public/test/browser_test_utils.h"
34 #include "content/public/test/test_utils.h"
35 #include "crypto/sha2.h"
36 #include "net/base/sdch_manager.h"
37 #include "net/http/http_response_headers.h"
38 #include "net/test/embedded_test_server/embedded_test_server.h"
39 #include "net/test/embedded_test_server/http_request.h"
40 #include "net/test/embedded_test_server/http_response.h"
41 #include "net/url_request/url_fetcher.h"
42 #include "net/url_request/url_fetcher_delegate.h"
43 #include "net/url_request/url_request_context.h"
44 #include "net/url_request/url_request_context_getter.h"
45 #include "sdch/open-vcdiff/src/google/vcencoder.h"
46 #include "testing/gtest/include/gtest/gtest.h"
47
48 #if defined(OS_CHROMEOS)
49 #include "chromeos/chromeos_switches.h"
50 #endif
51
52 namespace {
53
54 typedef std::vector<net::test_server::HttpRequest> RequestVector;
55 typedef std::map<std::string, std::string> HttpRequestHeaderMap;
56
57 // Credit Alfred, Lord Tennyson
58 static const char kSampleData[] = "<html><body><pre>"
59     "There lies the port; the vessel puffs her sail:\n"
60     "There gloom the dark, broad seas. My mariners,\n"
61     "Souls that have toil'd, and wrought, and thought with me—\n"
62     "That ever with a frolic welcome took\n"
63     "The thunder and the sunshine, and opposed\n"
64     "Free hearts, free foreheads—you and I are old;\n"
65     "Old age hath yet his honour and his toil;\n"
66     "Death closes all: but something ere the end,\n"
67     "Some work of noble note, may yet be done,\n"
68     "Not unbecoming men that strove with Gods.\n"
69     "The lights begin to twinkle from the rocks:\n"
70     "The long day wanes: the slow moon climbs: the deep\n"
71     "Moans round with many voices. Come, my friends,\n"
72     "'T is not too late to seek a newer world.\n"
73     "Push off, and sitting well in order smite\n"
74     "The sounding furrows; for my purpose holds\n"
75     "To sail beyond the sunset, and the baths\n"
76     "Of all the western stars, until I die.\n"
77     "It may be that the gulfs will wash us down:\n"
78     "It may be we shall touch the Happy Isles,\n"
79     "And see the great Achilles, whom we knew.\n"
80     "Tho' much is taken, much abides; and tho'\n"
81     "We are not now that strength which in old days\n"
82     "Moved earth and heaven, that which we are, we are;\n"
83     "One equal temper of heroic hearts,\n"
84     "Made weak by time and fate, but strong in will\n"
85     "To strive, to seek, to find, and not to yield.\n"
86     "</pre></body></html>";
87
88 // Random selection of lines from above, to allow some encoding, but
89 // not a trivial encoding.
90 static const char kDictionaryContents[] =
91     "The thunder and the sunshine, and opposed\n"
92     "To sail beyond the sunset, and the baths\n"
93     "Of all the western stars, until I die.\n"
94     "Made weak by time and fate, but strong in will\n"
95     "Moans round with many voices. Come, my friends,\n"
96     "The lights begin to twinkle from the rocks:";
97
98 static const char kDictionaryURLPath[] = "/dict";
99 static const char kDataURLPath[] = "/data";
100
101 // Scans in a case-insensitive way for |header| in |map|,
102 // returning true if found and setting |*value| to the value
103 // of that header.  Does not handle multiple instances of the same
104 // header.
105 bool GetRequestHeader(const HttpRequestHeaderMap& map,
106                       const char* header,
107                       std::string* value) {
108   for (HttpRequestHeaderMap::const_iterator it = map.begin();
109        it != map.end(); ++it) {
110     if (!base::strcasecmp(it->first.c_str(), header)) {
111       *value = it->second;
112       return true;
113     }
114   }
115   return false;
116 }
117
118 // Do a URL-safe base64 encoding.  See the SDCH spec "Dictionary Identifier"
119 // section, and RFC 3548 section 4.
120 void SafeBase64Encode(const std::string& input_value, std::string* output) {
121   DCHECK(output);
122   base::Base64Encode(input_value, output);
123   std::replace(output->begin(), output->end(), '+', '-');
124   std::replace(output->begin(), output->end(), '/', '_');
125 }
126
127 // Class that bundles responses for an EmbeddedTestServer().
128 // Dictionary is at <domain>/dict, data at <domain>/data.
129 // The data is sent SDCH encoded if that's allowed by protoocol.
130 class SdchResponseHandler {
131  public:
132   // Do initial preparation so that SDCH requests can be handled.
133   explicit SdchResponseHandler(std::string domain)
134       : cache_sdch_response_(false),
135         weak_ptr_factory_(this) {
136     // Dictionary
137     sdch_dictionary_contents_ = "Domain: ";
138     sdch_dictionary_contents_ += domain;
139     sdch_dictionary_contents_ += "\n\n";
140     sdch_dictionary_contents_ += kDictionaryContents;
141
142     // Dictionary hash for client and server.
143     char binary_hash[32];
144     crypto::SHA256HashString(sdch_dictionary_contents_, binary_hash,
145                              sizeof(binary_hash));
146     SafeBase64Encode(std::string(&binary_hash[0], 6), &dictionary_client_hash_);
147     SafeBase64Encode(std::string(&binary_hash[6], 6), &dictionary_server_hash_);
148
149     // Encoded response.
150     open_vcdiff::HashedDictionary vcdiff_dictionary(
151         kDictionaryContents, strlen(kDictionaryContents));
152     bool result = vcdiff_dictionary.Init();
153     DCHECK(result);
154     open_vcdiff::VCDiffStreamingEncoder encoder(&vcdiff_dictionary, 0, false);
155     encoded_data_ = dictionary_server_hash_;
156     encoded_data_ += '\0';
157     result = encoder.StartEncoding(&encoded_data_);
158     DCHECK(result);
159     result = encoder.EncodeChunk(
160         kSampleData, strlen(kSampleData), &encoded_data_);
161     DCHECK(result);
162     result = encoder.FinishEncoding(&encoded_data_);
163     DCHECK(result);
164   }
165
166   static bool ClientIsAdvertisingSdchEncoding(const HttpRequestHeaderMap& map) {
167     std::string value;
168     if (!GetRequestHeader(map, "accept-encoding", &value))
169       return false;
170     base::StringTokenizer tokenizer(value, " ,");
171     while (tokenizer.GetNext()) {
172       if (base::strcasecmp(tokenizer.token().c_str(), "sdch"))
173         return true;
174     }
175     return false;
176   }
177
178   bool ShouldRespondWithSdchEncoding(const HttpRequestHeaderMap& map) {
179     std::string value;
180     if (!GetRequestHeader(map, "avail-dictionary", &value))
181       return false;
182     return value == dictionary_client_hash_;
183   }
184
185   scoped_ptr<net::test_server::HttpResponse> HandleRequest(
186       const net::test_server::HttpRequest& request) {
187     request_vector_.push_back(request);
188
189     scoped_ptr<net::test_server::BasicHttpResponse> response(
190         new net::test_server::BasicHttpResponse);
191     if (request.relative_url == kDataURLPath) {
192       if (ShouldRespondWithSdchEncoding(request.headers)) {
193         // Note that chrome doesn't advertise accepting SDCH encoding
194         // for POSTs (because the meta-refresh hack would break a POST),
195         // but that's not for the server to enforce.
196         DCHECK_NE(encoded_data_, "");
197         response->set_content_type("text/html");
198         response->set_content(encoded_data_);
199         response->AddCustomHeader("Content-Encoding", "sdch");
200         // We allow tests to set caching on the sdch response,
201         // so that we can force an encoded response with no
202         // dictionary.
203         if (cache_sdch_response_)
204           response->AddCustomHeader("Cache-Control", "max-age=3600");
205         else
206           response->AddCustomHeader("Cache-Control", "no-store");
207       } else {
208         response->set_content_type("text/plain");
209         response->set_content(kSampleData);
210         if (ClientIsAdvertisingSdchEncoding(request.headers))
211           response->AddCustomHeader("Get-Dictionary", kDictionaryURLPath);
212         // We never cache the plain data response, to make it
213         // easy to refresh after we get the dictionary.
214         response->AddCustomHeader("Cache-Control", "no-store");
215       }
216     } else {
217       DCHECK_EQ(request.relative_url, kDictionaryURLPath);
218       DCHECK_NE(sdch_dictionary_contents_, "");
219       response->set_content_type("application/x-sdch-dictionary");
220       response->set_content(sdch_dictionary_contents_);
221     }
222     std::vector<base::Closure> callbacks;
223     callbacks.swap(callback_vector_);
224     for (std::vector<base::Closure>::iterator it = callbacks.begin();
225          it != callbacks.end(); ++it) {
226       it->Run();
227     }
228     return response.PassAs<net::test_server::HttpResponse>();
229   }
230
231   void WaitAndGetRequestVector(int num_requests,
232                                base::Closure callback,
233                                RequestVector* v) {
234     DCHECK_LT(0, num_requests);
235     if (static_cast<size_t>(num_requests) > request_vector_.size()) {
236       callback_vector_.push_back(
237           base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
238                      weak_ptr_factory_.GetWeakPtr(), num_requests,
239                      callback, v));
240       return;
241     }
242     *v = request_vector_;
243     content::BrowserThread::PostTask(
244         content::BrowserThread::UI, FROM_HERE, callback);
245   }
246
247   void set_cache_sdch_response(bool cache_sdch_response) {
248     cache_sdch_response_ = cache_sdch_response;
249   }
250
251  private:
252   bool cache_sdch_response_;
253   std::string encoded_data_;
254   std::string sdch_dictionary_contents_;
255   std::string dictionary_client_hash_;
256   std::string dictionary_server_hash_;
257   RequestVector request_vector_;
258   std::vector<base::Closure> callback_vector_;
259   base::WeakPtrFactory<SdchResponseHandler> weak_ptr_factory_;
260 };
261
262 class SdchBrowserTest : public InProcessBrowserTest, net::URLFetcherDelegate {
263  public:
264   static const char kTestHost[];
265
266   SdchBrowserTest()
267       : response_handler_(kTestHost),
268         url_request_context_getter_(NULL),
269         url_fetch_complete_(false),
270         waiting_(false) {}
271
272   // Helper functions for fetching data.
273
274   void FetchUrlDetailed(GURL url, net::URLRequestContextGetter* getter) {
275     url_fetch_complete_ = false;
276     fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this));
277     fetcher_->SetRequestContext(getter);
278     fetcher_->Start();
279     if (!url_fetch_complete_) {
280       waiting_ = true;
281       content::RunMessageLoop();
282       waiting_ = false;
283     }
284     CHECK(url_fetch_complete_);
285   }
286
287   void FetchUrl(GURL url) {
288     FetchUrlDetailed(url, url_request_context_getter_.get());
289   }
290
291   const net::URLRequestStatus& FetcherStatus() const {
292     return fetcher_->GetStatus();
293   }
294
295   int FetcherResponseCode() const {
296     return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
297             fetcher_->GetResponseCode() : 0);
298   }
299
300   const net::HttpResponseHeaders* FetcherResponseHeaders() const {
301     return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
302             fetcher_->GetResponseHeaders() : NULL);
303   }
304
305   std::string FetcherResponseContents() const {
306     std::string contents;
307     if (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS)
308       CHECK(fetcher_->GetResponseAsString(&contents));
309     return contents;
310   }
311
312   // Get the data from the server.  Return value is success/failure of the
313   // data operation, |*sdch_encoding_used| indicates whether or not the
314   // data was retrieved with sdch encoding.
315   // This is done through FetchUrl(), so the various helper functions
316   // will have valid status if it returns successfully.
317   bool GetDataDetailed(net::URLRequestContextGetter* getter,
318                        bool* sdch_encoding_used) {
319     FetchUrlDetailed(
320         GURL(base::StringPrintf(
321             "http://%s:%d%s", kTestHost, test_server_port(), kDataURLPath)),
322         getter);
323     EXPECT_EQ(net::URLRequestStatus::SUCCESS, FetcherStatus().status())
324         << "Error code is " << FetcherStatus().error();
325     EXPECT_EQ(200, FetcherResponseCode());
326     EXPECT_EQ(kSampleData, FetcherResponseContents());
327
328     if (net::URLRequestStatus::SUCCESS != FetcherStatus().status() ||
329         200 != FetcherResponseCode()) {
330       *sdch_encoding_used = false;
331       return false;
332     }
333
334     *sdch_encoding_used =
335         FetcherResponseHeaders()->HasHeaderValue("Content-Encoding", "sdch");
336
337     if (FetcherResponseContents() != kSampleData)
338       return false;
339
340     return true;
341   }
342
343   bool GetData(bool* sdch_encoding_used) {
344     return GetDataDetailed(url_request_context_getter_.get(),
345                            sdch_encoding_used);
346   }
347
348   // Client information and control.
349
350   int GetNumberOfDictionaryFetches(Profile* profile) {
351     int fetches = -1;
352     base::RunLoop run_loop;
353     content::BrowserThread::PostTaskAndReply(
354         content::BrowserThread::IO, FROM_HERE,
355         base::Bind(&SdchBrowserTest::GetNumberOfDictionaryFetchesOnIOThread,
356                    base::Unretained(profile->GetRequestContext()),
357                    &fetches),
358         run_loop.QuitClosure());
359     run_loop.Run();
360     DCHECK_NE(-1, fetches);
361     return fetches;
362   }
363
364   void BrowsingDataRemoveAndWait(int remove_mask) {
365     BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
366         browser()->profile(), BrowsingDataRemover::LAST_HOUR);
367     BrowsingDataRemoverCompletionObserver completion_observer(remover);
368     remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
369     completion_observer.BlockUntilCompletion();
370   }
371
372   // Something of a cheat; nuke the dictionaries off the SdchManager without
373   // touching the cache (which browsing data remover would do).
374   void NukeSdchDictionaries() {
375     base::RunLoop run_loop;
376     content::BrowserThread::PostTaskAndReply(
377         content::BrowserThread::IO, FROM_HERE,
378         base::Bind(&SdchBrowserTest::NukeSdchDictionariesOnIOThread,
379                    url_request_context_getter_),
380         run_loop.QuitClosure());
381     run_loop.Run();
382   }
383
384   // Create a second browser based on a second profile to work within
385   // multi-profile.
386   bool SetupSecondBrowser() {
387     base::FilePath user_data_dir;
388     PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
389
390     if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
391       return false;
392
393     second_profile_ = g_browser_process->profile_manager()->GetProfile(
394         second_profile_data_dir_.path());
395     if (!second_profile_) return false;
396
397     second_browser_ = new Browser(Browser::CreateParams(
398         second_profile_, browser()->host_desktop_type()));
399     if (!second_browser_) return false;
400
401     chrome::AddSelectedTabWithURL(second_browser_,
402                                   GURL(url::kAboutBlankURL),
403                                   ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
404     content::WaitForLoadStop(
405         second_browser_->tab_strip_model()->GetActiveWebContents());
406     second_browser_->window()->Show();
407
408     return true;
409   }
410
411   Browser* second_browser() { return second_browser_; }
412
413   // Server information and control.
414
415   void WaitAndGetTestVector(int num_requests, RequestVector* result) {
416     base::RunLoop run_loop;
417     content::BrowserThread::PostTask(
418         content::BrowserThread::IO, FROM_HERE,
419         base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
420                    base::Unretained(&response_handler_),
421                    num_requests,
422                    run_loop.QuitClosure(),
423                    result));
424     run_loop.Run();
425   }
426
427   int test_server_port() { return test_server_.port(); }
428
429   void SetSdchCacheability(bool cache_sdch_response) {
430     base::RunLoop run_loop;
431     content::BrowserThread::PostTaskAndReply(
432         content::BrowserThread::IO, FROM_HERE,
433         base::Bind(&SdchResponseHandler::set_cache_sdch_response,
434                    base::Unretained(&response_handler_),
435                    cache_sdch_response),
436         run_loop.QuitClosure());
437     run_loop.Run();
438   }
439
440   // Helper function for common test pattern.
441   //
442   // This function gets the data, confirms that the initial sending of the
443   // data included a dictionary advertisement, that that advertisement
444   // resulted in queueing a dictionary fetch, forces that fetch to
445   // go through, and confirms that a follow-on data load uses SDCH
446   // encoding.  Returns true if the entire sequence of events occurred.
447   bool ForceSdchDictionaryLoad(Browser* browser) {
448     bool sdch_encoding_used = true;
449     bool data_gotten = GetDataDetailed(
450         browser->profile()->GetRequestContext(), &sdch_encoding_used);
451     EXPECT_TRUE(data_gotten);
452     if (!data_gotten) return false;
453     EXPECT_FALSE(sdch_encoding_used);
454
455     // Confirm that we were told to get the dictionary
456     const net::HttpResponseHeaders* headers = FetcherResponseHeaders();
457     std::string value;
458     bool have_dict_header =
459         headers->EnumerateHeader(NULL, "Get-Dictionary", &value);
460     EXPECT_TRUE(have_dict_header);
461     if (!have_dict_header) return false;
462
463     // If the above didn't result in a dictionary fetch being queued, the
464     // rest of the test will time out.  Avoid that.
465     int num_fetches = GetNumberOfDictionaryFetches(browser->profile());
466     EXPECT_EQ(1, num_fetches);
467     if (1 != num_fetches) return false;
468
469     // Wait until the dictionary fetch actually happens.
470     RequestVector request_vector;
471     WaitAndGetTestVector(2, &request_vector);
472     EXPECT_EQ(request_vector[1].relative_url, kDictionaryURLPath);
473     if (request_vector[1].relative_url != kDictionaryURLPath) return false;
474
475     // Do a round trip to the server ignoring the encoding, presuming
476     // that if we've gotten data to this thread, the dictionary's made
477     // it into the SdchManager.
478     data_gotten = GetDataDetailed(
479         browser->profile()->GetRequestContext(), &sdch_encoding_used);
480     EXPECT_TRUE(data_gotten);
481     if (!data_gotten) return false;
482
483     // Now data fetches should be SDCH encoded.
484     sdch_encoding_used = false;
485     data_gotten = GetDataDetailed(
486         browser->profile()->GetRequestContext(), &sdch_encoding_used);
487     EXPECT_TRUE(data_gotten);
488     EXPECT_TRUE(sdch_encoding_used);
489
490     if (!data_gotten || !sdch_encoding_used) return false;
491
492     // Confirm the request vector looks at this point as expected.
493     WaitAndGetTestVector(4, &request_vector);
494     EXPECT_EQ(4u, request_vector.size());
495     EXPECT_EQ(request_vector[2].relative_url, kDataURLPath);
496     EXPECT_EQ(request_vector[3].relative_url, kDataURLPath);
497     return (4u == request_vector.size() &&
498             request_vector[2].relative_url == kDataURLPath &&
499             request_vector[3].relative_url == kDataURLPath);
500   }
501
502  private:
503   static void NukeSdchDictionariesOnIOThread(
504       net::URLRequestContextGetter* context_getter) {
505     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
506     net::SdchManager* sdch_manager =
507         context_getter->GetURLRequestContext()->sdch_manager();
508     DCHECK(sdch_manager);
509     sdch_manager->ClearData();
510   }
511
512   static void GetNumberOfDictionaryFetchesOnIOThread(
513       net::URLRequestContextGetter* url_request_context_getter,
514       int* result) {
515     DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
516     net::SdchManager* sdch_manager =
517         url_request_context_getter->GetURLRequestContext()->sdch_manager();
518     DCHECK(sdch_manager);
519     *result = sdch_manager->GetFetchesCountForTesting();
520   }
521
522   // InProcessBrowserTest
523   virtual void SetUpCommandLine(base::CommandLine* command_line) OVERRIDE {
524     command_line->AppendSwitchASCII(
525         switches::kHostResolverRules,
526         "MAP " + std::string(kTestHost) + " 127.0.0.1");
527 #if defined(OS_CHROMEOS)
528     command_line->AppendSwitch(
529         chromeos::switches::kIgnoreUserProfileMappingForTests);
530 #endif
531   }
532
533   virtual void SetUpOnMainThread() OVERRIDE {
534     test_server_.RegisterRequestHandler(
535         base::Bind(&SdchResponseHandler::HandleRequest,
536                    base::Unretained(&response_handler_)));
537     CHECK(test_server_.InitializeAndWaitUntilReady());
538     url_request_context_getter_ = browser()->profile()->GetRequestContext();
539   }
540
541   virtual void TearDownOnMainThread() OVERRIDE {
542     CHECK(test_server_.ShutdownAndWaitUntilComplete());
543   }
544
545   // URLFetcherDelegate
546   virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE {
547     url_fetch_complete_ = true;
548     if (waiting_)
549       base::MessageLoopForUI::current()->Quit();
550   }
551
552   SdchResponseHandler response_handler_;
553   net::test_server::EmbeddedTestServer test_server_;
554   scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
555   scoped_ptr<net::URLFetcher> fetcher_;
556   bool url_fetch_complete_;
557   bool waiting_;
558   base::ScopedTempDir second_profile_data_dir_;
559   Profile* second_profile_;
560   Browser* second_browser_;
561 };
562
563 const char SdchBrowserTest::kTestHost[] = "our.test.host.com";
564
565 // Confirm that after getting a dictionary, calling the browsing
566 // data remover renders it unusable.  Also (in calling
567 // ForceSdchDictionaryLoad()) servers as a smoke test for SDCH.
568 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, BrowsingDataRemover) {
569   ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
570
571   // Confirm browsing data remover without removing the cache leaves
572   // SDCH alone.
573   BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_ALL &
574                             ~BrowsingDataRemover::REMOVE_CACHE);
575   bool sdch_encoding_used = false;
576   ASSERT_TRUE(GetData(&sdch_encoding_used));
577   EXPECT_TRUE(sdch_encoding_used);
578
579   // Confirm browsing data remover removing the cache clears SDCH state.
580   BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_CACHE);
581   sdch_encoding_used = false;
582   ASSERT_TRUE(GetData(&sdch_encoding_used));
583   EXPECT_FALSE(sdch_encoding_used);
584 }
585
586 // Confirm dictionaries not visible in other profiles.
587 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, Isolation) {
588   ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
589   ASSERT_TRUE(SetupSecondBrowser());
590
591   // Data fetches from incognito or separate profiles should not be SDCH
592   // encoded.
593   bool sdch_encoding_used = true;
594   Browser* incognito_browser = CreateIncognitoBrowser();
595   EXPECT_TRUE(GetDataDetailed(
596       incognito_browser->profile()->GetRequestContext(),
597       &sdch_encoding_used));
598   EXPECT_FALSE(sdch_encoding_used);
599
600   sdch_encoding_used = true;
601   EXPECT_TRUE(GetDataDetailed(
602       second_browser()->profile()->GetRequestContext(), &sdch_encoding_used));
603   EXPECT_FALSE(sdch_encoding_used);
604 }
605
606 // Confirm a dictionary loaded in incognito isn't visible in the main profile.
607 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, ReverseIsolation) {
608   Browser* incognito_browser = CreateIncognitoBrowser();
609   ASSERT_TRUE(ForceSdchDictionaryLoad(incognito_browser));
610
611   // Data fetches on main browser should not be SDCH encoded.
612   bool sdch_encoding_used = true;
613   ASSERT_TRUE(GetData(&sdch_encoding_used));
614   EXPECT_FALSE(sdch_encoding_used);
615 }
616
617 }  // namespace