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

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: Fix moar nits Created 7 years, 6 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 FilePath GetMockLinkDoctorFilePath() {
60 FilePath root_http;
61 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
62 return root_http.AppendASCII("mock-link-doctor.html");
63 }
64
65 class BrokenLinkDoctorProtocolHandler
66 : public URLRequestJobFactory::ProtocolHandler {
67 public:
68 explicit BrokenLinkDoctorProtocolHandler(FilePath mock_link_doctor_file_path)
mmenke 2013/06/26 15:48:20 nit: const FilePath&?
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
69 : mock_link_doctor_file_path_(mock_link_doctor_file_path),
70 net_error_(net::OK) {}
mmenke 2013/06/26 15:48:20 nit: Google style guide requires a virtual destru
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
71
72 virtual URLRequestJob* MaybeCreateJob(
73 URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE {
74 if (net_error_ != net::OK) {
75 return new URLRequestFailedJob(request, network_delegate, net_error_);
76 } else {
77 return new URLRequestMockHTTPJob(
78 request, network_delegate, mock_link_doctor_file_path_);
79 }
80 }
81
82 void set_net_error(int net_error) { net_error_ = net_error; }
83
84 private:
85 const FilePath mock_link_doctor_file_path_;
86 int net_error_;
87 };
88
89 class DnsProbeBrowserTestIOThreadHelper {
90 public:
91 DnsProbeBrowserTestIOThreadHelper();
92 virtual ~DnsProbeBrowserTestIOThreadHelper() {}
mmenke 2013/06/26 15:48:20 nit: virtual no longer needed.
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
93
94 void SetUpOnIOThread(IOThread* io_thread);
95 void CleanUpOnIOThreadAndDeleteHelper();
96
97 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result,
98 MockDnsClientRule::Result public_good_result);
99 void SetLinkDoctorNetError(int link_doctor_net_error);
100
101 private:
102 IOThread* io_thread_;
103 BrokenLinkDoctorProtocolHandler* protocol_handler_;
104 FilePath mock_link_doctor_file_path_;
105 };
106
107 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper()
108 : io_thread_(NULL),
109 protocol_handler_(NULL),
110 mock_link_doctor_file_path_(GetMockLinkDoctorFilePath()) {}
111
112 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) {
113 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
114 CHECK(io_thread);
115 CHECK(!io_thread_);
116 CHECK(!protocol_handler_);
117
118 io_thread_ = io_thread;
119 protocol_handler_ =
120 new BrokenLinkDoctorProtocolHandler(mock_link_doctor_file_path_);
121
122 URLRequestFailedJob::AddUrlHandler();
123
124 const GURL link_doctor_base_url = LinkDoctorBaseURL();
125 const std::string link_doctor_host = link_doctor_base_url.host();
126 scoped_ptr<URLRequestJobFactory::ProtocolHandler>
127 protocol_handler_scoped_ptr_(protocol_handler_);
mmenke 2013/06/26 15:48:20 protocol_handler_scoped_ptr_ -> protocol_handler_s
mmenke 2013/06/26 15:48:20 Think it's a little cleaner to always have somethi
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done, but it requires an extra cast.
128 URLRequestFilter::GetInstance()->AddHostnameProtocolHandler(
129 "http", link_doctor_host, protocol_handler_scoped_ptr_.Pass());
130 }
131
132 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper() {
133 CHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
134
135 URLRequestFilter::GetInstance()->ClearHandlers();
136
137 delete this;
138 }
139
140 void DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules(
141 MockDnsClientRule::Result system_good_result,
142 MockDnsClientRule::Result public_good_result) {
143 DnsProbeService* service = io_thread_->globals()->dns_probe_service.get();
144 service->SetSystemClientForTesting(
145 CreateMockDnsClientForProbes(system_good_result));
146 service->SetPublicClientForTesting(
147 CreateMockDnsClientForProbes(public_good_result));
148 }
149
150 void DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError(
151 int link_doctor_net_error) {
152 protocol_handler_->set_net_error(link_doctor_net_error);
153 }
154
155 class DnsProbeBrowserTest : public InProcessBrowserTest {
156 public:
157 DnsProbeBrowserTest();
158
159 virtual void SetUpOnMainThread() OVERRIDE;
160 virtual void CleanUpOnMainThread() OVERRIDE;
161
162 protected:
163 void SetLinkDoctorBroken(bool broken);
164 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result,
165 MockDnsClientRule::Result public_good_result);
mmenke 2013/06/26 15:48:20 nit: Don't need the goods.
mmenke 2013/06/26 15:48:20 nit: Indent here is a little weird.
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
166 void NavigateToDnsError();
167 void NavigateToOtherError();
168
169 void WaitForNetErrorInfo();
170
171 bool TitleIs(const std::string& expected);
172 bool PageContains(const std::string& expected);
173
174 DnsProbeStatus last_dns_probe_status() const {
175 return last_dns_probe_status_;
176 }
177 int dns_probe_status_count() const { return dns_probe_status_count_; }
178
179 private:
180 void OnDnsProbeStatusSent(DnsProbeStatus dns_probe_status);
181
182 DnsProbeBrowserTestIOThreadHelper* helper_;
183
184 bool awaiting_dns_probe_status_;
185 bool received_dns_probe_status_;
186 int dns_probe_status_count_;
187 DnsProbeStatus last_dns_probe_status_;
188 };
189
190 DnsProbeBrowserTest::DnsProbeBrowserTest()
191 : helper_(new DnsProbeBrowserTestIOThreadHelper()),
192 awaiting_dns_probe_status_(false),
193 received_dns_probe_status_(false),
194 dns_probe_status_count_(0) {
195 }
196
197 void DnsProbeBrowserTest::SetUpOnMainThread() {
198 NetErrorTabHelper::set_state_for_testing(
199 NetErrorTabHelper::TESTING_FORCE_ENABLED);
200
201 CHECK(helper_);
202 BrowserThread::PostTask(
203 BrowserThread::IO, FROM_HERE,
204 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread,
205 Unretained(helper_),
206 g_browser_process->io_thread()));
207
208 NetErrorTabHelper* tab_helper = NetErrorTabHelper::FromWebContents(
209 browser()->tab_strip_model()->GetActiveWebContents());
210 tab_helper->set_dns_probe_status_snoop_callback_for_testing(Bind(
211 &DnsProbeBrowserTest::OnDnsProbeStatusSent,
212 Unretained(this)));
213 }
214
215 void DnsProbeBrowserTest::CleanUpOnMainThread() {
216 CHECK(helper_);
217 BrowserThread::PostTask(
218 BrowserThread::IO, FROM_HERE,
219 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper,
220 Unretained(helper_)));
221
222 NetErrorTabHelper::set_state_for_testing(
223 NetErrorTabHelper::TESTING_DEFAULT);
224 }
225
226 void DnsProbeBrowserTest::SetLinkDoctorBroken(bool broken) {
227 int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK;
228
229 BrowserThread::PostTask(
230 BrowserThread::IO, FROM_HERE,
231 Bind(&DnsProbeBrowserTestIOThreadHelper::SetLinkDoctorNetError,
232 Unretained(helper_),
233 net_error));
234 }
235
236 // These two functions wait for two navigations because Link Doctor loads two
237 // pages: a blank page, so the user stops seeing the previous page, and then
238 // either the Link Doctor page or a regular error page. We want to wait for
239 // the error page, so we wait for both loads to finish.
240
241 void DnsProbeBrowserTest::NavigateToDnsError() {
242 NavigateToURLBlockUntilNavigationsComplete(
243 browser(),
244 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
245 2);
246 }
247
248 void DnsProbeBrowserTest::NavigateToOtherError() {
249 NavigateToURLBlockUntilNavigationsComplete(
250 browser(),
251 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED),
252 2);
253 }
254
255 void DnsProbeBrowserTest::SetMockDnsClientRules(
256 MockDnsClientRule::Result system_good_result,
257 MockDnsClientRule::Result public_good_result) {
mmenke 2013/06/26 15:48:20 nit: Again, don't think "good" is needed any more
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Done.
258 BrowserThread::PostTask(
259 BrowserThread::IO, FROM_HERE,
260 Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules,
261 Unretained(helper_),
262 system_good_result,
263 public_good_result));
264 }
265
266 void DnsProbeBrowserTest::WaitForNetErrorInfo() {
267 CHECK(!awaiting_dns_probe_status_);
268 while (!received_dns_probe_status_) {
269 awaiting_dns_probe_status_ = true;
270 MessageLoop::current()->Run();
271 awaiting_dns_probe_status_ = false;
272 }
273 received_dns_probe_status_ = false;
274 }
275
276 // Check title by roundtripping to renderer, to make sure any probe results
277 // sent before this have been applied.
278 bool DnsProbeBrowserTest::TitleIs(const std::string& expected) {
279 std::string title;
280
281 WebContents* contents =
282 browser()->tab_strip_model()->GetActiveWebContents();
283
284 bool rv = content::ExecuteScriptAndExtractString(
285 contents,
286 "domAutomationController.send(document.title);",
287 &title);
288 if (!rv)
289 return false;
290
291 return title == expected;
292 }
293
294 // Check text by roundtripping to renderer, to make sure any probe results
295 // sent before this have been applied.
296 bool DnsProbeBrowserTest::PageContains(const std::string& expected) {
297 std::string text_content;
298
299 bool rv = content::ExecuteScriptAndExtractString(
300 browser()->tab_strip_model()->GetActiveWebContents(),
301 "domAutomationController.send(document.body.textContent);",
302 &text_content);
303 if (!rv)
304 return false;
305
306 return text_content.find(expected) != std::string::npos;
307 }
308
309 void DnsProbeBrowserTest::OnDnsProbeStatusSent(
310 DnsProbeStatus dns_probe_status) {
311 last_dns_probe_status_ = dns_probe_status;
312
313 dns_probe_status_count_++;
314 received_dns_probe_status_ = true;
315 if (awaiting_dns_probe_status_)
316 MessageLoop::current()->Quit();
317 }
318
319 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithLinkDoctor) {
320 SetLinkDoctorBroken(false);
321
322 NavigateToOtherError();
323 EXPECT_TRUE(TitleIs("Mock Link Doctor"));
324
325 EXPECT_EQ(0, dns_probe_status_count());
326 }
327
328 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithoutLinkDoctor) {
329 SetLinkDoctorBroken(true);
330
331 NavigateToOtherError();
332 EXPECT_TRUE(PageContains("CONNECTION_REFUSED"));
333
334 EXPECT_EQ(0, dns_probe_status_count());
335 }
336
337 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NxdomainWithLinkDoctor) {
338 SetLinkDoctorBroken(false);
339 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK);
340
341 NavigateToDnsError();
342 EXPECT_TRUE(TitleIs("Mock Link Doctor"));
343 }
344
345 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoInternetWithoutLinkDoctor) {
346 SetLinkDoctorBroken(true);
347 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
348 MockDnsClientRule::TIMEOUT);
349
350 NavigateToDnsError();
351
352 bool seen_finished = false;
353 bool page_updated = false;
354
355 // Wait for zero or more DNS_PROBE_STARTED followed by one or more
356 // DNS_PROBE_FINISHED_NO_INTERNET. After each of the latter, check to see if
357 // the error page has been updated.
358 while (!page_updated) {
359 WaitForNetErrorInfo();
mmenke 2013/06/26 15:48:20 Re-entering the message loop in a loop like this i
Deprecated (see juliatuttle) 2013/06/26 22:23:56 The problem is that the loop isn't, overall, waiti
mmenke 2013/06/27 14:49:37 Ah, right...Think the simplest solution would be t
Deprecated (see juliatuttle) 2013/06/28 16:59:46 Done.
360 switch (last_dns_probe_status()) {
361 case chrome_common_net::DNS_PROBE_STARTED:
362 ASSERT_FALSE(seen_finished);
363 break;
364 case chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET:
365 seen_finished = true;
366 if (PageContains("DNS_PROBE_FINISHED_NO_INTERNET"))
mmenke 2013/06/26 15:48:20 This is needed because of the blank page before we
Deprecated (see juliatuttle) 2013/06/26 22:23:56 Hmm. How do you think I should clarify this? Bas
Deprecated (see juliatuttle) 2013/06/28 16:59:46 Obsolete.
367 page_updated = true;
368 break;
369 default:
370 NOTREACHED();
371 }
372 }
373 }
374
375 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, SyncFailureWithoutLinkDoctor) {
376 SetLinkDoctorBroken(true);
377 SetMockDnsClientRules(MockDnsClientRule::FAIL_SYNC,
378 MockDnsClientRule::FAIL_SYNC);
379
380 NavigateToDnsError();
381
382 bool seen_finished = false;
383 bool page_updated = false;
384
385 // Wait for zero or more DNS_PROBE_STARTED followed by one or more
386 // DNS_PROBE_FINISHED_NO_INTERNET. After each of the latter, check to see if
387 // the error page has been updated.
388 while (!page_updated) {
389 WaitForNetErrorInfo();
390 switch (last_dns_probe_status()) {
391 case chrome_common_net::DNS_PROBE_STARTED:
392 ASSERT_FALSE(seen_finished);
393 break;
394 case chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN:
395 seen_finished = true;
396 if (PageContains("NAME_NOT_RESOLVED"))
397 page_updated = true;
398 break;
399 default:
400 NOTREACHED();
401 }
402 }
403 }
404
405 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) {
406 SetLinkDoctorBroken(false);
407
408 const FilePath::CharType kIframeDnsErrorHtmlName[] =
409 FILE_PATH_LITERAL("iframe_dns_error.html");
410
411 NavigateToURL(
412 browser(),
413 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName)));
414
415 // By the time NavigateToURL returns, the browser will have seen the failed
416 // provisional load. If a probe was started (or considered but not run),
417 // then the NetErrorTabHelper would have sent a NetErrorInfo message. Thus,
418 // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't)
419 // start a probe for this DNS error.
420 EXPECT_EQ(0, dns_probe_status_count());
421 }
422
423 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) {
424 NetErrorTabHelper::set_state_for_testing(
425 NetErrorTabHelper::TESTING_FORCE_DISABLED);
426
427 SetLinkDoctorBroken(true);
428 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT,
429 MockDnsClientRule::TIMEOUT);
430
431 NavigateToDnsError();
432
433 WaitForNetErrorInfo();
434 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, last_dns_probe_status());
435 }
436
437 } // namespace
438
439 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698