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::EqualsCaseInsensitiveASCII(it
->first
, 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::EqualsCaseInsensitiveASCII(tokenizer
.token(), "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
->AddCustomHeader("Cache-Control", "max-age=3600");
221 response
->set_content_type("application/x-sdch-dictionary");
222 response
->set_content(sdch_dictionary_contents_
);
224 std::vector
<base::Closure
> callbacks
;
225 callbacks
.swap(callback_vector_
);
226 for (std::vector
<base::Closure
>::iterator it
= callbacks
.begin();
227 it
!= callbacks
.end(); ++it
) {
230 return response
.Pass();
233 void WaitAndGetRequestVector(int num_requests
,
234 base::Closure callback
,
236 DCHECK_LT(0, num_requests
);
237 if (static_cast<size_t>(num_requests
) > request_vector_
.size()) {
238 callback_vector_
.push_back(
239 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector
,
240 weak_ptr_factory_
.GetWeakPtr(), num_requests
,
244 *v
= request_vector_
;
245 content::BrowserThread::PostTask(
246 content::BrowserThread::UI
, FROM_HERE
, callback
);
249 void set_cache_sdch_response(bool cache_sdch_response
) {
250 cache_sdch_response_
= cache_sdch_response
;
254 bool cache_sdch_response_
;
255 std::string encoded_data_
;
256 std::string sdch_dictionary_contents_
;
257 std::string dictionary_client_hash_
;
258 std::string dictionary_server_hash_
;
259 RequestVector request_vector_
;
260 std::vector
<base::Closure
> callback_vector_
;
261 base::WeakPtrFactory
<SdchResponseHandler
> weak_ptr_factory_
;
264 class TestSdchObserver
: public net::SdchObserver
{
266 TestSdchObserver() : manager_(nullptr), fetch_count_(0) {}
267 ~TestSdchObserver() override
{
269 manager_
->RemoveObserver(this);
273 void Observe(net::SdchManager
* manager
) {
276 manager_
->AddObserver(this);
280 void OnDictionaryAdded(const GURL
& /* dictionary_url */,
281 const std::string
& /* server_hash */) override
{}
282 void OnDictionaryRemoved(const std::string
& /* server_hash */) override
{}
283 void OnGetDictionary(const GURL
& /* request_url */,
284 const GURL
& /* dictionary_url */) override
{
287 void OnDictionaryUsed(const std::string
& /* server_hash */) override
{}
288 void OnClearDictionaries() override
{}
290 int fetch_count() const { return fetch_count_
; }
293 net::SdchManager
* manager_
;
297 class SdchBrowserTest
: public InProcessBrowserTest
,
298 public net::URLFetcherDelegate
{
300 static const char kTestHost
[];
303 : response_handler_(kTestHost
),
304 url_request_context_getter_(NULL
),
305 url_fetch_complete_(false),
308 // Helper functions for fetching data.
310 void FetchUrlDetailed(GURL url
, net::URLRequestContextGetter
* getter
) {
311 url_fetch_complete_
= false;
312 fetcher_
= net::URLFetcher::Create(url
, net::URLFetcher::GET
, this);
313 fetcher_
->SetRequestContext(getter
);
315 if (!url_fetch_complete_
) {
317 content::RunMessageLoop();
320 CHECK(url_fetch_complete_
);
323 void FetchUrl(GURL url
) {
324 FetchUrlDetailed(url
, url_request_context_getter_
.get());
327 const net::URLRequestStatus
& FetcherStatus() const {
328 return fetcher_
->GetStatus();
331 int FetcherResponseCode() const {
332 return (fetcher_
->GetStatus().status() == net::URLRequestStatus::SUCCESS
?
333 fetcher_
->GetResponseCode() : 0);
336 const net::HttpResponseHeaders
* FetcherResponseHeaders() const {
337 return (fetcher_
->GetStatus().status() == net::URLRequestStatus::SUCCESS
?
338 fetcher_
->GetResponseHeaders() : NULL
);
341 std::string
FetcherResponseContents() const {
342 std::string contents
;
343 if (fetcher_
->GetStatus().status() == net::URLRequestStatus::SUCCESS
)
344 CHECK(fetcher_
->GetResponseAsString(&contents
));
348 // Get the data from the server. Return value is success/failure of the
349 // data operation, |*sdch_encoding_used| indicates whether or not the
350 // data was retrieved with sdch encoding.
351 // This is done through FetchUrl(), so the various helper functions
352 // will have valid status if it returns successfully.
353 bool GetDataDetailed(net::URLRequestContextGetter
* getter
,
354 bool* sdch_encoding_used
) {
356 GURL(base::StringPrintf(
357 "http://%s:%u%s", kTestHost
, test_server_port(), kDataURLPath
)),
359 EXPECT_EQ(net::URLRequestStatus::SUCCESS
, FetcherStatus().status())
360 << "Error code is " << FetcherStatus().error();
361 EXPECT_EQ(200, FetcherResponseCode());
362 EXPECT_EQ(kSampleData
, FetcherResponseContents());
364 if (net::URLRequestStatus::SUCCESS
!= FetcherStatus().status() ||
365 200 != FetcherResponseCode()) {
366 *sdch_encoding_used
= false;
370 *sdch_encoding_used
=
371 FetcherResponseHeaders()->HasHeaderValue("Content-Encoding", "sdch");
373 if (FetcherResponseContents() != kSampleData
)
379 bool GetData(bool* sdch_encoding_used
) {
380 return GetDataDetailed(url_request_context_getter_
.get(),
384 // Client information and control.
386 int GetNumberOfDictionaryFetches(Profile
* profile
) {
388 base::RunLoop run_loop
;
389 content::BrowserThread::PostTaskAndReply(
390 content::BrowserThread::IO
,
392 base::Bind(&SdchBrowserTest::GetNumberOfDictionaryFetchesOnIOThread
,
393 base::Unretained(this),
394 base::Unretained(profile
->GetRequestContext()),
396 run_loop
.QuitClosure());
398 DCHECK_NE(-1, fetches
);
402 void BrowsingDataRemoveAndWait(int remove_mask
) {
403 BrowsingDataRemover
* remover
= BrowsingDataRemover::CreateForPeriod(
404 browser()->profile(), BrowsingDataRemover::LAST_HOUR
);
405 BrowsingDataRemoverCompletionObserver
completion_observer(remover
);
406 remover
->Remove(remove_mask
, BrowsingDataHelper::UNPROTECTED_WEB
);
407 completion_observer
.BlockUntilCompletion();
410 // Something of a cheat; nuke the dictionaries off the SdchManager without
411 // touching the cache (which browsing data remover would do).
412 void NukeSdchDictionaries() {
413 base::RunLoop run_loop
;
414 content::BrowserThread::PostTaskAndReply(
415 content::BrowserThread::IO
, FROM_HERE
,
416 base::Bind(&SdchBrowserTest::NukeSdchDictionariesOnIOThread
,
417 url_request_context_getter_
),
418 run_loop
.QuitClosure());
422 // Create a second browser based on a second profile to work within
424 bool SetupSecondBrowser() {
425 base::FilePath user_data_dir
;
426 PathService::Get(chrome::DIR_USER_DATA
, &user_data_dir
);
428 if (!second_profile_data_dir_
.CreateUniqueTempDirUnderPath(user_data_dir
))
431 second_profile_
= g_browser_process
->profile_manager()->GetProfile(
432 second_profile_data_dir_
.path());
433 if (!second_profile_
) return false;
435 second_browser_
= new Browser(Browser::CreateParams(
436 second_profile_
, browser()->host_desktop_type()));
437 if (!second_browser_
) return false;
439 chrome::AddSelectedTabWithURL(second_browser_
,
440 GURL(url::kAboutBlankURL
),
441 ui::PAGE_TRANSITION_AUTO_TOPLEVEL
);
442 content::WaitForLoadStop(
443 second_browser_
->tab_strip_model()->GetActiveWebContents());
444 second_browser_
->window()->Show();
446 content::BrowserThread::PostTask(
447 content::BrowserThread::IO
,
449 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications
,
450 base::Unretained(this),
452 second_browser_
->profile()->GetRequestContext())));
457 bool SetupIncognitoBrowser() {
458 incognito_browser_
= CreateIncognitoBrowser();
460 if (!incognito_browser_
)
463 content::BrowserThread::PostTask(
464 content::BrowserThread::IO
,
466 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications
,
467 base::Unretained(this),
469 incognito_browser_
->profile()->GetRequestContext())));
474 Browser
* second_browser() { return second_browser_
; }
475 Browser
* incognito_browser() { return incognito_browser_
; }
477 // Server information and control.
479 void WaitAndGetTestVector(int num_requests
, RequestVector
* result
) {
480 base::RunLoop run_loop
;
481 content::BrowserThread::PostTask(
482 content::BrowserThread::IO
, FROM_HERE
,
483 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector
,
484 base::Unretained(&response_handler_
),
486 run_loop
.QuitClosure(),
491 uint16
test_server_port() { return test_server_
.port(); }
493 void SetSdchCacheability(bool cache_sdch_response
) {
494 base::RunLoop run_loop
;
495 content::BrowserThread::PostTaskAndReply(
496 content::BrowserThread::IO
, FROM_HERE
,
497 base::Bind(&SdchResponseHandler::set_cache_sdch_response
,
498 base::Unretained(&response_handler_
),
499 cache_sdch_response
),
500 run_loop
.QuitClosure());
504 // Helper function for common test pattern.
506 // This function gets the data, confirms that the initial sending of the
507 // data included a dictionary advertisement, that that advertisement
508 // resulted in queueing a dictionary fetch, forces that fetch to
509 // go through, and confirms that a follow-on data load uses SDCH
510 // encoding. Returns true if the entire sequence of events occurred.
511 bool ForceSdchDictionaryLoad(Browser
* browser
) {
512 bool sdch_encoding_used
= true;
513 bool data_gotten
= GetDataDetailed(
514 browser
->profile()->GetRequestContext(), &sdch_encoding_used
);
515 EXPECT_TRUE(data_gotten
);
516 if (!data_gotten
) return false;
517 EXPECT_FALSE(sdch_encoding_used
);
519 // Confirm that we were told to get the dictionary
520 const net::HttpResponseHeaders
* headers
= FetcherResponseHeaders();
522 bool have_dict_header
=
523 headers
->EnumerateHeader(NULL
, "Get-Dictionary", &value
);
524 EXPECT_TRUE(have_dict_header
);
525 if (!have_dict_header
) return false;
527 // If the above didn't result in a dictionary fetch being queued, the
528 // rest of the test will time out. Avoid that.
529 int num_fetches
= GetNumberOfDictionaryFetches(browser
->profile());
530 EXPECT_EQ(1, num_fetches
);
531 if (1 != num_fetches
) return false;
533 // Wait until the dictionary fetch actually happens.
534 RequestVector request_vector
;
535 WaitAndGetTestVector(2, &request_vector
);
536 EXPECT_EQ(request_vector
[1].relative_url
, kDictionaryURLPath
);
537 if (request_vector
[1].relative_url
!= kDictionaryURLPath
) return false;
539 // Do a round trip to the server ignoring the encoding, presuming
540 // that if we've gotten data to this thread, the dictionary's made
541 // it into the SdchManager.
542 data_gotten
= GetDataDetailed(
543 browser
->profile()->GetRequestContext(), &sdch_encoding_used
);
544 EXPECT_TRUE(data_gotten
);
545 if (!data_gotten
) return false;
547 // Now data fetches should be SDCH encoded.
548 sdch_encoding_used
= false;
549 data_gotten
= GetDataDetailed(
550 browser
->profile()->GetRequestContext(), &sdch_encoding_used
);
551 EXPECT_TRUE(data_gotten
);
552 EXPECT_TRUE(sdch_encoding_used
);
554 if (!data_gotten
|| !sdch_encoding_used
) return false;
556 // Confirm the request vector looks at this point as expected.
557 WaitAndGetTestVector(4, &request_vector
);
558 EXPECT_EQ(4u, request_vector
.size());
559 EXPECT_EQ(request_vector
[2].relative_url
, kDataURLPath
);
560 EXPECT_EQ(request_vector
[3].relative_url
, kDataURLPath
);
561 return (4u == request_vector
.size() &&
562 request_vector
[2].relative_url
== kDataURLPath
&&
563 request_vector
[3].relative_url
== kDataURLPath
);
567 static void NukeSdchDictionariesOnIOThread(
568 net::URLRequestContextGetter
* context_getter
) {
569 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
570 net::SdchManager
* sdch_manager
=
571 context_getter
->GetURLRequestContext()->sdch_manager();
572 DCHECK(sdch_manager
);
573 sdch_manager
->ClearData();
576 void GetNumberOfDictionaryFetchesOnIOThread(
577 net::URLRequestContextGetter
* context_getter
,
579 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
581 net::SdchManager
* manager(
582 context_getter
->GetURLRequestContext()->sdch_manager());
583 DCHECK(observers_
.end() != observers_
.find(manager
));
585 *result
= observers_
[manager
].fetch_count();
588 // InProcessBrowserTest
589 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
590 command_line
->AppendSwitchASCII(
591 switches::kHostResolverRules
,
592 "MAP " + std::string(kTestHost
) + " 127.0.0.1");
593 #if defined(OS_CHROMEOS)
594 command_line
->AppendSwitch(
595 chromeos::switches::kIgnoreUserProfileMappingForTests
);
599 void SetUpOnMainThread() override
{
600 test_server_
.RegisterRequestHandler(
601 base::Bind(&SdchResponseHandler::HandleRequest
,
602 base::Unretained(&response_handler_
)));
603 CHECK(test_server_
.InitializeAndWaitUntilReady());
604 url_request_context_getter_
= browser()->profile()->GetRequestContext();
606 content::BrowserThread::PostTask(
607 content::BrowserThread::IO
,
609 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications
,
610 base::Unretained(this),
611 url_request_context_getter_
));
614 void TearDownOnMainThread() override
{
615 CHECK(test_server_
.ShutdownAndWaitUntilComplete());
617 content::BrowserThread::PostTask(
618 content::BrowserThread::IO
,
620 base::Bind(&SdchBrowserTest::UnsubscribeFromAllSdchNotifications
,
621 base::Unretained(this)));
624 void SubscribeToSdchNotifications(
625 net::URLRequestContextGetter
* context_getter
) {
626 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
628 net::SdchManager
* manager
=
629 context_getter
->GetURLRequestContext()->sdch_manager();
630 DCHECK(observers_
.end() == observers_
.find(manager
));
632 observers_
[manager
].Observe(manager
);
635 void UnsubscribeFromAllSdchNotifications() {
636 DCHECK_CURRENTLY_ON(content::BrowserThread::IO
);
640 // URLFetcherDelegate
641 void OnURLFetchComplete(const net::URLFetcher
* source
) override
{
642 url_fetch_complete_
= true;
644 base::MessageLoopForUI::current()->Quit();
647 SdchResponseHandler response_handler_
;
648 net::test_server::EmbeddedTestServer test_server_
;
649 scoped_refptr
<net::URLRequestContextGetter
> url_request_context_getter_
;
650 scoped_ptr
<net::URLFetcher
> fetcher_
;
651 bool url_fetch_complete_
;
653 base::ScopedTempDir second_profile_data_dir_
;
654 Profile
* second_profile_
;
655 Browser
* second_browser_
;
656 Browser
* incognito_browser_
;
658 // IO Thread access only.
659 std::map
<net::SdchManager
*, TestSdchObserver
> observers_
;
662 const char SdchBrowserTest::kTestHost
[] = "our.test.host.com";
664 // Confirm that after getting a dictionary, calling the browsing
665 // data remover renders it unusable. Also (in calling
666 // ForceSdchDictionaryLoad()) servers as a smoke test for SDCH.
667 IN_PROC_BROWSER_TEST_F(SdchBrowserTest
, BrowsingDataRemover
) {
668 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
670 // Confirm browsing data remover without removing the cache leaves
672 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_ALL
&
673 ~BrowsingDataRemover::REMOVE_CACHE
);
674 bool sdch_encoding_used
= false;
675 ASSERT_TRUE(GetData(&sdch_encoding_used
));
676 EXPECT_TRUE(sdch_encoding_used
);
678 // Confirm browsing data remover removing the cache clears SDCH state.
679 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_CACHE
);
680 sdch_encoding_used
= false;
681 ASSERT_TRUE(GetData(&sdch_encoding_used
));
682 EXPECT_FALSE(sdch_encoding_used
);
685 // Confirm dictionaries not visible in other profiles.
686 IN_PROC_BROWSER_TEST_F(SdchBrowserTest
, Isolation
) {
687 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
688 ASSERT_TRUE(SetupSecondBrowser());
689 ASSERT_TRUE(SetupIncognitoBrowser());
691 // Data fetches from incognito or separate profiles should not be SDCH
693 bool sdch_encoding_used
= true;
695 GetDataDetailed(incognito_browser()->profile()->GetRequestContext(),
696 &sdch_encoding_used
));
697 EXPECT_FALSE(sdch_encoding_used
);
699 sdch_encoding_used
= true;
700 EXPECT_TRUE(GetDataDetailed(
701 second_browser()->profile()->GetRequestContext(), &sdch_encoding_used
));
702 EXPECT_FALSE(sdch_encoding_used
);
705 // Confirm a dictionary loaded in incognito isn't visible in the main profile.
706 IN_PROC_BROWSER_TEST_F(SdchBrowserTest
, ReverseIsolation
) {
707 ASSERT_TRUE(SetupIncognitoBrowser());
708 ASSERT_TRUE(ForceSdchDictionaryLoad(incognito_browser()));
710 // Data fetches on main browser should not be SDCH encoded.
711 bool sdch_encoding_used
= true;
712 ASSERT_TRUE(GetData(&sdch_encoding_used
));
713 EXPECT_FALSE(sdch_encoding_used
);