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

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 browser test 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 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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698