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.
5 // End-to-end SDCH tests. Uses the embedded test server to return SDCH
8 #include "base/base64.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/base/sdch_observer.h"
38 #include "net/http/http_response_headers.h"
39 #include "net/test/embedded_test_server/embedded_test_server.h"
40 #include "net/test/embedded_test_server/http_request.h"
41 #include "net/test/embedded_test_server/http_response.h"
42 #include "net/url_request/url_fetcher.h"
43 #include "net/url_request/url_fetcher_delegate.h"
44 #include "net/url_request/url_request_context.h"
45 #include "net/url_request/url_request_context_getter.h"
46 #include "sdch/open-vcdiff/src/google/vcencoder.h"
47 #include "testing/gtest/include/gtest/gtest.h"
49 #if defined(OS_CHROMEOS)
50 #include "chromeos/chromeos_switches.h"
55 typedef std::vector<net::test_server::HttpRequest> RequestVector;
56 typedef std::map<std::string, std::string> HttpRequestHeaderMap;
58 // Credit Alfred, Lord Tennyson
59 static const char kSampleData[] = "<html><body><pre>"
60 "There lies the port; the vessel puffs her sail:\n"
61 "There gloom the dark, broad seas. My mariners,\n"
62 "Souls that have toil'd, and wrought, and thought with me—\n"
63 "That ever with a frolic welcome took\n"
64 "The thunder and the sunshine, and opposed\n"
65 "Free hearts, free foreheads—you and I are old;\n"
66 "Old age hath yet his honour and his toil;\n"
67 "Death closes all: but something ere the end,\n"
68 "Some work of noble note, may yet be done,\n"
69 "Not unbecoming men that strove with Gods.\n"
70 "The lights begin to twinkle from the rocks:\n"
71 "The long day wanes: the slow moon climbs: the deep\n"
72 "Moans round with many voices. Come, my friends,\n"
73 "'T is not too late to seek a newer world.\n"
74 "Push off, and sitting well in order smite\n"
75 "The sounding furrows; for my purpose holds\n"
76 "To sail beyond the sunset, and the baths\n"
77 "Of all the western stars, until I die.\n"
78 "It may be that the gulfs will wash us down:\n"
79 "It may be we shall touch the Happy Isles,\n"
80 "And see the great Achilles, whom we knew.\n"
81 "Tho' much is taken, much abides; and tho'\n"
82 "We are not now that strength which in old days\n"
83 "Moved earth and heaven, that which we are, we are;\n"
84 "One equal temper of heroic hearts,\n"
85 "Made weak by time and fate, but strong in will\n"
86 "To strive, to seek, to find, and not to yield.\n"
87 "</pre></body></html>";
89 // Random selection of lines from above, to allow some encoding, but
90 // not a trivial encoding.
91 static const char kDictionaryContents[] =
92 "The thunder and the sunshine, and opposed\n"
93 "To sail beyond the sunset, and the baths\n"
94 "Of all the western stars, until I die.\n"
95 "Made weak by time and fate, but strong in will\n"
96 "Moans round with many voices. Come, my friends,\n"
97 "The lights begin to twinkle from the rocks:";
99 static const char kDictionaryURLPath[] = "/dict";
100 static const char kDataURLPath[] = "/data";
102 // Scans in a case-insensitive way for |header| in |map|,
103 // returning true if found and setting |*value| to the value
104 // of that header. Does not handle multiple instances of the same
106 bool GetRequestHeader(const HttpRequestHeaderMap& map,
108 std::string* value) {
109 for (HttpRequestHeaderMap::const_iterator it = map.begin();
110 it != map.end(); ++it) {
111 if (!base::strcasecmp(it->first.c_str(), header)) {
119 // Do a URL-safe base64 encoding. See the SDCH spec "Dictionary Identifier"
120 // section, and RFC 3548 section 4.
121 void SafeBase64Encode(const std::string& input_value, std::string* output) {
123 base::Base64Encode(input_value, output);
124 std::replace(output->begin(), output->end(), '+', '-');
125 std::replace(output->begin(), output->end(), '/', '_');
128 // Class that bundles responses for an EmbeddedTestServer().
129 // Dictionary is at <domain>/dict, data at <domain>/data.
130 // The data is sent SDCH encoded if that's allowed by protoocol.
131 class SdchResponseHandler {
133 // Do initial preparation so that SDCH requests can be handled.
134 explicit SdchResponseHandler(std::string domain)
135 : cache_sdch_response_(false),
136 weak_ptr_factory_(this) {
138 sdch_dictionary_contents_ = "Domain: ";
139 sdch_dictionary_contents_ += domain;
140 sdch_dictionary_contents_ += "\n\n";
141 sdch_dictionary_contents_ += kDictionaryContents;
143 // Dictionary hash for client and server.
144 char binary_hash[32];
145 crypto::SHA256HashString(sdch_dictionary_contents_, binary_hash,
146 sizeof(binary_hash));
147 SafeBase64Encode(std::string(&binary_hash[0], 6), &dictionary_client_hash_);
148 SafeBase64Encode(std::string(&binary_hash[6], 6), &dictionary_server_hash_);
151 open_vcdiff::HashedDictionary vcdiff_dictionary(
152 kDictionaryContents, strlen(kDictionaryContents));
153 bool result = vcdiff_dictionary.Init();
155 open_vcdiff::VCDiffStreamingEncoder encoder(&vcdiff_dictionary, 0, false);
156 encoded_data_ = dictionary_server_hash_;
157 encoded_data_ += '\0';
158 result = encoder.StartEncoding(&encoded_data_);
160 result = encoder.EncodeChunk(
161 kSampleData, strlen(kSampleData), &encoded_data_);
163 result = encoder.FinishEncoding(&encoded_data_);
167 static bool ClientIsAdvertisingSdchEncoding(const HttpRequestHeaderMap& map) {
169 if (!GetRequestHeader(map, "accept-encoding", &value))
171 base::StringTokenizer tokenizer(value, " ,");
172 while (tokenizer.GetNext()) {
173 if (base::strcasecmp(tokenizer.token().c_str(), "sdch"))
179 bool ShouldRespondWithSdchEncoding(const HttpRequestHeaderMap& map) {
181 if (!GetRequestHeader(map, "avail-dictionary", &value))
183 return value == dictionary_client_hash_;
186 scoped_ptr<net::test_server::HttpResponse> HandleRequest(
187 const net::test_server::HttpRequest& request) {
188 request_vector_.push_back(request);
190 scoped_ptr<net::test_server::BasicHttpResponse> response(
191 new net::test_server::BasicHttpResponse);
192 if (request.relative_url == kDataURLPath) {
193 if (ShouldRespondWithSdchEncoding(request.headers)) {
194 // Note that chrome doesn't advertise accepting SDCH encoding
195 // for POSTs (because the meta-refresh hack would break a POST),
196 // but that's not for the server to enforce.
197 DCHECK_NE(encoded_data_, "");
198 response->set_content_type("text/html");
199 response->set_content(encoded_data_);
200 response->AddCustomHeader("Content-Encoding", "sdch");
201 // We allow tests to set caching on the sdch response,
202 // so that we can force an encoded response with no
204 if (cache_sdch_response_)
205 response->AddCustomHeader("Cache-Control", "max-age=3600");
207 response->AddCustomHeader("Cache-Control", "no-store");
209 response->set_content_type("text/plain");
210 response->set_content(kSampleData);
211 if (ClientIsAdvertisingSdchEncoding(request.headers))
212 response->AddCustomHeader("Get-Dictionary", kDictionaryURLPath);
213 // We never cache the plain data response, to make it
214 // easy to refresh after we get the dictionary.
215 response->AddCustomHeader("Cache-Control", "no-store");
218 DCHECK_EQ(request.relative_url, kDictionaryURLPath);
219 DCHECK_NE(sdch_dictionary_contents_, "");
220 response->set_content_type("application/x-sdch-dictionary");
221 response->set_content(sdch_dictionary_contents_);
223 std::vector<base::Closure> callbacks;
224 callbacks.swap(callback_vector_);
225 for (std::vector<base::Closure>::iterator it = callbacks.begin();
226 it != callbacks.end(); ++it) {
229 return response.Pass();
232 void WaitAndGetRequestVector(int num_requests,
233 base::Closure callback,
235 DCHECK_LT(0, num_requests);
236 if (static_cast<size_t>(num_requests) > request_vector_.size()) {
237 callback_vector_.push_back(
238 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
239 weak_ptr_factory_.GetWeakPtr(), num_requests,
243 *v = request_vector_;
244 content::BrowserThread::PostTask(
245 content::BrowserThread::UI, FROM_HERE, callback);
248 void set_cache_sdch_response(bool cache_sdch_response) {
249 cache_sdch_response_ = cache_sdch_response;
253 bool cache_sdch_response_;
254 std::string encoded_data_;
255 std::string sdch_dictionary_contents_;
256 std::string dictionary_client_hash_;
257 std::string dictionary_server_hash_;
258 RequestVector request_vector_;
259 std::vector<base::Closure> callback_vector_;
260 base::WeakPtrFactory<SdchResponseHandler> weak_ptr_factory_;
263 class SdchBrowserTest : public InProcessBrowserTest,
264 public net::URLFetcherDelegate,
265 public net::SdchObserver {
267 static const char kTestHost[];
270 : response_handler_(kTestHost),
271 url_request_context_getter_(NULL),
272 url_fetch_complete_(false),
275 // Helper functions for fetching data.
277 void FetchUrlDetailed(GURL url, net::URLRequestContextGetter* getter) {
278 url_fetch_complete_ = false;
279 fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this));
280 fetcher_->SetRequestContext(getter);
282 if (!url_fetch_complete_) {
284 content::RunMessageLoop();
287 CHECK(url_fetch_complete_);
290 void FetchUrl(GURL url) {
291 FetchUrlDetailed(url, url_request_context_getter_.get());
294 const net::URLRequestStatus& FetcherStatus() const {
295 return fetcher_->GetStatus();
298 int FetcherResponseCode() const {
299 return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
300 fetcher_->GetResponseCode() : 0);
303 const net::HttpResponseHeaders* FetcherResponseHeaders() const {
304 return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
305 fetcher_->GetResponseHeaders() : NULL);
308 std::string FetcherResponseContents() const {
309 std::string contents;
310 if (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS)
311 CHECK(fetcher_->GetResponseAsString(&contents));
315 // Get the data from the server. Return value is success/failure of the
316 // data operation, |*sdch_encoding_used| indicates whether or not the
317 // data was retrieved with sdch encoding.
318 // This is done through FetchUrl(), so the various helper functions
319 // will have valid status if it returns successfully.
320 bool GetDataDetailed(net::URLRequestContextGetter* getter,
321 bool* sdch_encoding_used) {
323 GURL(base::StringPrintf(
324 "http://%s:%d%s", kTestHost, test_server_port(), kDataURLPath)),
326 EXPECT_EQ(net::URLRequestStatus::SUCCESS, FetcherStatus().status())
327 << "Error code is " << FetcherStatus().error();
328 EXPECT_EQ(200, FetcherResponseCode());
329 EXPECT_EQ(kSampleData, FetcherResponseContents());
331 if (net::URLRequestStatus::SUCCESS != FetcherStatus().status() ||
332 200 != FetcherResponseCode()) {
333 *sdch_encoding_used = false;
337 *sdch_encoding_used =
338 FetcherResponseHeaders()->HasHeaderValue("Content-Encoding", "sdch");
340 if (FetcherResponseContents() != kSampleData)
346 bool GetData(bool* sdch_encoding_used) {
347 return GetDataDetailed(url_request_context_getter_.get(),
351 // Client information and control.
353 int GetNumberOfDictionaryFetches(Profile* profile) {
355 base::RunLoop run_loop;
356 content::BrowserThread::PostTaskAndReply(
357 content::BrowserThread::IO,
359 base::Bind(&SdchBrowserTest::GetNumberOfDictionaryFetchesOnIOThread,
360 base::Unretained(this),
361 base::Unretained(profile->GetRequestContext()),
363 run_loop.QuitClosure());
365 DCHECK_NE(-1, fetches);
369 void BrowsingDataRemoveAndWait(int remove_mask) {
370 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
371 browser()->profile(), BrowsingDataRemover::LAST_HOUR);
372 BrowsingDataRemoverCompletionObserver completion_observer(remover);
373 remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
374 completion_observer.BlockUntilCompletion();
377 // Something of a cheat; nuke the dictionaries off the SdchManager without
378 // touching the cache (which browsing data remover would do).
379 void NukeSdchDictionaries() {
380 base::RunLoop run_loop;
381 content::BrowserThread::PostTaskAndReply(
382 content::BrowserThread::IO, FROM_HERE,
383 base::Bind(&SdchBrowserTest::NukeSdchDictionariesOnIOThread,
384 url_request_context_getter_),
385 run_loop.QuitClosure());
389 // Create a second browser based on a second profile to work within
391 bool SetupSecondBrowser() {
392 base::FilePath user_data_dir;
393 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
395 if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
398 second_profile_ = g_browser_process->profile_manager()->GetProfile(
399 second_profile_data_dir_.path());
400 if (!second_profile_) return false;
402 second_browser_ = new Browser(Browser::CreateParams(
403 second_profile_, browser()->host_desktop_type()));
404 if (!second_browser_) return false;
406 chrome::AddSelectedTabWithURL(second_browser_,
407 GURL(url::kAboutBlankURL),
408 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
409 content::WaitForLoadStop(
410 second_browser_->tab_strip_model()->GetActiveWebContents());
411 second_browser_->window()->Show();
413 content::BrowserThread::PostTask(
414 content::BrowserThread::IO,
416 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
417 base::Unretained(this),
419 second_browser_->profile()->GetRequestContext())));
424 bool SetupIncognitoBrowser() {
425 incognito_browser_ = CreateIncognitoBrowser();
427 if (!incognito_browser_)
430 content::BrowserThread::PostTask(
431 content::BrowserThread::IO,
433 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
434 base::Unretained(this),
436 incognito_browser_->profile()->GetRequestContext())));
441 Browser* second_browser() { return second_browser_; }
442 Browser* incognito_browser() { return incognito_browser_; }
444 // Server information and control.
446 void WaitAndGetTestVector(int num_requests, RequestVector* result) {
447 base::RunLoop run_loop;
448 content::BrowserThread::PostTask(
449 content::BrowserThread::IO, FROM_HERE,
450 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
451 base::Unretained(&response_handler_),
453 run_loop.QuitClosure(),
458 int test_server_port() { return test_server_.port(); }
460 void SetSdchCacheability(bool cache_sdch_response) {
461 base::RunLoop run_loop;
462 content::BrowserThread::PostTaskAndReply(
463 content::BrowserThread::IO, FROM_HERE,
464 base::Bind(&SdchResponseHandler::set_cache_sdch_response,
465 base::Unretained(&response_handler_),
466 cache_sdch_response),
467 run_loop.QuitClosure());
471 // Helper function for common test pattern.
473 // This function gets the data, confirms that the initial sending of the
474 // data included a dictionary advertisement, that that advertisement
475 // resulted in queueing a dictionary fetch, forces that fetch to
476 // go through, and confirms that a follow-on data load uses SDCH
477 // encoding. Returns true if the entire sequence of events occurred.
478 bool ForceSdchDictionaryLoad(Browser* browser) {
479 bool sdch_encoding_used = true;
480 bool data_gotten = GetDataDetailed(
481 browser->profile()->GetRequestContext(), &sdch_encoding_used);
482 EXPECT_TRUE(data_gotten);
483 if (!data_gotten) return false;
484 EXPECT_FALSE(sdch_encoding_used);
486 // Confirm that we were told to get the dictionary
487 const net::HttpResponseHeaders* headers = FetcherResponseHeaders();
489 bool have_dict_header =
490 headers->EnumerateHeader(NULL, "Get-Dictionary", &value);
491 EXPECT_TRUE(have_dict_header);
492 if (!have_dict_header) return false;
494 // If the above didn't result in a dictionary fetch being queued, the
495 // rest of the test will time out. Avoid that.
496 int num_fetches = GetNumberOfDictionaryFetches(browser->profile());
497 EXPECT_EQ(1, num_fetches);
498 if (1 != num_fetches) return false;
500 // Wait until the dictionary fetch actually happens.
501 RequestVector request_vector;
502 WaitAndGetTestVector(2, &request_vector);
503 EXPECT_EQ(request_vector[1].relative_url, kDictionaryURLPath);
504 if (request_vector[1].relative_url != kDictionaryURLPath) return false;
506 // Do a round trip to the server ignoring the encoding, presuming
507 // that if we've gotten data to this thread, the dictionary's made
508 // it into the SdchManager.
509 data_gotten = GetDataDetailed(
510 browser->profile()->GetRequestContext(), &sdch_encoding_used);
511 EXPECT_TRUE(data_gotten);
512 if (!data_gotten) return false;
514 // Now data fetches should be SDCH encoded.
515 sdch_encoding_used = false;
516 data_gotten = GetDataDetailed(
517 browser->profile()->GetRequestContext(), &sdch_encoding_used);
518 EXPECT_TRUE(data_gotten);
519 EXPECT_TRUE(sdch_encoding_used);
521 if (!data_gotten || !sdch_encoding_used) return false;
523 // Confirm the request vector looks at this point as expected.
524 WaitAndGetTestVector(4, &request_vector);
525 EXPECT_EQ(4u, request_vector.size());
526 EXPECT_EQ(request_vector[2].relative_url, kDataURLPath);
527 EXPECT_EQ(request_vector[3].relative_url, kDataURLPath);
528 return (4u == request_vector.size() &&
529 request_vector[2].relative_url == kDataURLPath &&
530 request_vector[3].relative_url == kDataURLPath);
534 static void NukeSdchDictionariesOnIOThread(
535 net::URLRequestContextGetter* context_getter) {
536 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
537 net::SdchManager* sdch_manager =
538 context_getter->GetURLRequestContext()->sdch_manager();
539 DCHECK(sdch_manager);
540 sdch_manager->ClearData();
543 void GetNumberOfDictionaryFetchesOnIOThread(
544 net::URLRequestContextGetter* context_getter,
546 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
548 net::SdchManager* manager(
549 context_getter->GetURLRequestContext()->sdch_manager());
550 DCHECK(fetch_counts_.end() != fetch_counts_.find(manager));
552 *result = fetch_counts_[manager];
555 // InProcessBrowserTest
556 void SetUpCommandLine(base::CommandLine* command_line) override {
557 command_line->AppendSwitchASCII(
558 switches::kHostResolverRules,
559 "MAP " + std::string(kTestHost) + " 127.0.0.1");
560 #if defined(OS_CHROMEOS)
561 command_line->AppendSwitch(
562 chromeos::switches::kIgnoreUserProfileMappingForTests);
566 void SetUpOnMainThread() override {
567 test_server_.RegisterRequestHandler(
568 base::Bind(&SdchResponseHandler::HandleRequest,
569 base::Unretained(&response_handler_)));
570 CHECK(test_server_.InitializeAndWaitUntilReady());
571 url_request_context_getter_ = browser()->profile()->GetRequestContext();
573 content::BrowserThread::PostTask(
574 content::BrowserThread::IO,
576 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
577 base::Unretained(this),
578 url_request_context_getter_));
581 void TearDownOnMainThread() override {
582 CHECK(test_server_.ShutdownAndWaitUntilComplete());
584 content::BrowserThread::PostTask(
585 content::BrowserThread::IO,
587 base::Bind(&SdchBrowserTest::UnsubscribeFromAllSdchNotifications,
588 base::Unretained(this)));
591 void SubscribeToSdchNotifications(
592 net::URLRequestContextGetter* context_getter) {
593 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
595 net::SdchManager* manager =
596 context_getter->GetURLRequestContext()->sdch_manager();
597 DCHECK(fetch_counts_.end() == fetch_counts_.find(manager));
599 fetch_counts_[manager] = 0;
600 manager->AddObserver(this);
603 void UnsubscribeFromAllSdchNotifications() {
604 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
606 for (auto it = fetch_counts_.begin(); it != fetch_counts_.end(); ++it)
607 it->first->RemoveObserver(this);
609 fetch_counts_.clear();
613 void OnGetDictionary(net::SdchManager* manager,
614 const GURL& request_url,
615 const GURL& dictionary_url) override {
616 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
617 DLOG(ERROR) << "Retrieving count of notifications from manager " << manager;
618 DCHECK(fetch_counts_.end() != fetch_counts_.find(manager));
619 ++fetch_counts_[manager];
621 void OnClearDictionaries(net::SdchManager* manager) override {}
623 // URLFetcherDelegate
624 void OnURLFetchComplete(const net::URLFetcher* source) override {
625 url_fetch_complete_ = true;
627 base::MessageLoopForUI::current()->Quit();
630 SdchResponseHandler response_handler_;
631 net::test_server::EmbeddedTestServer test_server_;
632 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
633 scoped_ptr<net::URLFetcher> fetcher_;
634 bool url_fetch_complete_;
636 base::ScopedTempDir second_profile_data_dir_;
637 Profile* second_profile_;
638 Browser* second_browser_;
639 Browser* incognito_browser_;
641 // IO Thread access only.
642 std::map<net::SdchManager*, int> fetch_counts_;
645 const char SdchBrowserTest::kTestHost[] = "our.test.host.com";
647 // Confirm that after getting a dictionary, calling the browsing
648 // data remover renders it unusable. Also (in calling
649 // ForceSdchDictionaryLoad()) servers as a smoke test for SDCH.
650 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, BrowsingDataRemover) {
651 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
653 // Confirm browsing data remover without removing the cache leaves
655 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_ALL &
656 ~BrowsingDataRemover::REMOVE_CACHE);
657 bool sdch_encoding_used = false;
658 ASSERT_TRUE(GetData(&sdch_encoding_used));
659 EXPECT_TRUE(sdch_encoding_used);
661 // Confirm browsing data remover removing the cache clears SDCH state.
662 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_CACHE);
663 sdch_encoding_used = false;
664 ASSERT_TRUE(GetData(&sdch_encoding_used));
665 EXPECT_FALSE(sdch_encoding_used);
668 // Confirm dictionaries not visible in other profiles.
669 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, Isolation) {
670 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
671 ASSERT_TRUE(SetupSecondBrowser());
672 ASSERT_TRUE(SetupIncognitoBrowser());
674 // Data fetches from incognito or separate profiles should not be SDCH
676 bool sdch_encoding_used = true;
678 GetDataDetailed(incognito_browser()->profile()->GetRequestContext(),
679 &sdch_encoding_used));
680 EXPECT_FALSE(sdch_encoding_used);
682 sdch_encoding_used = true;
683 EXPECT_TRUE(GetDataDetailed(
684 second_browser()->profile()->GetRequestContext(), &sdch_encoding_used));
685 EXPECT_FALSE(sdch_encoding_used);
688 // Confirm a dictionary loaded in incognito isn't visible in the main profile.
689 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, ReverseIsolation) {
690 ASSERT_TRUE(SetupIncognitoBrowser());
691 ASSERT_TRUE(ForceSdchDictionaryLoad(incognito_browser()));
693 // Data fetches on main browser should not be SDCH encoded.
694 bool sdch_encoding_used = true;
695 ASSERT_TRUE(GetData(&sdch_encoding_used));
696 EXPECT_FALSE(sdch_encoding_used);