Check USB device path access when prompting users to select a device.
[chromium-blink-merge.git] / chrome / browser / net / sdch_browsertest.cc
bloba3748af4583121ccdfc4b1289806196436dd0373
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
6 // results
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/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"
51 #endif
53 namespace {
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
105 // header.
106 bool GetRequestHeader(const HttpRequestHeaderMap& map,
107 const char* header,
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)) {
112 *value = it->second;
113 return true;
116 return false;
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) {
122 DCHECK(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 {
132 public:
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) {
137 // Dictionary
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_);
150 // Encoded response.
151 open_vcdiff::HashedDictionary vcdiff_dictionary(
152 kDictionaryContents, strlen(kDictionaryContents));
153 bool result = vcdiff_dictionary.Init();
154 DCHECK(result);
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_);
159 DCHECK(result);
160 result = encoder.EncodeChunk(
161 kSampleData, strlen(kSampleData), &encoded_data_);
162 DCHECK(result);
163 result = encoder.FinishEncoding(&encoded_data_);
164 DCHECK(result);
167 static bool ClientIsAdvertisingSdchEncoding(const HttpRequestHeaderMap& map) {
168 std::string value;
169 if (!GetRequestHeader(map, "accept-encoding", &value))
170 return false;
171 base::StringTokenizer tokenizer(value, " ,");
172 while (tokenizer.GetNext()) {
173 if (base::strcasecmp(tokenizer.token().c_str(), "sdch"))
174 return true;
176 return false;
179 bool ShouldRespondWithSdchEncoding(const HttpRequestHeaderMap& map) {
180 std::string value;
181 if (!GetRequestHeader(map, "avail-dictionary", &value))
182 return false;
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
203 // dictionary.
204 if (cache_sdch_response_)
205 response->AddCustomHeader("Cache-Control", "max-age=3600");
206 else
207 response->AddCustomHeader("Cache-Control", "no-store");
208 } else {
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");
217 } else {
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) {
228 it->Run();
230 return response.Pass();
233 void WaitAndGetRequestVector(int num_requests,
234 base::Closure callback,
235 RequestVector* v) {
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,
241 callback, v));
242 return;
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;
253 private:
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 SdchBrowserTest : public InProcessBrowserTest,
265 public net::URLFetcherDelegate,
266 public net::SdchObserver {
267 public:
268 static const char kTestHost[];
270 SdchBrowserTest()
271 : response_handler_(kTestHost),
272 url_request_context_getter_(NULL),
273 url_fetch_complete_(false),
274 waiting_(false) {}
276 // Helper functions for fetching data.
278 void FetchUrlDetailed(GURL url, net::URLRequestContextGetter* getter) {
279 url_fetch_complete_ = false;
280 fetcher_.reset(net::URLFetcher::Create(url, net::URLFetcher::GET, this));
281 fetcher_->SetRequestContext(getter);
282 fetcher_->Start();
283 if (!url_fetch_complete_) {
284 waiting_ = true;
285 content::RunMessageLoop();
286 waiting_ = false;
288 CHECK(url_fetch_complete_);
291 void FetchUrl(GURL url) {
292 FetchUrlDetailed(url, url_request_context_getter_.get());
295 const net::URLRequestStatus& FetcherStatus() const {
296 return fetcher_->GetStatus();
299 int FetcherResponseCode() const {
300 return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
301 fetcher_->GetResponseCode() : 0);
304 const net::HttpResponseHeaders* FetcherResponseHeaders() const {
305 return (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS ?
306 fetcher_->GetResponseHeaders() : NULL);
309 std::string FetcherResponseContents() const {
310 std::string contents;
311 if (fetcher_->GetStatus().status() == net::URLRequestStatus::SUCCESS)
312 CHECK(fetcher_->GetResponseAsString(&contents));
313 return contents;
316 // Get the data from the server. Return value is success/failure of the
317 // data operation, |*sdch_encoding_used| indicates whether or not the
318 // data was retrieved with sdch encoding.
319 // This is done through FetchUrl(), so the various helper functions
320 // will have valid status if it returns successfully.
321 bool GetDataDetailed(net::URLRequestContextGetter* getter,
322 bool* sdch_encoding_used) {
323 FetchUrlDetailed(
324 GURL(base::StringPrintf(
325 "http://%s:%u%s", kTestHost, test_server_port(), kDataURLPath)),
326 getter);
327 EXPECT_EQ(net::URLRequestStatus::SUCCESS, FetcherStatus().status())
328 << "Error code is " << FetcherStatus().error();
329 EXPECT_EQ(200, FetcherResponseCode());
330 EXPECT_EQ(kSampleData, FetcherResponseContents());
332 if (net::URLRequestStatus::SUCCESS != FetcherStatus().status() ||
333 200 != FetcherResponseCode()) {
334 *sdch_encoding_used = false;
335 return false;
338 *sdch_encoding_used =
339 FetcherResponseHeaders()->HasHeaderValue("Content-Encoding", "sdch");
341 if (FetcherResponseContents() != kSampleData)
342 return false;
344 return true;
347 bool GetData(bool* sdch_encoding_used) {
348 return GetDataDetailed(url_request_context_getter_.get(),
349 sdch_encoding_used);
352 // Client information and control.
354 int GetNumberOfDictionaryFetches(Profile* profile) {
355 int fetches = -1;
356 base::RunLoop run_loop;
357 content::BrowserThread::PostTaskAndReply(
358 content::BrowserThread::IO,
359 FROM_HERE,
360 base::Bind(&SdchBrowserTest::GetNumberOfDictionaryFetchesOnIOThread,
361 base::Unretained(this),
362 base::Unretained(profile->GetRequestContext()),
363 &fetches),
364 run_loop.QuitClosure());
365 run_loop.Run();
366 DCHECK_NE(-1, fetches);
367 return fetches;
370 void BrowsingDataRemoveAndWait(int remove_mask) {
371 BrowsingDataRemover* remover = BrowsingDataRemover::CreateForPeriod(
372 browser()->profile(), BrowsingDataRemover::LAST_HOUR);
373 BrowsingDataRemoverCompletionObserver completion_observer(remover);
374 remover->Remove(remove_mask, BrowsingDataHelper::UNPROTECTED_WEB);
375 completion_observer.BlockUntilCompletion();
378 // Something of a cheat; nuke the dictionaries off the SdchManager without
379 // touching the cache (which browsing data remover would do).
380 void NukeSdchDictionaries() {
381 base::RunLoop run_loop;
382 content::BrowserThread::PostTaskAndReply(
383 content::BrowserThread::IO, FROM_HERE,
384 base::Bind(&SdchBrowserTest::NukeSdchDictionariesOnIOThread,
385 url_request_context_getter_),
386 run_loop.QuitClosure());
387 run_loop.Run();
390 // Create a second browser based on a second profile to work within
391 // multi-profile.
392 bool SetupSecondBrowser() {
393 base::FilePath user_data_dir;
394 PathService::Get(chrome::DIR_USER_DATA, &user_data_dir);
396 if (!second_profile_data_dir_.CreateUniqueTempDirUnderPath(user_data_dir))
397 return false;
399 second_profile_ = g_browser_process->profile_manager()->GetProfile(
400 second_profile_data_dir_.path());
401 if (!second_profile_) return false;
403 second_browser_ = new Browser(Browser::CreateParams(
404 second_profile_, browser()->host_desktop_type()));
405 if (!second_browser_) return false;
407 chrome::AddSelectedTabWithURL(second_browser_,
408 GURL(url::kAboutBlankURL),
409 ui::PAGE_TRANSITION_AUTO_TOPLEVEL);
410 content::WaitForLoadStop(
411 second_browser_->tab_strip_model()->GetActiveWebContents());
412 second_browser_->window()->Show();
414 content::BrowserThread::PostTask(
415 content::BrowserThread::IO,
416 FROM_HERE,
417 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
418 base::Unretained(this),
419 make_scoped_refptr(
420 second_browser_->profile()->GetRequestContext())));
422 return true;
425 bool SetupIncognitoBrowser() {
426 incognito_browser_ = CreateIncognitoBrowser();
428 if (!incognito_browser_)
429 return false;
431 content::BrowserThread::PostTask(
432 content::BrowserThread::IO,
433 FROM_HERE,
434 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
435 base::Unretained(this),
436 make_scoped_refptr(
437 incognito_browser_->profile()->GetRequestContext())));
439 return true;
442 Browser* second_browser() { return second_browser_; }
443 Browser* incognito_browser() { return incognito_browser_; }
445 // Server information and control.
447 void WaitAndGetTestVector(int num_requests, RequestVector* result) {
448 base::RunLoop run_loop;
449 content::BrowserThread::PostTask(
450 content::BrowserThread::IO, FROM_HERE,
451 base::Bind(&SdchResponseHandler::WaitAndGetRequestVector,
452 base::Unretained(&response_handler_),
453 num_requests,
454 run_loop.QuitClosure(),
455 result));
456 run_loop.Run();
459 uint16 test_server_port() { return test_server_.port(); }
461 void SetSdchCacheability(bool cache_sdch_response) {
462 base::RunLoop run_loop;
463 content::BrowserThread::PostTaskAndReply(
464 content::BrowserThread::IO, FROM_HERE,
465 base::Bind(&SdchResponseHandler::set_cache_sdch_response,
466 base::Unretained(&response_handler_),
467 cache_sdch_response),
468 run_loop.QuitClosure());
469 run_loop.Run();
472 // Helper function for common test pattern.
474 // This function gets the data, confirms that the initial sending of the
475 // data included a dictionary advertisement, that that advertisement
476 // resulted in queueing a dictionary fetch, forces that fetch to
477 // go through, and confirms that a follow-on data load uses SDCH
478 // encoding. Returns true if the entire sequence of events occurred.
479 bool ForceSdchDictionaryLoad(Browser* browser) {
480 bool sdch_encoding_used = true;
481 bool data_gotten = GetDataDetailed(
482 browser->profile()->GetRequestContext(), &sdch_encoding_used);
483 EXPECT_TRUE(data_gotten);
484 if (!data_gotten) return false;
485 EXPECT_FALSE(sdch_encoding_used);
487 // Confirm that we were told to get the dictionary
488 const net::HttpResponseHeaders* headers = FetcherResponseHeaders();
489 std::string value;
490 bool have_dict_header =
491 headers->EnumerateHeader(NULL, "Get-Dictionary", &value);
492 EXPECT_TRUE(have_dict_header);
493 if (!have_dict_header) return false;
495 // If the above didn't result in a dictionary fetch being queued, the
496 // rest of the test will time out. Avoid that.
497 int num_fetches = GetNumberOfDictionaryFetches(browser->profile());
498 EXPECT_EQ(1, num_fetches);
499 if (1 != num_fetches) return false;
501 // Wait until the dictionary fetch actually happens.
502 RequestVector request_vector;
503 WaitAndGetTestVector(2, &request_vector);
504 EXPECT_EQ(request_vector[1].relative_url, kDictionaryURLPath);
505 if (request_vector[1].relative_url != kDictionaryURLPath) return false;
507 // Do a round trip to the server ignoring the encoding, presuming
508 // that if we've gotten data to this thread, the dictionary's made
509 // it into the SdchManager.
510 data_gotten = GetDataDetailed(
511 browser->profile()->GetRequestContext(), &sdch_encoding_used);
512 EXPECT_TRUE(data_gotten);
513 if (!data_gotten) return false;
515 // Now data fetches should be SDCH encoded.
516 sdch_encoding_used = false;
517 data_gotten = GetDataDetailed(
518 browser->profile()->GetRequestContext(), &sdch_encoding_used);
519 EXPECT_TRUE(data_gotten);
520 EXPECT_TRUE(sdch_encoding_used);
522 if (!data_gotten || !sdch_encoding_used) return false;
524 // Confirm the request vector looks at this point as expected.
525 WaitAndGetTestVector(4, &request_vector);
526 EXPECT_EQ(4u, request_vector.size());
527 EXPECT_EQ(request_vector[2].relative_url, kDataURLPath);
528 EXPECT_EQ(request_vector[3].relative_url, kDataURLPath);
529 return (4u == request_vector.size() &&
530 request_vector[2].relative_url == kDataURLPath &&
531 request_vector[3].relative_url == kDataURLPath);
534 private:
535 static void NukeSdchDictionariesOnIOThread(
536 net::URLRequestContextGetter* context_getter) {
537 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
538 net::SdchManager* sdch_manager =
539 context_getter->GetURLRequestContext()->sdch_manager();
540 DCHECK(sdch_manager);
541 sdch_manager->ClearData();
544 void GetNumberOfDictionaryFetchesOnIOThread(
545 net::URLRequestContextGetter* context_getter,
546 int* result) {
547 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
549 net::SdchManager* manager(
550 context_getter->GetURLRequestContext()->sdch_manager());
551 DCHECK(fetch_counts_.end() != fetch_counts_.find(manager));
553 *result = fetch_counts_[manager];
556 // InProcessBrowserTest
557 void SetUpCommandLine(base::CommandLine* command_line) override {
558 command_line->AppendSwitchASCII(
559 switches::kHostResolverRules,
560 "MAP " + std::string(kTestHost) + " 127.0.0.1");
561 #if defined(OS_CHROMEOS)
562 command_line->AppendSwitch(
563 chromeos::switches::kIgnoreUserProfileMappingForTests);
564 #endif
567 void SetUpOnMainThread() override {
568 test_server_.RegisterRequestHandler(
569 base::Bind(&SdchResponseHandler::HandleRequest,
570 base::Unretained(&response_handler_)));
571 CHECK(test_server_.InitializeAndWaitUntilReady());
572 url_request_context_getter_ = browser()->profile()->GetRequestContext();
574 content::BrowserThread::PostTask(
575 content::BrowserThread::IO,
576 FROM_HERE,
577 base::Bind(&SdchBrowserTest::SubscribeToSdchNotifications,
578 base::Unretained(this),
579 url_request_context_getter_));
582 void TearDownOnMainThread() override {
583 CHECK(test_server_.ShutdownAndWaitUntilComplete());
585 content::BrowserThread::PostTask(
586 content::BrowserThread::IO,
587 FROM_HERE,
588 base::Bind(&SdchBrowserTest::UnsubscribeFromAllSdchNotifications,
589 base::Unretained(this)));
592 void SubscribeToSdchNotifications(
593 net::URLRequestContextGetter* context_getter) {
594 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
596 net::SdchManager* manager =
597 context_getter->GetURLRequestContext()->sdch_manager();
598 DCHECK(fetch_counts_.end() == fetch_counts_.find(manager));
600 fetch_counts_[manager] = 0;
601 manager->AddObserver(this);
604 void UnsubscribeFromAllSdchNotifications() {
605 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
607 for (auto it = fetch_counts_.begin(); it != fetch_counts_.end(); ++it)
608 it->first->RemoveObserver(this);
610 fetch_counts_.clear();
613 // SdchObserver
614 void OnDictionaryUsed(net::SdchManager* manager,
615 const std::string& server_hash) override {}
617 void OnGetDictionary(net::SdchManager* manager,
618 const GURL& request_url,
619 const GURL& dictionary_url) override {
620 DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::IO));
621 DLOG(ERROR) << "Retrieving count of notifications from manager " << manager;
622 DCHECK(fetch_counts_.end() != fetch_counts_.find(manager));
623 ++fetch_counts_[manager];
626 void OnClearDictionaries(net::SdchManager* manager) override {}
628 // URLFetcherDelegate
629 void OnURLFetchComplete(const net::URLFetcher* source) override {
630 url_fetch_complete_ = true;
631 if (waiting_)
632 base::MessageLoopForUI::current()->Quit();
635 SdchResponseHandler response_handler_;
636 net::test_server::EmbeddedTestServer test_server_;
637 scoped_refptr<net::URLRequestContextGetter> url_request_context_getter_;
638 scoped_ptr<net::URLFetcher> fetcher_;
639 bool url_fetch_complete_;
640 bool waiting_;
641 base::ScopedTempDir second_profile_data_dir_;
642 Profile* second_profile_;
643 Browser* second_browser_;
644 Browser* incognito_browser_;
646 // IO Thread access only.
647 std::map<net::SdchManager*, int> fetch_counts_;
650 const char SdchBrowserTest::kTestHost[] = "our.test.host.com";
652 // Confirm that after getting a dictionary, calling the browsing
653 // data remover renders it unusable. Also (in calling
654 // ForceSdchDictionaryLoad()) servers as a smoke test for SDCH.
655 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, BrowsingDataRemover) {
656 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
658 // Confirm browsing data remover without removing the cache leaves
659 // SDCH alone.
660 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_ALL &
661 ~BrowsingDataRemover::REMOVE_CACHE);
662 bool sdch_encoding_used = false;
663 ASSERT_TRUE(GetData(&sdch_encoding_used));
664 EXPECT_TRUE(sdch_encoding_used);
666 // Confirm browsing data remover removing the cache clears SDCH state.
667 BrowsingDataRemoveAndWait(BrowsingDataRemover::REMOVE_CACHE);
668 sdch_encoding_used = false;
669 ASSERT_TRUE(GetData(&sdch_encoding_used));
670 EXPECT_FALSE(sdch_encoding_used);
673 // Confirm dictionaries not visible in other profiles.
674 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, Isolation) {
675 ASSERT_TRUE(ForceSdchDictionaryLoad(browser()));
676 ASSERT_TRUE(SetupSecondBrowser());
677 ASSERT_TRUE(SetupIncognitoBrowser());
679 // Data fetches from incognito or separate profiles should not be SDCH
680 // encoded.
681 bool sdch_encoding_used = true;
682 EXPECT_TRUE(
683 GetDataDetailed(incognito_browser()->profile()->GetRequestContext(),
684 &sdch_encoding_used));
685 EXPECT_FALSE(sdch_encoding_used);
687 sdch_encoding_used = true;
688 EXPECT_TRUE(GetDataDetailed(
689 second_browser()->profile()->GetRequestContext(), &sdch_encoding_used));
690 EXPECT_FALSE(sdch_encoding_used);
693 // Confirm a dictionary loaded in incognito isn't visible in the main profile.
694 IN_PROC_BROWSER_TEST_F(SdchBrowserTest, ReverseIsolation) {
695 ASSERT_TRUE(SetupIncognitoBrowser());
696 ASSERT_TRUE(ForceSdchDictionaryLoad(incognito_browser()));
698 // Data fetches on main browser should not be SDCH encoded.
699 bool sdch_encoding_used = true;
700 ASSERT_TRUE(GetData(&sdch_encoding_used));
701 EXPECT_FALSE(sdch_encoding_used);
704 } // namespace