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

Side by Side Diff: chrome/browser/net/net_error_tab_helper.cc

Issue 13270005: Display DNS probe results. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Created 7 years, 5 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
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/net/net_error_tab_helper.h" 5 #include "chrome/browser/net/net_error_tab_helper.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/metrics/field_trial.h" 8 #include "base/metrics/field_trial.h"
9 #include "base/prefs/pref_service.h" 9 #include "base/prefs/pref_service.h"
10 #include "chrome/browser/browser_process.h" 10 #include "chrome/browser/browser_process.h"
11 #include "chrome/browser/io_thread.h" 11 #include "chrome/browser/io_thread.h"
12 #include "chrome/browser/net/dns_probe_service.h" 12 #include "chrome/browser/net/dns_probe_service.h"
13 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
14 #include "chrome/common/net/net_error_info.h" 14 #include "chrome/common/net/net_error_info.h"
15 #include "chrome/common/pref_names.h" 15 #include "chrome/common/pref_names.h"
16 #include "chrome/common/render_messages.h" 16 #include "chrome/common/render_messages.h"
17 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
18 #include "net/base/net_errors.h" 18 #include "net/base/net_errors.h"
19 19
20 using base::FieldTrialList; 20 using base::FieldTrialList;
21 using chrome_common_net::DnsProbeResult; 21 using chrome_common_net::DnsProbeStatus;
22 using chrome_common_net::DnsProbeStatusToString;
22 using content::BrowserContext; 23 using content::BrowserContext;
23 using content::BrowserThread; 24 using content::BrowserThread;
24 using content::PageTransition; 25 using content::PageTransition;
25 using content::RenderViewHost; 26 using content::RenderViewHost;
26 using content::WebContents; 27 using content::WebContents;
27 using content::WebContentsObserver; 28 using content::WebContentsObserver;
28 29
29 DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper); 30 DEFINE_WEB_CONTENTS_USER_DATA_KEY(chrome_browser_net::NetErrorTabHelper);
30 31
31 namespace chrome_browser_net { 32 namespace chrome_browser_net {
32 33
33 namespace { 34 namespace {
34 35
35 const char kDnsProbeFieldTrialName[] = "DnsProbe-Enable";
36 const char kDnsProbeFieldTrialEnableGroupName[] = "enable";
37
38 static NetErrorTabHelper::TestingState testing_state_ = 36 static NetErrorTabHelper::TestingState testing_state_ =
39 NetErrorTabHelper::TESTING_DEFAULT; 37 NetErrorTabHelper::TESTING_DEFAULT;
40 38
41 // Returns whether |net_error| is a DNS-related error (and therefore whether 39 // Returns whether |net_error| is a DNS-related error (and therefore whether
42 // the tab helper should start a DNS probe after receiving it.) 40 // the tab helper should start a DNS probe after receiving it.)
43 bool IsDnsError(int net_error) { 41 bool IsDnsError(int net_error) {
44 return net_error == net::ERR_NAME_NOT_RESOLVED || 42 return net_error == net::ERR_NAME_NOT_RESOLVED ||
45 net_error == net::ERR_NAME_RESOLUTION_FAILED; 43 net_error == net::ERR_NAME_RESOLUTION_FAILED;
46 } 44 }
47 45
48 bool GetEnabledByTrial() {
49 return (FieldTrialList::FindFullName(kDnsProbeFieldTrialName)
50 == kDnsProbeFieldTrialEnableGroupName);
51 }
52
53 NetErrorTracker::FrameType GetFrameType(bool is_main_frame) {
54 return is_main_frame ? NetErrorTracker::FRAME_MAIN
55 : NetErrorTracker::FRAME_SUB;
56 }
57
58 NetErrorTracker::PageType GetPageType(bool is_error_page) {
59 return is_error_page ? NetErrorTracker::PAGE_ERROR
60 : NetErrorTracker::PAGE_NORMAL;
61 }
62
63 NetErrorTracker::ErrorType GetErrorType(int net_error) {
64 return IsDnsError(net_error) ? NetErrorTracker::ERROR_DNS
65 : NetErrorTracker::ERROR_OTHER;
66 }
67
68 void OnDnsProbeFinishedOnIOThread( 46 void OnDnsProbeFinishedOnIOThread(
69 const base::Callback<void(DnsProbeResult)>& callback, 47 const base::Callback<void(DnsProbeStatus)>& callback,
70 DnsProbeResult result) { 48 DnsProbeStatus result) {
71 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 49 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
72 50
73 DVLOG(1) << "DNS probe finished with result " << result;
74
75 BrowserThread::PostTask( 51 BrowserThread::PostTask(
76 BrowserThread::UI, 52 BrowserThread::UI,
77 FROM_HERE, 53 FROM_HERE,
78 base::Bind(callback, result)); 54 base::Bind(callback, result));
79 } 55 }
80 56
81 // We can only access g_browser_process->io_thread() from the browser thread, 57 // We can only access g_browser_process->io_thread() from the browser thread,
82 // so we have to pass it in to the callback instead of dereferencing it here. 58 // so we have to pass it in to the callback instead of dereferencing it here.
83 void StartDnsProbeOnIOThread( 59 void StartDnsProbeOnIOThread(
84 const base::Callback<void(DnsProbeResult)>& callback, 60 const base::Callback<void(DnsProbeStatus)>& callback,
85 IOThread* io_thread) { 61 IOThread* io_thread) {
86 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO)); 62 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
87 63
88 DVLOG(1) << "Starting DNS probe";
89
90 DnsProbeService* probe_service = 64 DnsProbeService* probe_service =
91 io_thread->globals()->dns_probe_service.get(); 65 io_thread->globals()->dns_probe_service.get();
92 66
93 probe_service->ProbeDns(base::Bind(&OnDnsProbeFinishedOnIOThread, callback)); 67 probe_service->ProbeDns(base::Bind(&OnDnsProbeFinishedOnIOThread, callback));
94 } 68 }
95 69
96 } // namespace 70 } // namespace
97 71
98 NetErrorTabHelper::~NetErrorTabHelper() { 72 NetErrorTabHelper::~NetErrorTabHelper() {
99 } 73 }
100 74
101 // static 75 // static
102 void NetErrorTabHelper::set_state_for_testing(TestingState state) { 76 void NetErrorTabHelper::set_state_for_testing(TestingState state) {
103 testing_state_ = state; 77 testing_state_ = state;
104 } 78 }
105 79
106 void NetErrorTabHelper::DidStartProvisionalLoadForFrame( 80 void NetErrorTabHelper::DidStartProvisionalLoadForFrame(
107 int64 frame_id, 81 int64 frame_id,
108 int64 parent_frame_id, 82 int64 parent_frame_id,
109 bool is_main_frame, 83 bool is_main_frame,
110 const GURL& validated_url, 84 const GURL& validated_url,
111 bool is_error_page, 85 bool is_error_page,
112 bool is_iframe_srcdoc, 86 bool is_iframe_srcdoc,
113 RenderViewHost* render_view_host) { 87 RenderViewHost* render_view_host) {
114 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 88 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
115 89
116 tracker_.OnStartProvisionalLoad(GetFrameType(is_main_frame), 90 if (!is_main_frame)
117 GetPageType(is_error_page)); 91 return;
92
93 is_error_page_ = is_error_page;
118 } 94 }
119 95
120 void NetErrorTabHelper::DidCommitProvisionalLoadForFrame( 96 void NetErrorTabHelper::DidCommitProvisionalLoadForFrame(
121 int64 frame_id, 97 int64 frame_id,
122 bool is_main_frame, 98 bool is_main_frame,
123 const GURL& url, 99 const GURL& url,
124 PageTransition transition_type, 100 PageTransition transition_type,
125 RenderViewHost* render_view_host) { 101 RenderViewHost* render_view_host) {
126 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
127 103
128 tracker_.OnCommitProvisionalLoad(GetFrameType(is_main_frame)); 104 if (!is_main_frame)
105 return;
106
107 // Resend status every time we commit a page; this is somewhat spammy, but
108 // ensures that the status will make it to the real error page, even if the
109 // link doctor loads a blank intermediate page or the tab switches renderer
110 // processes.
111 if (is_error_page_) {
112 if (dns_error_active_) {
113 dns_error_page_committed_ = true;
114 DVLOG(1) << "Committed error page; resending status.";
115 SendInfo();
116 }
mmenke 2013/07/12 19:51:22 Shouldn't we clear dns_error_page_committed_ if dn
Deprecated (see juliatuttle) 2013/07/12 20:55:55 Done.
117 } else {
118 dns_error_active_ = false;
mmenke 2013/07/12 19:51:22 optional: Could we just clear this in DidStartPro
Deprecated (see juliatuttle) 2013/07/12 20:55:55 What would it be more consistent with? Right now
mmenke 2013/07/12 21:07:49 It would be more consistent with the current state
119 dns_error_page_committed_ = false;
120 }
129 } 121 }
130 122
131 void NetErrorTabHelper::DidFailProvisionalLoad( 123 void NetErrorTabHelper::DidFailProvisionalLoad(
132 int64 frame_id, 124 int64 frame_id,
133 bool is_main_frame, 125 bool is_main_frame,
134 const GURL& validated_url, 126 const GURL& validated_url,
135 int error_code, 127 int error_code,
136 const string16& error_description, 128 const string16& error_description,
137 RenderViewHost* render_view_host) { 129 RenderViewHost* render_view_host) {
138 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 130 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
139 131
140 tracker_.OnFailProvisionalLoad(GetFrameType(is_main_frame), 132 if (!is_main_frame)
141 GetErrorType(error_code)); 133 return;
142 }
143 134
144 void NetErrorTabHelper::DidFinishLoad( 135 if (IsDnsError(error_code)) {
145 int64 frame_id, 136 dns_error_active_ = true;
146 const GURL& validated_url, 137 OnMainFrameDnsError();
147 bool is_main_frame, 138 }
148 RenderViewHost* render_view_host) {
149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
150
151 tracker_.OnFinishLoad(GetFrameType(is_main_frame));
152 } 139 }
153 140
154 NetErrorTabHelper::NetErrorTabHelper(WebContents* contents) 141 NetErrorTabHelper::NetErrorTabHelper(WebContents* contents)
155 : WebContentsObserver(contents), 142 : WebContentsObserver(contents),
156 weak_factory_(this), 143 weak_factory_(this),
157 tracker_(base::Bind(&NetErrorTabHelper::TrackerCallback, 144 is_error_page_(false),
158 weak_factory_.GetWeakPtr())), 145 dns_error_active_(false),
159 dns_error_page_state_(NetErrorTracker::DNS_ERROR_PAGE_NONE), 146 dns_error_page_committed_(false),
160 dns_probe_state_(DNS_PROBE_NONE), 147 dns_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE),
161 enabled_by_trial_(GetEnabledByTrial()) { 148 enabled_by_trial_(chrome_common_net::DnsProbesEnabledByFieldTrial()) {
162 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 149 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
163 150
164 InitializePref(contents); 151 // If we're being tested, we don't have a WebContents.
mmenke 2013/07/12 19:51:22 nit: Some people feel strongly about not using "w
Deprecated (see juliatuttle) 2013/07/12 20:55:55 Fixed, here and elsewhere.
152 if (contents)
153 InitializePref(contents);
165 } 154 }
166 155
167 void NetErrorTabHelper::TrackerCallback( 156 void NetErrorTabHelper::OnMainFrameDnsError() {
168 NetErrorTracker::DnsErrorPageState state) { 157 if (ProbesAllowed()) {
169 dns_error_page_state_ = state; 158 // Don't start more than one probe at a time.
170 159 if (dns_probe_status_ != chrome_common_net::DNS_PROBE_STARTED) {
171 MaybePostStartDnsProbeTask(); 160 StartDnsProbe();
172 MaybeSendInfo(); 161 dns_probe_status_ = chrome_common_net::DNS_PROBE_STARTED;
173 } 162 }
174 163 } else {
175 void NetErrorTabHelper::MaybePostStartDnsProbeTask() { 164 dns_probe_status_ = chrome_common_net::DNS_PROBE_NOT_RUN;
176 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
177
178 if (dns_error_page_state_ != NetErrorTracker::DNS_ERROR_PAGE_NONE &&
179 dns_probe_state_ != DNS_PROBE_STARTED &&
180 ProbesAllowed()) {
181 BrowserThread::PostTask(
182 BrowserThread::IO,
183 FROM_HERE,
184 base::Bind(&StartDnsProbeOnIOThread,
185 base::Bind(&NetErrorTabHelper::OnDnsProbeFinished,
186 weak_factory_.GetWeakPtr()),
187 g_browser_process->io_thread()));
188 dns_probe_state_ = DNS_PROBE_STARTED;
189 } 165 }
190 } 166 }
191 167
192 void NetErrorTabHelper::OnDnsProbeFinished(DnsProbeResult result) { 168 void NetErrorTabHelper::StartDnsProbe() {
193 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI)); 169 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
194 DCHECK_EQ(DNS_PROBE_STARTED, dns_probe_state_); 170 DCHECK(dns_error_active_);
171 DCHECK_NE(chrome_common_net::DNS_PROBE_STARTED, dns_probe_status_);
195 172
196 dns_probe_result_ = result; 173 DVLOG(1) << "Starting DNS probe.";
197 dns_probe_state_ = DNS_PROBE_FINISHED;
198 174
199 MaybeSendInfo(); 175 BrowserThread::PostTask(
176 BrowserThread::IO,
177 FROM_HERE,
178 base::Bind(&StartDnsProbeOnIOThread,
179 base::Bind(&NetErrorTabHelper::OnDnsProbeFinished,
180 weak_factory_.GetWeakPtr()),
181 g_browser_process->io_thread()));
200 } 182 }
201 183
202 void NetErrorTabHelper::MaybeSendInfo() { 184 void NetErrorTabHelper::OnDnsProbeFinished(DnsProbeStatus result) {
203 if (dns_error_page_state_ == NetErrorTracker::DNS_ERROR_PAGE_LOADED && 185 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
204 dns_probe_state_ == DNS_PROBE_FINISHED) { 186 DCHECK_EQ(chrome_common_net::DNS_PROBE_STARTED, dns_probe_status_);
205 DVLOG(1) << "Sending result " << dns_probe_result_ << " to renderer"; 187 DCHECK(chrome_common_net::DnsProbeStatusIsFinished(result));
206 Send(new ChromeViewMsg_NetErrorInfo(routing_id(), dns_probe_result_)); 188
207 dns_probe_state_ = DNS_PROBE_NONE; 189 DVLOG(1) << "Finished DNS probe with result "
208 } 190 << DnsProbeStatusToString(result) << ".";
191
192 dns_probe_status_ = result;
193
194 if (dns_error_page_committed_)
195 SendInfo();
209 } 196 }
210 197
211 void NetErrorTabHelper::InitializePref(WebContents* contents) { 198 void NetErrorTabHelper::InitializePref(WebContents* contents) {
212 DCHECK(contents); 199 DCHECK(contents);
213 200
214 BrowserContext* browser_context = contents->GetBrowserContext(); 201 BrowserContext* browser_context = contents->GetBrowserContext();
215 Profile* profile = Profile::FromBrowserContext(browser_context); 202 Profile* profile = Profile::FromBrowserContext(browser_context);
216 resolve_errors_with_web_service_.Init( 203 resolve_errors_with_web_service_.Init(
217 prefs::kAlternateErrorPagesEnabled, 204 prefs::kAlternateErrorPagesEnabled,
218 profile->GetPrefs()); 205 profile->GetPrefs());
219 } 206 }
220 207
221 bool NetErrorTabHelper::ProbesAllowed() const { 208 bool NetErrorTabHelper::ProbesAllowed() const {
222 if (testing_state_ != TESTING_DEFAULT) 209 if (testing_state_ != TESTING_DEFAULT)
223 return testing_state_ == TESTING_FORCE_ENABLED; 210 return testing_state_ == TESTING_FORCE_ENABLED;
224 211
225 // TODO(ttuttle): Disable on mobile? 212 // TODO(ttuttle): Disable on mobile?
226 return enabled_by_trial_ && *resolve_errors_with_web_service_; 213 return enabled_by_trial_ && *resolve_errors_with_web_service_;
227 } 214 }
228 215
216 void NetErrorTabHelper::SendInfo() {
217 DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, dns_probe_status_);
218 DCHECK(dns_error_page_committed_);
219
220 DVLOG(1) << "Sending status " << DnsProbeStatusToString(dns_probe_status_);
221 Send(new ChromeViewMsg_NetErrorInfo(routing_id(), dns_probe_status_));
222
223 if (!dns_probe_status_snoop_callback_.is_null())
224 dns_probe_status_snoop_callback_.Run(dns_probe_status_);
225 }
226
229 } // namespace chrome_browser_net 227 } // namespace chrome_browser_net
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698