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

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

Issue 13270005: Display DNS probe results. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 #include "base/bind.h"
6 #include "base/memory/scoped_ptr.h"
7 #include "base/message_loop.h"
8 #include "base/path_service.h"
9 #include "base/threading/thread_restrictions.h"
10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/google/google_util.h"
12 #include "chrome/browser/io_thread.h"
13 #include "chrome/browser/net/dns_probe_test_util.h"
14 #include "chrome/browser/net/net_error_tab_helper.h"
15 #include "chrome/browser/net/url_request_mock_util.h"
16 #include "chrome/browser/ui/browser.h"
17 #include "chrome/browser/ui/tabs/tab_strip_model.h"
18 #include "chrome/common/chrome_paths.h"
19 #include "chrome/common/net/net_error_info.h"
20 #include "chrome/test/base/in_process_browser_test.h"
21 #include "chrome/test/base/ui_test_utils.h"
22 #include "content/public/browser/browser_thread.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/test/browser_test_utils.h"
25 #include "content/test/net/url_request_failed_job.h"
26 #include "content/test/net/url_request_mock_http_job.h"
27 #include "net/base/net_errors.h"
28 #include "net/dns/dns_test_util.h"
29 #include "net/url_request/url_request_filter.h"
30 #include "net/url_request/url_request_job.h"
31 #include "net/url_request/url_request_job_factory.h"
32
33 using base::Bind;
34 using base::Callback;
35 using base::Closure;
36 using base::ConstRef;
37 using base::FilePath;
38 using base::MessageLoop;
39 using base::Unretained;
40 using chrome_common_net::DnsProbeStatus;
41 using content::BrowserThread;
42 using content::URLRequestFailedJob;
43 using content::URLRequestMockHTTPJob;
44 using content::WebContents;
45 using google_util::LinkDoctorBaseURL;
46 using net::MockDnsClientRule;
47 using net::NetworkDelegate;
48 using net::URLRequest;
49 using net::URLRequestFilter;
50 using net::URLRequestJob;
51 using net::URLRequestJobFactory;
52 using ui_test_utils::NavigateToURL;
53 using ui_test_utils::NavigateToURLBlockUntilNavigationsComplete;
54
55 namespace chrome_browser_net {
56
57 namespace {
58
59 // Wraps DnsProbeService and delays callbacks until someone calls
60 // CallDelayedCallbacks. This allows the DnsProbeBrowserTest to enforce a
61 // stricter ordering of events.
62 class DelayingDnsProbeService : public DnsProbeService {
63 public:
64 DelayingDnsProbeService() {}
65
66 virtual ~DelayingDnsProbeService() {
67 EXPECT_TRUE(delayed_probes_.empty());
68 }
69
70 virtual void ProbeDns(const ProbeCallback& callback) OVERRIDE {
71 delayed_probes_.push_back(callback);
72 }
73
74 void StartDelayedProbes() {
75 std::vector<ProbeCallback> probes;
76 probes.swap(delayed_probes_);
77
78 for (std::vector<ProbeCallback>::const_iterator i = probes.begin();
79 i != probes.end(); ++i) {
80 DnsProbeService::ProbeDns(*i);
81 }
82 }
83
84 int delayed_probe_count() const { return delayed_probes_.size(); }
mmenke 2013/07/12 20:09:00 Suggest verifying this and StartDelayedProbes are
Deprecated (see juliatuttle) 2013/07/12 20:55:55 Done.
85
86 private:
87 std::vector<ProbeCallback> delayed_probes_;
88 };
89
90 FilePath GetMockLinkDoctorFilePath() {
91 FilePath root_http;
92 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
93 return root_http.AppendASCII("mock-link-doctor.html");
94 }
95
96 class BrokenLinkDoctorProtocolHandler
mmenke 2013/07/12 20:09:00 Since this cal also handle non-broken link doctors
Deprecated (see juliatuttle) 2013/07/12 20:55:55 BreakableLinkDoctorProtocolHandler :)
97 : public URLRequestJobFactory::ProtocolHandler {
98 public:
99 explicit BrokenLinkDoctorProtocolHandler(
100 const FilePath& mock_link_doctor_file_path)
101 : mock_link_doctor_file_path_(mock_link_doctor_file_path),
102 net_error_(net::OK) {}
103
104 virtual ~BrokenLinkDoctorProtocolHandler() {}
105
106 virtual URLRequestJob* MaybeCreateJob(
107 URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE {
108 if (net_error_ != net::OK) {
109 return new URLRequestFailedJob(request, network_delegate, net_error_);
110 } else {
111 return new URLRequestMockHTTPJob(
112 request, network_delegate, mock_link_doctor_file_path_);
113 }
114 }
115
116 void set_net_error(int net_error) { net_error_ = net_error; }
117
118 private:
119 const FilePath mock_link_doctor_file_path_;
120 int net_error_;
121 };
122
123 class DnsProbeBrowserTestIOThreadHelper {
124 public:
125 DnsProbeBrowserTestIOThreadHelper();
126
127 void SetUpOnIOThread(IOThread* io_thread);
128 void CleanUpOnIOThreadAndDeleteHelper();
129
130 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result,
131 MockDnsClientRule::Result public_good_result);
132 void SetLinkDoctorNetError(int link_doctor_net_error);
133 void StartDelayedProbes(int expected_delayed_probe_count);
134
135 private:
136 IOThread* io_thread_;
137 DnsProbeService* original_dns_probe_service_;
138 DelayingDnsProbeService* delaying_dns_probe_service_;
139 BrokenLinkDoctorProtocolHandler* protocol_handler_;
140 FilePath mock_link_doctor_file_path_;
141 };
142
143 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper()
144 : io_thread_(NULL),
145 original_dns_probe_service_(NULL),
146 delaying_dns_probe_service_(NULL),
147 protocol_handler_(NULL),
148 mock_link_doctor_file_path_(GetMockLinkDoctorFilePath()) {}
149
150 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) {
151 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
152 CHECK(io_thread);
153 CHECK(!io_thread_);
154 CHECK(!original_dns_probe_service_);
155 CHECK(!delaying_dns_probe_service_);
156 CHECK(!protocol_handler_);
157
158 io_thread_ = io_thread;
159
160 delaying_dns_probe_service_ = new DelayingDnsProbeService();
161
162 IOThread::Globals* globals = io_thread_->globals();
163 original_dns_probe_service_ = globals->dns_probe_service.release();
164 globals->dns_probe_service.reset(delaying_dns_probe_service_);
165
166 URLRequestFailedJob::AddUrlHandler();
167
168 scoped_ptr<URLRequestJobFactory::ProtocolHandler> protocol_handler(
169 new BrokenLinkDoctorProtocolHandler(mock_link_doctor_file_path_));
170 protocol_handler_ =
171 static_cast<BrokenLinkDoctorProtocolHandler*>(protocol_handler.get());
172 const GURL link_doctor_base_url = LinkDoctorBaseURL();
173 const std::string link_doctor_host = link_doctor_base_url.host();
174 URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
175 "http", link_doctor_host, protocol_handler.Pass());
176 }
177
178 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper() {
179 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
180
181 URLRequestFilter::GetInstance()->ClearHandlers();
182
183 IOThread::Globals* globals = io_thread_->globals();
184 scoped_ptr<DnsProbeService> delaying_dns_probe_service(
185 globals->dns_probe_service.release());
186 globals->dns_probe_service.reset(original_dns_probe_service_);
187
188 CHECK_EQ(delaying_dns_probe_service_, delaying_dns_probe_service.get());
189
190 delete this;
191 }
192
193 void DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules(
194 MockDnsClientRule::Result system_result,
195 MockDnsClientRule::Result public_result) {
196 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
197
198 DnsProbeService* service = io_thread_->globals()->dns_probe_service.get();
199 service->SetSystemClientForTesting(
200 CreateMockDnsClientForProbes(system_result));
201 service->SetPublicClientForTesting(
202 CreateMockDnsClientForProbes(public_result));
203 }
204
205 void DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError(
206 int link_doctor_net_error) {
207 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
208
209 protocol_handler_->set_net_error(link_doctor_net_error);
210 }
211
212 void DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes(
213 int expected_delayed_probe_count) {
214 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
215
216 CHECK(delaying_dns_probe_service_);
217
218 int actual_delayed_probe_count =
219 delaying_dns_probe_service_->delayed_probe_count();
220 EXPECT_EQ(expected_delayed_probe_count, actual_delayed_probe_count);
221
222 delaying_dns_probe_service_->StartDelayedProbes();
223 }
224
225 class DnsProbeBrowserTest : public InProcessBrowserTest {
226 public:
227 DnsProbeBrowserTest();
228
229 virtual void SetUpOnMainThread() OVERRIDE;
230 virtual void CleanUpOnMainThread() OVERRIDE;
231
232 protected:
233 void SetLinkDoctorBroken(bool broken);
234 void SetMockDnsClientRules(MockDnsClientRule::Result system_result,
235 MockDnsClientRule::Result public_result);
236 void NavigateToDnsError();
237 void NavigateToOtherError();
238
239 void StartDelayedProbes(int expected_delayed_probe_count);
240 DnsProbeStatus WaitForSentStatus();
241 int dns_probe_status_count() const { return dns_probe_status_count_; }
242
243 std::string Title();
244 bool PageContains(const std::string& expected);
245
246 private:
247 void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status);
248
249 DnsProbeBrowserTestIOThreadHelper* helper_;
250
251 bool awaiting_dns_probe_status_;
252 int dns_probe_status_count_;
253 std::list<DnsProbeStatus> dns_probe_statuses_;
mmenke 2013/07/12 20:09:00 Think it's worth commenting on this one.
Deprecated (see juliatuttle) 2013/07/12 20:55:55 Done.
254 };
255
256 DnsProbeBrowserTest::DnsProbeBrowserTest()
257 : helper_(new DnsProbeBrowserTestIOThreadHelper()),
258 awaiting_dns_probe_status_(false),
259 dns_probe_status_count_(0) {
260 }
261
262 void DnsProbeBrowserTest::SetUpOnMainThread() {
263 NetErrorTabHelper::set_state_for_testing(
264 NetErrorTabHelper::TESTING_FORCE_ENABLED);
265
266 BrowserThread::PostTask(
267 BrowserThread::IO, FROM_HERE,
268 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread,
269 Unretained(helper_),
270 g_browser_process->io_thread()));
271
272 NetErrorTabHelper* tab_helper = NetErrorTabHelper::FromWebContents(
273 browser()->tab_strip_model()->GetActiveWebContents());
274 tab_helper->set_dns_probe_status_snoop_callback_for_testing(Bind(
275 &DnsProbeBrowserTest::OnDnsProbeStatusSent,
276 Unretained(this)));
277 }
278
279 void DnsProbeBrowserTest::CleanUpOnMainThread() {
280 BrowserThread::PostTask(
281 BrowserThread::IO, FROM_HERE,
282 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper,
283 Unretained(helper_)));
284
285 NetErrorTabHelper::set_state_for_testing(
286 NetErrorTabHelper::TESTING_DEFAULT);
287 }
288
289 void DnsProbeBrowserTest::SetLinkDoctorBroken(bool broken) {
290 int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK;
291
292 BrowserThread::PostTask(
293 BrowserThread::IO, FROM_HERE,
294 Bind(&DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError,
295 Unretained(helper_),
296 net_error));
297 }
298
299 // These two functions wait for two navigations because Link Doctor loads two
300 // pages: a blank page, so the user stops seeing the previous page, and then
301 // either the Link Doctor page or a regular error page. We want to wait for
302 // the error page, so we wait for both loads to finish.
303
304 void DnsProbeBrowserTest::NavigateToDnsError() {
305 NavigateToURLBlockUntilNavigationsComplete(
306 browser(),
307 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
308 2);
309 }
310
311 void DnsProbeBrowserTest::NavigateToOtherError() {
312 NavigateToURLBlockUntilNavigationsComplete(
313 browser(),
314 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED),
315 2);
316 }
317
318 void DnsProbeBrowserTest::SetMockDnsClientRules(
319 MockDnsClientRule::Result system_result,
320 MockDnsClientRule::Result public_result) {
321 BrowserThread::PostTask(
322 BrowserThread::IO, FROM_HERE,
323 Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules,
324 Unretained(helper_),
325 system_result,
326 public_result));
327 }
328
329 void DnsProbeBrowserTest::StartDelayedProbes(
330 int expected_delayed_probe_count) {
331 BrowserThread::PostTask(
332 BrowserThread::IO, FROM_HERE,
333 Bind(&DnsProbeBrowserTestIOThreadHelper::StartDelayedProbes,
334 Unretained(helper_),
335 expected_delayed_probe_count));
336 }
337
338 DnsProbeStatus DnsProbeBrowserTest::WaitForSentStatus() {
339 CHECK(!awaiting_dns_probe_status_);
340 while (dns_probe_statuses_.empty()) {
341 awaiting_dns_probe_status_ = true;
342 MessageLoop::current()->Run();
343 awaiting_dns_probe_status_ = false;
344 }
345
346 CHECK(!dns_probe_statuses_.empty());
347 DnsProbeStatus status = dns_probe_statuses_.front();
348 dns_probe_statuses_.pop_front();
349 return status;
350 }
351
352 // Check title by roundtripping to renderer, to make sure any probe results
353 // sent before this have been applied.
354 std::string DnsProbeBrowserTest::Title() {
355 std::string title;
356
357 WebContents* contents =
358 browser()->tab_strip_model()->GetActiveWebContents();
359
360 bool rv = content::ExecuteScriptAndExtractString(
361 contents,
362 "domAutomationController.send(document.title);",
363 &title);
364 if (!rv)
365 return "";
366
367 return title;
368 }
369
370 // Check text by roundtripping to renderer, to make sure any probe results
371 // sent before this have been applied.
372 bool DnsProbeBrowserTest::PageContains(const std::string& expected) {
373 std::string text_content;
374
375 bool rv = content::ExecuteScriptAndExtractString(
376 browser()->tab_strip_model()->GetActiveWebContents(),
377 "domAutomationController.send(document.body.textContent);",
378 &text_content);
379 if (!rv)
380 return false;
381
382 return text_content.find(expected) != std::string::npos;
383 }
384
385 void DnsProbeBrowserTest::OnDnsProbeStatusSent(
386 DnsProbeStatus dns_probe_status) {
387 dns_probe_statuses_.push_back(dns_probe_status);
388
mmenke 2013/07/12 20:09:00 optional nit: Think this linebreak makes more sen
Deprecated (see juliatuttle) 2013/07/12 20:55:55 Done.
389 dns_probe_status_count_++;
390 if (awaiting_dns_probe_status_)
391 MessageLoop::current()->Quit();
392 }
393
394 // Make sure probes don't break non-DNS error pages when Link Doctor loads.
395 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithWorkingLinkDoctor) {
396 SetLinkDoctorBroken(false);
397
398 NavigateToOtherError();
399 EXPECT_EQ("Mock Link Doctor", Title());
400
401 EXPECT_EQ(0, dns_probe_status_count());
402 }
403
404 // Make sure probes don't break non-DNS error pages when Link Doctor doesn't
405 // load.
406 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithBrokenLinkDoctor) {
407 SetLinkDoctorBroken(true);
408
409 NavigateToOtherError();
410 EXPECT_TRUE(PageContains("CONNECTION_REFUSED"));
411
412 EXPECT_EQ(0, dns_probe_status_count());
413 }
414
415 // Make sure probes don't break DNS error pages when Link doctor loads.
416 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
417 NxdomainProbeResultWithWorkingLinkDoctor) {
418 SetLinkDoctorBroken(false);
419 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK);
420
421 NavigateToDnsError();
422 EXPECT_EQ("Mock Link Doctor", Title());
423
424 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
425 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
426 EXPECT_EQ(2, dns_probe_status_count());
427 EXPECT_EQ("Mock Link Doctor", Title());
428
429 StartDelayedProbes(1);
430
431 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN,
432 WaitForSentStatus());
433 EXPECT_EQ(3, dns_probe_status_count());
434 EXPECT_EQ("Mock Link Doctor", Title());
435 }
436
437 // Make sure probes update DNS error page properly when they're supposed to.
438 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest,
439 NoInternetProbeResultWithBrokenLinkDoctor) {
440 SetLinkDoctorBroken(true);
441 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
442 MockDnsClientRule::TIMEOUT);
443
444 NavigateToDnsError();
445
446 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
447 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
448
449 // PageContains runs the RunLoop, so make sure nothing hairy happens.
450 EXPECT_EQ(2, dns_probe_status_count());
451 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED"));
452 EXPECT_EQ(2, dns_probe_status_count());
453
454 StartDelayedProbes(1);
455
456 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET,
457 WaitForSentStatus());
458
459 // PageContains runs the RunLoop, so make sure nothing hairy happens.
460 EXPECT_EQ(3, dns_probe_status_count());
461 EXPECT_TRUE(PageContains("DNS_PROBE_FINISHED_NO_INTERNET"));
462 EXPECT_EQ(3, dns_probe_status_count());
463 }
464
465 // Double-check to make sure sync failures don't explode.
466 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, SyncFailureWithBrokenLinkDoctor) {
467 SetLinkDoctorBroken(true);
468 SetMockDnsClientRules(MockDnsClientRule::FAIL_SYNC,
469 MockDnsClientRule::FAIL_SYNC);
470
471 NavigateToDnsError();
472
473 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
474 EXPECT_EQ(chrome_common_net::DNS_PROBE_STARTED, WaitForSentStatus());
475
476 // PageContains runs the RunLoop, so make sure nothing hairy happens.
477 EXPECT_EQ(2, dns_probe_status_count());
478 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED"));
479 EXPECT_EQ(2, dns_probe_status_count());
480
481 StartDelayedProbes(1);
482
483 EXPECT_EQ(chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN,
484 WaitForSentStatus());
485
486 // PageContains runs the RunLoop, so make sure nothing hairy happens.
487 EXPECT_EQ(3, dns_probe_status_count());
488 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED"));
489 EXPECT_EQ(3, dns_probe_status_count());
490 }
491
492 // Make sure probes don't run for subframe DNS errors.
493 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) {
494 SetLinkDoctorBroken(false);
495
496 const FilePath::CharType kIframeDnsErrorHtmlName[] =
497 FILE_PATH_LITERAL("iframe_dns_error.html");
498
499 NavigateToURL(
500 browser(),
501 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName)));
502
503 // By the time NavigateToURL returns, the browser will have seen the failed
504 // provisional load. If a probe was started (or considered but not run),
505 // then the NetErrorTabHelper would have sent a NetErrorInfo message. Thus,
506 // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't)
507 // start a probe for this DNS error.
508 EXPECT_EQ(0, dns_probe_status_count());
509 }
510
511 // Make sure browser sends NOT_RUN properly when probes are disabled.
512 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) {
513 NetErrorTabHelper::set_state_for_testing(
514 NetErrorTabHelper::TESTING_FORCE_DISABLED);
515
516 SetLinkDoctorBroken(true);
517 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
518 MockDnsClientRule::TIMEOUT);
519
520 NavigateToDnsError();
521
522 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, WaitForSentStatus());
523 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, WaitForSentStatus());
524
525 // PageContains runs the RunLoop, so make sure nothing hairy happens.
526 EXPECT_EQ(2, dns_probe_status_count());
527 EXPECT_TRUE(PageContains("NAME_NOT_RESOLVED"));
528 EXPECT_EQ(2, dns_probe_status_count());
529 }
530
531 } // namespace
532
533 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698