OLD | NEW |
---|---|
(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) | |
69 : mock_link_doctor_file_path_(mock_link_doctor_file_path), | |
70 net_error_(net::OK) {} | |
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() {} | |
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_); | |
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); | |
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) { | |
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(); | |
360 switch (last_dns_probe_status()) { | |
mmenke
2013/06/25 17:40:27
Please indent the body of switch statements - not
Deprecated (see juliatuttle)
2013/06/26 22:23:56
Done.
| |
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")) | |
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 }} | |
mmenke
2013/06/25 17:40:27
nit: Split onto two lines.
Deprecated (see juliatuttle)
2013/06/26 22:23:56
Done.
| |
403 | |
404 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) { | |
405 SetLinkDoctorBroken(false); | |
406 | |
407 const FilePath::CharType kIframeDnsErrorHtmlName[] = | |
408 FILE_PATH_LITERAL("iframe_dns_error.html"); | |
409 | |
410 NavigateToURL( | |
411 browser(), | |
412 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName))); | |
413 | |
414 // By the time NavigateToURL returns, the browser will have seen the failed | |
415 // provisional load. If a probe was started (or considered but not run), | |
416 // then the NetErrorTabHelper would have sent a NetErrorInfo message. Thus, | |
417 // if one hasn't been sent by now, the NetErrorTabHelper has not (and won't) | |
418 // start a probe for this DNS error. | |
419 EXPECT_EQ(0, dns_probe_status_count()); | |
420 } | |
421 | |
422 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) { | |
423 NetErrorTabHelper::set_state_for_testing( | |
424 NetErrorTabHelper::TESTING_FORCE_DISABLED); | |
425 | |
426 SetLinkDoctorBroken(true); | |
427 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, | |
428 MockDnsClientRule::TIMEOUT); | |
429 | |
430 NavigateToDnsError(); | |
431 | |
432 WaitForNetErrorInfo(); | |
433 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, last_dns_probe_status()); | |
434 } | |
435 | |
436 } // namespace | |
437 | |
438 } // namespace chrome_browser_net | |
OLD | NEW |