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

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 FilePath initalization on Windows Created 7 years, 7 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 "chrome/browser/browser_process.h"
10 #include "chrome/browser/google/google_util.h"
11 #include "chrome/browser/io_thread.h"
12 #include "chrome/browser/net/net_error_tab_helper.h"
13 #include "chrome/browser/net/url_request_mock_util.h"
14 #include "chrome/browser/ui/browser.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/common/chrome_paths.h"
17 #include "chrome/common/net/net_error_info.h"
18 #include "chrome/test/base/in_process_browser_test.h"
19 #include "chrome/test/base/ui_test_utils.h"
20 #include "content/public/browser/browser_thread.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/browser_test_utils.h"
23 #include "content/test/net/url_request_failed_job.h"
24 #include "content/test/net/url_request_mock_http_job.h"
25 #include "net/base/net_errors.h"
26 #include "net/url_request/url_request_filter.h"
27 #include "net/url_request/url_request_job.h"
28 #include "net/url_request/url_request_job_factory.h"
29
30 namespace {
31
32 using base::Bind;
33 using base::Callback;
34 using base::Closure;
35 using base::ConstRef;
36 using base::FilePath;
37 using base::Unretained;
38 using chrome_browser_net::DnsProbeService;
39 using chrome_browser_net::NetErrorTabHelper;
40 using chrome_browser_net::SetUrlRequestMocksEnabled;
41 using chrome_common_net::DnsProbeStatus;
42 using content::BrowserThread;
43 using content::URLRequestFailedJob;
44 using content::URLRequestMockHTTPJob;
45 using content::WebContents;
46 using google_util::LinkDoctorBaseURL;
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 // TODO(ttuttle): Dedupe this and net/base/test_completion_callback.*.
56 class TestCompletionCallback {
57 public:
58 // TODO(ttuttle): Weak pointer instead of Unretained?
59 TestCompletionCallback()
60 : callback_(Bind(&TestCompletionCallback::DidCall, Unretained(this))),
61 waiting_(false),
62 called_(false) {
63 }
64
65 void DidCall() {
66 called_ = true;
67 if (waiting_)
68 MessageLoop::current()->Quit();
69 }
70
71 void WaitForCall() {
72 DCHECK(!waiting_);
73 while (!called_) {
74 waiting_ = true;
75 MessageLoop::current()->Run();
76 waiting_ = false;
77 }
78 called_ = false;
79 }
80
81 const Closure& callback() {
82 return callback_;
83 }
84
85 private:
86 Closure callback_;
87 bool waiting_;
88 bool called_;
89 };
90
91 class MockDnsProbeService : public DnsProbeService {
mmenke 2013/05/28 18:20:13 I'd rather use the real DnsProbeService. Also thi
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
92 public:
93 explicit MockDnsProbeService(const Closure& probe_started_callback)
94 : DnsProbeService(),
95 probe_started_callback_(probe_started_callback) {
96 }
97
98 virtual ~MockDnsProbeService() { }
99
100 virtual void ProbeDns(const CallbackType& callback) OVERRIDE {
101 callbacks_.push_back(callback);
102 BrowserThread::PostTask(
103 BrowserThread::UI, FROM_HERE, probe_started_callback_);
104 }
105
106 void CallCallbacks(DnsProbeStatus result) {
107 std::vector<CallbackType> callbacks = callbacks_;
108 callbacks_.clear();
109
110 for (std::vector<CallbackType>::const_iterator i = callbacks.begin();
111 i != callbacks.end(); ++i) {
112 i->Run(result);
113 }
114 }
115
116 int callback_count() {
117 return callbacks_.size();
118 }
119
120 private:
121 const Closure probe_started_callback_;
122 std::vector<CallbackType> callbacks_;
123 };
124
125 class DnsProbeBrowserTestIOThreadHelper {
126 public:
127 DnsProbeBrowserTestIOThreadHelper()
128 : io_thread_(NULL),
129 real_service_(NULL),
130 mock_service_(NULL),
131 link_doctor_net_error_(net::OK) {
132 }
133
134 void SetUpOnIOThread(
135 IOThread* io_thread,
136 const Closure& probe_started_callback,
137 const Closure& callback);
138 void CleanUpOnIOThread(const Closure& callback);
139
140 void SimulateProbeResult(
141 DnsProbeStatus result,
142 const Closure& callback);
143
144 int link_doctor_net_error() const {
145 return link_doctor_net_error_;
146 }
147 void set_link_doctor_net_error(int link_doctor_net_error) {
148 link_doctor_net_error_ = link_doctor_net_error;
149 }
150
151 private:
152 IOThread* io_thread_;
153 DnsProbeService* real_service_;
154 MockDnsProbeService* mock_service_;
155 int link_doctor_net_error_;
156 };
157
158 class DnsProbeBrowserTest : public InProcessBrowserTest {
159 public:
160 DnsProbeBrowserTest();
161
162 virtual void SetUpOnMainThread() OVERRIDE;
163 virtual void CleanUpOnMainThread() OVERRIDE;
164
165 protected:
mmenke 2013/05/28 18:20:13 optional: Most test fixtures don't use protected,
Deprecated (see juliatuttle) 2013/06/05 21:01:47 The test cases are implemented as subclasses, I th
166 void SetLinkDoctorBroken(bool broken);
167 void NavigateToDnsError();
168 void NavigateToOtherError();
169 void WaitForProbe();
mmenke 2013/05/28 18:20:13 I think "WaitForProbeStart" would be clearer.
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
170 void SimulateProbeResult(DnsProbeStatus result);
171
172 bool TitleContains(const std::string& expected);
173 bool PageContains(const std::string& expected);
174
175 int probe_count() const { return probe_started_count_; }
176
177 private:
178 void SetLinkDoctorNetError(int net_error);
179 void OnProbeStarted();
180
181 DnsProbeBrowserTestIOThreadHelper helper_;
182 TestCompletionCallback probe_started_callback_;
mmenke 2013/05/28 18:20:13 I think having two variables in this file called p
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Obsolete.
183 int probe_started_count_;
184 };
185
186 class BrokenLinkDoctorProtocolHandler
187 : public URLRequestJobFactory::ProtocolHandler {
188 public:
189 explicit BrokenLinkDoctorProtocolHandler(
190 DnsProbeBrowserTestIOThreadHelper* helper)
191 : helper_(helper) { }
192
193 virtual URLRequestJob* MaybeCreateJob(
194 URLRequest* request, NetworkDelegate* network_delegate) const OVERRIDE {
195 int net_error = helper_->link_doctor_net_error();
196 if (net_error != net::OK) {
197 return new URLRequestFailedJob(request, network_delegate, net_error);
198 } else {
199 FilePath file_path = GetMockLinkDoctorFilePath();
200 return new URLRequestMockHTTPJob(request, network_delegate, file_path);
201 }
202 }
203
204 private:
205 FilePath GetMockLinkDoctorFilePath() const {
206 FilePath root_http;
207 PathService::Get(chrome::DIR_TEST_DATA, &root_http);
208 return root_http.AppendASCII("mock-link-doctor.html");
209 }
210
211 const DnsProbeBrowserTestIOThreadHelper* helper_;
212 };
213
214 DnsProbeBrowserTest::DnsProbeBrowserTest()
215 : probe_started_count_(0) {
216 }
217
218 void DnsProbeBrowserTest::SetUpOnMainThread() {
219 NetErrorTabHelper::set_state_for_testing(
220 NetErrorTabHelper::TESTING_FORCE_ENABLED);
221
222 Closure on_probe_started =
223 Bind(&DnsProbeBrowserTest::OnProbeStarted, Unretained(this));
224
225 TestCompletionCallback io_thread_done;
226 BrowserThread::PostTask(
227 BrowserThread::IO, FROM_HERE,
228 Bind(&DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread,
229 Unretained(&helper_),
230 g_browser_process->io_thread(),
231 ConstRef(on_probe_started),
232 ConstRef(io_thread_done.callback())));
233 io_thread_done.WaitForCall();
mmenke 2013/05/28 18:20:13 Waiting on this does not seem to be needed. Any t
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
234 }
235
236 void DnsProbeBrowserTestIOThreadHelper::SetUpOnIOThread(
mmenke 2013/05/28 18:20:13 DnsProbeBrowserTestIOThreadHelper's functions shou
Deprecated (see juliatuttle) 2013/06/05 21:01:47 My goal was to arrange them in the order of what a
237 IOThread* io_thread,
238 const Closure& probe_started_callback,
239 const Closure& callback) {
240 DCHECK(io_thread);
241 DCHECK(!io_thread_ && !real_service_ && !mock_service_);
242
243 io_thread_ = io_thread;
244
245 mock_service_ = new MockDnsProbeService(probe_started_callback);
246
247 real_service_ = io_thread_->globals()->dns_probe_service.release();
248 io_thread_->globals()->dns_probe_service.reset(mock_service_);
249
250 // SetUrlRequestMocksEnabled clears the filter list and then adds filters
251 // for several things, including the mock link doctor. So, we call it
252 // first, then remove the handler it's added for the mock link doctor and
253 // add our own.
254 SetUrlRequestMocksEnabled(true);
255
256 URLRequestFilter* filter = URLRequestFilter::GetInstance();
257 const GURL link_doctor_base_url = LinkDoctorBaseURL();
258 const std::string host = link_doctor_base_url.host();
259 scoped_ptr<URLRequestJobFactory::ProtocolHandler> handler(
260 new BrokenLinkDoctorProtocolHandler(this));
261 filter->RemoveHostnameHandler("http", host);
262 filter->AddHostnameProtocolHandler("http", host, handler.Pass());
263
264 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
265 }
266
267 void DnsProbeBrowserTest::CleanUpOnMainThread() {
268 NetErrorTabHelper::set_state_for_testing(
269 NetErrorTabHelper::TESTING_DEFAULT);
270
271 TestCompletionCallback io_thread_done;
272 BrowserThread::PostTask(
273 BrowserThread::IO, FROM_HERE,
274 Bind(&DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThread,
275 Unretained(&helper_),
276 ConstRef(io_thread_done.callback())));
277 io_thread_done.WaitForCall();
mmenke 2013/05/28 18:20:13 Rather than waiting on a callback, how about havin
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
278 }
279
280 void DnsProbeBrowserTestIOThreadHelper::CleanUpOnIOThread(
281 const Closure& callback) {
282 DCHECK(io_thread_ && real_service_ && mock_service_);
283
284 SetUrlRequestMocksEnabled(false);
285
286 DnsProbeService* mock_service;
287 mock_service = io_thread_->globals()->dns_probe_service.release();
288 DCHECK_EQ(mock_service_, mock_service);
289 io_thread_->globals()->dns_probe_service.reset(real_service_);
290 real_service_ = NULL;
291
292 delete mock_service_;
293 mock_service_ = NULL;
294
295 io_thread_ = NULL;
296
297 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
298 }
299
300 void DnsProbeBrowserTest::SetLinkDoctorBroken(bool broken) {
301 SetLinkDoctorNetError(broken ? net::ERR_NAME_NOT_RESOLVED : net::OK);
302 }
303
304 // These two functions wait for two navigations because Link Doctor loads two
305 // pages: a blank page, so the user stops seeing the previous page, and then
306 // either the Link Doctor page or a regular error page. We want to wait for
307 // the error page, so we wait for both loads to finish.
308
309 void DnsProbeBrowserTest::NavigateToDnsError() {
310 NavigateToURLBlockUntilNavigationsComplete(
311 browser(),
312 URLRequestFailedJob::GetMockHttpUrl(net::ERR_NAME_NOT_RESOLVED),
313 2);
314 }
315
316 void DnsProbeBrowserTest::NavigateToOtherError() {
317 NavigateToURLBlockUntilNavigationsComplete(
318 browser(),
319 URLRequestFailedJob::GetMockHttpUrl(net::ERR_CONNECTION_REFUSED),
320 2);
321 }
322
323 void DnsProbeBrowserTest::WaitForProbe() {
324 probe_started_callback_.WaitForCall();
325 }
326
327 void DnsProbeBrowserTest::SimulateProbeResult(DnsProbeStatus result) {
328 TestCompletionCallback io_thread_done;
329 BrowserThread::PostTask(
330 BrowserThread::IO, FROM_HERE,
331 Bind(&DnsProbeBrowserTestIOThreadHelper::SimulateProbeResult,
332 Unretained(&helper_),
333 result,
334 ConstRef(io_thread_done.callback())));
335 io_thread_done.WaitForCall();
336 }
337
338 void DnsProbeBrowserTestIOThreadHelper::SimulateProbeResult(
339 DnsProbeStatus result,
340 const Closure& callback) {
341 DCHECK(mock_service_);
342 mock_service_->CallCallbacks(result);
343 BrowserThread::PostTask(BrowserThread::UI, FROM_HERE, callback);
344 }
345
346 bool DnsProbeBrowserTest::TitleContains(const std::string& expected) {
mmenke 2013/05/28 18:20:13 Is there a reason not to use TitleWatcher?
Deprecated (see juliatuttle) 2013/06/05 21:01:47 I don't want to wait for it; I expect it to have t
347 std::string title;
348
349 WebContents* contents =
350 browser()->tab_strip_model()->GetActiveWebContents();
351
352 bool rv = content::ExecuteScriptAndExtractString(
353 contents,
354 "domAutomationController.send(document.title);",
355 &title);
356 if (!rv)
357 return false;
358
359 return title.find(expected) != std::string::npos;
360 }
361
362 bool DnsProbeBrowserTest::PageContains(const std::string& expected) {
363 std::string textContent;
mmenke 2013/05/28 18:20:13 text_content.
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
364
365 WebContents* contents =
366 browser()->tab_strip_model()->GetActiveWebContents();
mmenke 2013/05/28 18:20:13 optional: Suggest you just inline this, to reduce
Deprecated (see juliatuttle) 2013/06/05 21:01:47 Done.
367
368 bool rv = content::ExecuteScriptAndExtractString(
369 contents,
370 "domAutomationController.send(document.body.textContent);",
371 &textContent);
372 if (!rv)
373 return false;
374
375 return textContent.find(expected) != std::string::npos;
376 }
377
378 void DnsProbeBrowserTest::SetLinkDoctorNetError(int net_error) {
mmenke 2013/05/28 18:20:13 Instead of this, can we just change the link docto
Deprecated (see juliatuttle) 2013/06/05 21:01:47 We can't change it once the tab is created. That'
379 BrowserThread::PostTask(
380 BrowserThread::IO, FROM_HERE,
381 Bind(&DnsProbeBrowserTestIOThreadHelper::set_link_doctor_net_error,
382 Unretained(&helper_),
383 net_error));
384 }
385
386 void DnsProbeBrowserTest::OnProbeStarted() {
387 probe_started_count_++;
388 probe_started_callback_.callback().Run();
389 }
390
391 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithLinkDoctor) {
392 SetLinkDoctorBroken(false);
393
394 NavigateToOtherError();
395 EXPECT_EQ(0, probe_count());
396 EXPECT_TRUE(TitleContains("Mock Link Doctor"));
397 }
398
399 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, OtherErrorWithoutLinkDoctor) {
400 SetLinkDoctorBroken(true);
401
402 NavigateToOtherError();
403 EXPECT_EQ(0, probe_count());
404 EXPECT_TRUE(PageContains("CONNECTION_REFUSED"));
405 }
406
407 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NxdomainWithLinkDoctor) {
408 SetLinkDoctorBroken(false);
409
410 NavigateToDnsError();
411 WaitForProbe();
412 SimulateProbeResult(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
413 EXPECT_TRUE(TitleContains("Mock Link Doctor"));
414 }
415
416 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoInternetWithoutLinkDoctor) {
417 SetLinkDoctorBroken(true);
418
419 NavigateToDnsError();
420 WaitForProbe();
421 EXPECT_TRUE(PageContains("DNS_PROBE_STARTED"));
422
423 SimulateProbeResult(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
424 EXPECT_TRUE(PageContains("DNS_PROBE_FINISHED_NO_INTERNET"));
425 }
426
427 static const FilePath::CharType kIframeDnsErrorHtmlName[] =
428 FILE_PATH_LITERAL("iframe_dns_error.html");
429
430 IN_PROC_BROWSER_TEST_F(DnsProbeBrowserTest, NoProbeInSubframe) {
431 SetLinkDoctorBroken(false);
432
433 NavigateToURL(
434 browser(),
435 URLRequestMockHTTPJob::GetMockUrl(FilePath(kIframeDnsErrorHtmlName)));
436 EXPECT_EQ(0, probe_count());
437 }
438
439 } // namespace
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698