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 BrokenLinkDoctorProtocolHandlerDelegate { | |
66 public: | |
67 virtual int link_doctor_net_error() const = 0; | |
mmenke
2013/06/24 16:20:00
nit: Virtual functions shouldn't be named this wa
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Done.
| |
68 }; | |
69 | |
70 class BrokenLinkDoctorProtocolHandler | |
71 : public URLRequestJobFactory::ProtocolHandler { | |
72 public: | |
73 explicit BrokenLinkDoctorProtocolHandler( | |
mmenke
2013/06/24 16:20:00
nit: Explicit not needed (Unless you get rid of t
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Done.
| |
74 FilePath mock_link_doctor_file_path, | |
75 BrokenLinkDoctorProtocolHandlerDelegate* delegate) | |
76 : mock_link_doctor_file_path_(mock_link_doctor_file_path), | |
77 delegate_(delegate) {} | |
78 | |
79 virtual URLRequestJob* MaybeCreateJob( | |
80 URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE { | |
81 int net_error = delegate_->link_doctor_net_error(); | |
82 if (net_error != net::OK) { | |
83 return new URLRequestFailedJob(request, network_delegate, net_error); | |
84 } else { | |
85 return new URLRequestMockHTTPJob( | |
86 request, network_delegate, mock_link_doctor_file_path_); | |
87 } | |
88 } | |
89 | |
90 private: | |
91 const FilePath mock_link_doctor_file_path_; | |
92 const BrokenLinkDoctorProtocolHandlerDelegate* delegate_; | |
93 }; | |
94 | |
95 class DnsProbeBrowserTestIOThreadHelper | |
96 : public BrokenLinkDoctorProtocolHandlerDelegate { | |
97 public: | |
98 DnsProbeBrowserTestIOThreadHelper(); | |
99 virtual ~DnsProbeBrowserTestIOThreadHelper() {} | |
100 | |
101 void SetUpOnIOThread(IOThread* io_thread); | |
102 void CleanUpOnIOThreadAndDeleteHelper(); | |
103 | |
104 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result, | |
105 MockDnsClientRule::Result public_good_result); | |
106 | |
107 virtual int link_doctor_net_error() const OVERRIDE { | |
108 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
109 return link_doctor_net_error_; | |
110 } | |
111 | |
112 void set_link_doctor_net_error(int link_doctor_net_error) { | |
113 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
114 link_doctor_net_error_ = link_doctor_net_error; | |
115 } | |
116 | |
117 private: | |
118 IOThread* io_thread_; | |
119 FilePath mock_link_doctor_file_path_; | |
120 int link_doctor_net_error_; | |
121 }; | |
122 | |
123 DnsProbeBrowserTestIOThreadHelper::DnsProbeBrowserTestIOThreadHelper() | |
124 : io_thread_(NULL), | |
125 mock_link_doctor_file_path_(GetMockLinkDoctorFilePath()), | |
126 link_doctor_net_error_(net::OK) {} | |
127 | |
128 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(IOThread* io_thread) { | |
129 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
mmenke
2013/06/24 16:20:00
Should use CHECKS (Or asserts) in tests, since we
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Done. Do any of the DCHECKs in the non-test code
mmenke
2013/06/25 17:40:26
My general feeling is that production code should
| |
130 DCHECK(io_thread); | |
131 DCHECK(!io_thread_); | |
132 | |
133 io_thread_ = io_thread; | |
134 | |
135 URLRequestFailedJob::AddUrlHandler(); | |
136 | |
137 const GURL link_doctor_base_url = LinkDoctorBaseURL(); | |
138 const std::string link_doctor_host = link_doctor_base_url.host(); | |
139 scoped_ptr<URLRequestJobFactory::ProtocolHandler> link_doctor_handler( | |
140 new BrokenLinkDoctorProtocolHandler(mock_link_doctor_file_path_, this)); | |
141 URLRequestFilter::GetInstance()->AddHostnameProtocolHandler( | |
142 "http", link_doctor_host, link_doctor_handler.Pass()); | |
143 } | |
144 | |
145 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper() { | |
146 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); | |
147 DCHECK(io_thread_); | |
148 | |
149 URLRequestFilter::GetInstance()->ClearHandlers(); | |
150 | |
151 delete this; | |
152 } | |
153 | |
154 void DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules( | |
155 MockDnsClientRule::Result system_good_result, | |
156 MockDnsClientRule::Result public_good_result) { | |
157 DnsProbeService* service = io_thread_->globals()->dns_probe_service.get(); | |
158 service->SetSystemClientForTesting( | |
159 CreateMockDnsClientForProbes(system_good_result)); | |
160 service->SetPublicClientForTesting( | |
161 CreateMockDnsClientForProbes(public_good_result)); | |
162 } | |
163 | |
164 class DnsProbeBrowserTest : public InProcessBrowserTest { | |
165 public: | |
166 DnsProbeBrowserTest(); | |
167 | |
168 virtual void SetUpOnMainThread() OVERRIDE; | |
169 virtual void CleanUpOnMainThread() OVERRIDE; | |
170 | |
171 protected: | |
172 void SetLinkDoctorBroken(bool broken); | |
173 void SetMockDnsClientRules(MockDnsClientRule::Result system_good_result, | |
174 MockDnsClientRule::Result public_good_result); | |
175 void NavigateToDnsError(); | |
176 void NavigateToOtherError(); | |
177 | |
178 void WaitForNetErrorInfo(); | |
179 | |
180 bool TitleIs(const std::string& expected); | |
181 bool PageContains(const std::string& expected); | |
182 | |
183 DnsProbeStatus last_dns_probe_status() const { | |
184 return last_dns_probe_status_; | |
185 } | |
186 int net_error_info_count() const { return net_error_info_count_; } | |
187 | |
188 private: | |
189 void OnNetErrorInfoSent(DnsProbeStatus dns_probe_status); | |
190 | |
191 DnsProbeBrowserTestIOThreadHelper* helper_; | |
192 | |
193 bool awaiting_net_error_info_; | |
194 bool received_net_error_info_; | |
195 int net_error_info_count_; | |
mmenke
2013/06/24 16:20:00
We're actually waiting / monitoring dns_probe_stat
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Yeah, but what we receive is a NetErrorInfo messag
| |
196 DnsProbeStatus last_dns_probe_status_; | |
197 }; | |
198 | |
199 DnsProbeBrowserTest::DnsProbeBrowserTest() | |
200 : helper_(new DnsProbeBrowserTestIOThreadHelper()), | |
201 awaiting_net_error_info_(false), | |
202 received_net_error_info_(false), | |
203 net_error_info_count_(0) { | |
204 } | |
205 | |
206 void DnsProbeBrowserTest::SetUpOnMainThread() { | |
207 NetErrorTabHelper::set_state_for_testing( | |
208 NetErrorTabHelper::TESTING_FORCE_ENABLED); | |
209 | |
210 DCHECK(helper_); | |
211 BrowserThread::PostTask( | |
212 BrowserThread::IO, FROM_HERE, | |
213 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread, | |
214 Unretained(helper_), | |
215 g_browser_process->io_thread())); | |
216 | |
217 NetErrorTabHelper* tab_helper = NetErrorTabHelper::FromWebContents( | |
218 browser()->tab_strip_model()->GetActiveWebContents()); | |
219 tab_helper->set_net_error_info_snoop_callback_for_testing(Bind( | |
220 &DnsProbeBrowserTest::OnNetErrorInfoSent, | |
221 Unretained(this))); | |
222 } | |
223 | |
224 void DnsProbeBrowserTest::CleanUpOnMainThread() { | |
225 DCHECK(helper_); | |
226 BrowserThread::PostTask( | |
227 BrowserThread::IO, FROM_HERE, | |
228 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThreadAndDeleteHelper, | |
229 Unretained(helper_))); | |
230 | |
231 NetErrorTabHelper::set_state_for_testing( | |
232 NetErrorTabHelper::TESTING_DEFAULT); | |
233 } | |
234 | |
235 void DnsProbeBrowserTest::SetLinkDoctorBroken(bool broken) { | |
236 int net_error = broken ? net::ERR_NAME_NOT_RESOLVED : net::OK; | |
237 | |
238 BrowserThread::PostTask( | |
239 BrowserThread::IO, FROM_HERE, | |
240 Bind(&DnsProbeBrowserTestIOThreadHelper::set_link_doctor_net_error, | |
241 Unretained(helper_), | |
242 net_error)); | |
243 } | |
244 | |
245 // These two functions wait for two navigations because Link Doctor loads two | |
246 // pages: a blank page, so the user stops seeing the previous page, and then | |
247 // either the Link Doctor page or a regular error page. We want to wait for | |
248 // the error page, so we wait for both loads to finish. | |
249 | |
250 void DnsProbeBrowserTest::NavigateToDnsError() { | |
251 NavigateToURLBlockUntilNavigationsComplete( | |
252 browser(), | |
253 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED), | |
254 2); | |
255 } | |
256 | |
257 void DnsProbeBrowserTest::NavigateToOtherError() { | |
258 NavigateToURLBlockUntilNavigationsComplete( | |
259 browser(), | |
260 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED), | |
261 2); | |
262 } | |
263 | |
264 void DnsProbeBrowserTest::SetMockDnsClientRules( | |
265 MockDnsClientRule::Result system_good_result, | |
266 MockDnsClientRule::Result public_good_result) { | |
267 BrowserThread::PostTask( | |
268 BrowserThread::IO, FROM_HERE, | |
269 Bind(&DnsProbeBrowserTestIOThreadHelper::SetMockDnsClientRules, | |
270 Unretained(helper_), | |
271 system_good_result, | |
272 public_good_result)); | |
273 } | |
274 | |
275 void DnsProbeBrowserTest::WaitForNetErrorInfo() { | |
276 DCHECK(!awaiting_net_error_info_); | |
277 while (!received_net_error_info_) { | |
278 awaiting_net_error_info_ = true; | |
279 MessageLoop::current()->Run(); | |
280 awaiting_net_error_info_ = false; | |
281 } | |
282 } | |
283 | |
284 // Check title by roundtripping to renderer, to make sure any probe results | |
285 // sent before this have been applied. | |
mmenke
2013/06/24 16:20:00
Did you consider the title watcher? The one conce
Deprecated (see juliatuttle)
2013/06/25 16:45:04
I did; I like this better, but I'll change it if y
mmenke
2013/06/26 15:48:20
I've gone back and forth on this. One one hand, i
| |
286 bool DnsProbeBrowserTest::TitleIs(const std::string& expected) { | |
287 std::string title; | |
288 | |
289 WebContents* contents = | |
290 browser()->tab_strip_model()->GetActiveWebContents(); | |
291 | |
292 bool rv = content::ExecuteScriptAndExtractString( | |
293 contents, | |
294 "domAutomationController.send(document.title);", | |
295 &title); | |
296 if (!rv) | |
297 return false; | |
298 | |
299 return title == expected; | |
300 } | |
301 | |
302 // Check text by roundtripping to renderer, to make sure any probe results | |
303 // sent before this have been applied. | |
304 bool DnsProbeBrowserTest::PageContains(const std::string& expected) { | |
305 std::string text_content; | |
306 | |
307 bool rv = content::ExecuteScriptAndExtractString( | |
308 browser()->tab_strip_model()->GetActiveWebContents(), | |
309 "domAutomationController.send(document.body.textContent);", | |
310 &text_content); | |
311 if (!rv) | |
312 return false; | |
313 | |
314 return text_content.find(expected) != std::string::npos; | |
315 } | |
316 | |
317 void DnsProbeBrowserTest::OnNetErrorInfoSent(DnsProbeStatus dns_probe_status) { | |
318 last_dns_probe_status_ = dns_probe_status; | |
319 | |
320 net_error_info_count_++; | |
321 received_net_error_info_ = true; | |
322 if (awaiting_net_error_info_) | |
323 MessageLoop::current()->Quit(); | |
324 } | |
325 | |
326 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithLinkDoctor) { | |
327 SetLinkDoctorBroken(false); | |
328 | |
329 NavigateToOtherError(); | |
330 EXPECT_TRUE(TitleIs("Mock Link Doctor")); | |
331 | |
332 EXPECT_EQ(0, net_error_info_count()); | |
333 } | |
334 | |
335 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithoutLinkDoctor) { | |
336 SetLinkDoctorBroken(true); | |
337 | |
338 NavigateToOtherError(); | |
339 EXPECT_TRUE(PageContains("CONNECTION_REFUSED")); | |
340 | |
341 EXPECT_EQ(0, net_error_info_count()); | |
342 } | |
343 | |
344 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NxdomainWithLinkDoctor) { | |
345 SetLinkDoctorBroken(false); | |
346 SetMockDnsClientRules(MockDnsClientRule::OK, MockDnsClientRule::OK); | |
347 | |
348 NavigateToDnsError(); | |
349 EXPECT_TRUE(TitleIs("Mock Link Doctor")); | |
350 } | |
351 | |
352 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoInternetWithoutLinkDoctor) { | |
353 SetLinkDoctorBroken(true); | |
354 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, | |
355 MockDnsClientRule::TIMEOUT); | |
356 | |
357 NavigateToDnsError(); | |
358 | |
359 bool seen_finished = false; | |
360 bool page_updated = false; | |
361 | |
362 // Wait for zero or more DNS_PROBE_STARTED followed by one or more | |
363 // DNS_PROBE_FINISHED_NO_INTERNET. After each of the latter, check to see if | |
364 // the error page has been updated. | |
365 while (!page_updated) { | |
366 WaitForNetErrorInfo(); | |
367 switch (last_dns_probe_status()) { | |
368 case chrome_common_net::DNS_PROBE_STARTED: | |
369 ASSERT_FALSE(seen_finished); | |
370 break; | |
371 case chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET: | |
372 seen_finished = true; | |
373 if (PageContains("DNS_PROBE_FINISHED_NO_INTERNET")) | |
374 page_updated = true; | |
375 break; | |
376 default: | |
377 NOTREACHED(); | |
378 } | |
379 } | |
380 } | |
381 | |
382 static const FilePath::CharType kIframeDnsErrorHtmlName[] = | |
383 FILE_PATH_LITERAL("iframe_dns_error.html"); | |
mmenke
2013/06/24 16:20:00
Since this is only used in one test body, suggest
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Done.
| |
384 | |
385 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) { | |
386 SetLinkDoctorBroken(false); | |
387 | |
388 NavigateToURL( | |
389 browser(), | |
390 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName))); | |
391 EXPECT_EQ(0, net_error_info_count()); | |
mmenke
2013/06/24 16:20:00
Think it's worth mentioning why these two tests wo
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Added to NoProbeInSubFrame. ProbesDisabled explic
mmenke
2013/06/25 17:40:26
You're right, was still thinking of the pre-callba
| |
392 } | |
393 | |
394 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, ProbesDisabled) { | |
395 NetErrorTabHelper::set_state_for_testing( | |
396 NetErrorTabHelper::TESTING_FORCE_DISABLED); | |
397 | |
398 SetLinkDoctorBroken(true); | |
399 SetMockDnsClientRules(MockDnsClientRule::TIMEOUT, | |
400 MockDnsClientRule::TIMEOUT); | |
401 | |
402 NavigateToDnsError(); | |
403 | |
404 WaitForNetErrorInfo(); | |
405 EXPECT_EQ(chrome_common_net::DNS_PROBE_NOT_RUN, last_dns_probe_status()); | |
406 } | |
mmenke
2013/06/24 16:20:00
Suggest a test with the link doctor diabled via pr
mmenke
2013/06/24 16:20:00
Suggest a test with dns failing synchronously, jus
Deprecated (see juliatuttle)
2013/06/25 16:45:04
That's tricky; we're currently gated on a field tr
Deprecated (see juliatuttle)
2013/06/25 16:45:04
Done.
mmenke
2013/06/25 17:40:26
The issue I'm concerned about isn't what we're gat
| |
407 | |
408 } // namespace | |
409 | |
410 } // namespace chrome_browser_net | |
OLD | NEW |