OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/renderer/net/net_error_helper_core.h" | 5 #include "chrome/renderer/net/net_error_helper_core.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/bind.h" | |
10 #include "base/callback.h" | |
11 #include "base/location.h" | |
9 #include "base/metrics/histogram.h" | 12 #include "base/metrics/histogram.h" |
10 #include "chrome/common/localized_error.h" | 13 #include "chrome/common/localized_error.h" |
11 #include "net/base/escape.h" | 14 #include "net/base/escape.h" |
12 #include "net/base/net_errors.h" | 15 #include "net/base/net_errors.h" |
13 #include "third_party/WebKit/public/platform/WebString.h" | 16 #include "third_party/WebKit/public/platform/WebString.h" |
14 #include "third_party/WebKit/public/platform/WebURLError.h" | 17 #include "third_party/WebKit/public/platform/WebURLError.h" |
15 #include "url/gurl.h" | 18 #include "url/gurl.h" |
16 | 19 |
17 namespace { | 20 namespace { |
18 | 21 |
22 base::TimeDelta GetAutoReloadTime(size_t reload_count) { | |
23 LOG(ERROR) << "GetAutoReloadTime: " << reload_count; | |
mmenke
2014/03/11 20:07:54
nit: Remove logging
Elly Fong-Jones
2014/03/12 15:08:58
Done.
| |
24 static const int kDelaysMs[] = { | |
25 0, 5000, 30000, 60000, 300000, 600000, 1800000 | |
26 }; | |
27 if (reload_count >= arraysize(kDelaysMs)) | |
28 reload_count = arraysize(kDelaysMs) - 1; | |
29 return base::TimeDelta::FromMilliseconds(kDelaysMs[reload_count]); | |
30 } | |
31 | |
19 // Returns whether |net_error| is a DNS-related error (and therefore whether | 32 // Returns whether |net_error| is a DNS-related error (and therefore whether |
20 // the tab helper should start a DNS probe after receiving it.) | 33 // the tab helper should start a DNS probe after receiving it.) |
21 bool IsDnsError(const blink::WebURLError& error) { | 34 bool IsDnsError(const blink::WebURLError& error) { |
22 return error.domain.utf8() == net::kErrorDomain && | 35 return error.domain.utf8() == net::kErrorDomain && |
23 (error.reason == net::ERR_NAME_NOT_RESOLVED || | 36 (error.reason == net::ERR_NAME_NOT_RESOLVED || |
24 error.reason == net::ERR_NAME_RESOLUTION_FAILED); | 37 error.reason == net::ERR_NAME_RESOLUTION_FAILED); |
25 } | 38 } |
26 | 39 |
27 // If an alternate error page should be retrieved remotely for a main frame load | 40 // If an alternate error page should be retrieved remotely for a main frame load |
28 // that failed with |error|, returns true and sets |error_page_url| to the URL | 41 // that failed with |error|, returns true and sets |error_page_url| to the URL |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
109 // valid URL. Request will be issued when the error page finishes loading. | 122 // valid URL. Request will be issued when the error page finishes loading. |
110 // This is done on load complete to ensure that there are two complete loads | 123 // This is done on load complete to ensure that there are two complete loads |
111 // for tests to wait for. | 124 // for tests to wait for. |
112 GURL alternate_error_page_url; | 125 GURL alternate_error_page_url; |
113 | 126 |
114 // True if a page has completed loading, at which point it can receive | 127 // True if a page has completed loading, at which point it can receive |
115 // updates. | 128 // updates. |
116 bool is_finished_loading; | 129 bool is_finished_loading; |
117 }; | 130 }; |
118 | 131 |
119 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 132 bool NetErrorHelperCore::IsReloadableError( |
133 const NetErrorHelperCore::ErrorPageInfo& info) { | |
134 return info.error.domain.utf8() == net::kErrorDomain && | |
135 info.error.reason != net::ERR_ABORTED && | |
136 !info.was_failed_post; | |
137 } | |
138 | |
139 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate, | |
140 scoped_ptr<MockableOneShotTimer> reload_timer) | |
120 : delegate_(delegate), | 141 : delegate_(delegate), |
121 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { | 142 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
143 auto_reload_enabled_(false), | |
144 auto_reload_timer_(reload_timer.Pass()), | |
145 online_(true), | |
146 auto_reload_count_(0), | |
147 can_auto_reload_page_(false) { | |
122 } | 148 } |
123 | 149 |
124 NetErrorHelperCore::~NetErrorHelperCore() { | 150 NetErrorHelperCore::~NetErrorHelperCore() { |
125 } | 151 } |
126 | 152 |
153 void NetErrorHelperCore::CancelPendingFetches() { | |
154 // Cancel loading the alternate error page, and prevent any pending error page | |
155 // load from starting a new error page load. Swapping in the error page when | |
156 // it's finished loading could abort the navigation, otherwise. | |
157 if (committed_error_page_info_ && can_auto_reload_page_) { | |
158 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtStop", | |
159 committed_error_page_info_->error.reason, | |
160 net::GetAllErrorCodesForUma()); | |
161 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtStop", auto_reload_count_); | |
162 } | |
163 if (committed_error_page_info_) { | |
164 committed_error_page_info_->alternate_error_page_url = GURL(); | |
165 } | |
166 if (pending_error_page_info_) { | |
167 pending_error_page_info_->alternate_error_page_url = GURL(); | |
168 } | |
169 delegate_->CancelFetchErrorPage(); | |
170 auto_reload_timer_->Stop(); | |
171 } | |
172 | |
127 void NetErrorHelperCore::OnStop() { | 173 void NetErrorHelperCore::OnStop() { |
128 // On stop, cancel loading the alternate error page, and prevent any pending | 174 CancelPendingFetches(); |
129 // error page load from starting a new error page load. Swapping in the error | 175 auto_reload_count_ = 0; |
130 // page when it's finished loading could abort the navigation, otherwise. | 176 can_auto_reload_page_ = false; |
131 if (committed_error_page_info_) | |
132 committed_error_page_info_->alternate_error_page_url = GURL(); | |
133 if (pending_error_page_info_) | |
134 pending_error_page_info_->alternate_error_page_url = GURL(); | |
135 delegate_->CancelFetchErrorPage(); | |
136 } | 177 } |
137 | 178 |
138 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { | 179 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
139 if (frame_type != MAIN_FRAME) | 180 if (frame_type != MAIN_FRAME) |
140 return; | 181 return; |
141 | 182 |
142 // If there's no pending error page information associated with the page load, | 183 // If there's no pending error page information associated with the page load, |
143 // or the new page is not an error page, then reset pending error page state. | 184 // or the new page is not an error page, then reset pending error page state. |
144 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { | 185 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { |
145 OnStop(); | 186 CancelPendingFetches(); |
146 } | 187 } |
147 } | 188 } |
148 | 189 |
149 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 190 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
150 if (frame_type != MAIN_FRAME) | 191 if (frame_type != MAIN_FRAME) |
151 return; | 192 return; |
152 | 193 |
194 if (committed_error_page_info_ && !pending_error_page_info_ && | |
195 can_auto_reload_page_) { | |
196 int reason = committed_error_page_info_->error.reason; | |
197 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtSuccess", | |
198 reason, | |
199 net::GetAllErrorCodesForUma()); | |
200 UMA_HISTOGRAM_COUNTS("Net.AutoReload.CountAtSuccess", auto_reload_count_); | |
201 if (auto_reload_count_ == 1) { | |
202 UMA_HISTOGRAM_CUSTOM_ENUMERATION("Net.AutoReload.ErrorAtFirstSuccess", | |
203 reason, | |
204 net::GetAllErrorCodesForUma()); | |
205 } | |
206 } | |
207 | |
153 committed_error_page_info_.reset(pending_error_page_info_.release()); | 208 committed_error_page_info_.reset(pending_error_page_info_.release()); |
154 } | 209 } |
155 | 210 |
156 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 211 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
157 if (frame_type != MAIN_FRAME || !committed_error_page_info_) | 212 if (frame_type != MAIN_FRAME) |
158 return; | 213 return; |
159 | 214 |
215 if (!committed_error_page_info_) { | |
216 auto_reload_count_ = 0; | |
217 return; | |
218 } | |
219 | |
160 committed_error_page_info_->is_finished_loading = true; | 220 committed_error_page_info_->is_finished_loading = true; |
161 | 221 |
162 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { | 222 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { |
163 // If there is another pending error page load, | 223 // If there is another pending error page load, |
164 // |replace_with_alternate_error_page| should have been set to false. | 224 // |replace_with_alternate_error_page| should have been set to false. |
165 DCHECK(!pending_error_page_info_); | 225 DCHECK(!pending_error_page_info_); |
166 DCHECK(!committed_error_page_info_->needs_dns_updates); | 226 DCHECK(!committed_error_page_info_->needs_dns_updates); |
167 GURL error_page_url; | 227 GURL error_page_url; |
168 delegate_->FetchErrorPage( | 228 delegate_->FetchErrorPage( |
169 committed_error_page_info_->alternate_error_page_url); | 229 committed_error_page_info_->alternate_error_page_url); |
230 } else if (auto_reload_enabled_ && | |
231 IsReloadableError(*committed_error_page_info_)) { | |
232 can_auto_reload_page_ = true; | |
233 MaybeStartAutoReloadTimer(); | |
170 } | 234 } |
171 | 235 |
172 if (!committed_error_page_info_->needs_dns_updates || | 236 if (!committed_error_page_info_->needs_dns_updates || |
173 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { | 237 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { |
174 return; | 238 return; |
175 } | 239 } |
176 DVLOG(1) << "Error page finished loading; sending saved status."; | 240 DVLOG(1) << "Error page finished loading; sending saved status."; |
177 UpdateErrorPage(); | 241 UpdateErrorPage(); |
178 } | 242 } |
179 | 243 |
(...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
310 | 374 |
311 blink::WebURLError updated_error; | 375 blink::WebURLError updated_error; |
312 updated_error.domain = blink::WebString::fromUTF8( | 376 updated_error.domain = blink::WebString::fromUTF8( |
313 chrome_common_net::kDnsProbeErrorDomain); | 377 chrome_common_net::kDnsProbeErrorDomain); |
314 updated_error.reason = last_probe_status_; | 378 updated_error.reason = last_probe_status_; |
315 updated_error.unreachableURL = error.unreachableURL; | 379 updated_error.unreachableURL = error.unreachableURL; |
316 updated_error.staleCopyInCache = error.staleCopyInCache; | 380 updated_error.staleCopyInCache = error.staleCopyInCache; |
317 | 381 |
318 return updated_error; | 382 return updated_error; |
319 } | 383 } |
384 | |
385 void NetErrorHelperCore::Reload() { | |
386 if (!committed_error_page_info_) { | |
387 return; | |
388 } | |
389 delegate_->ReloadPage(); | |
390 } | |
391 | |
392 bool NetErrorHelperCore::MaybeStartAutoReloadTimer() { | |
393 if (!committed_error_page_info_ || !can_auto_reload_page_) | |
394 return false; | |
395 | |
396 DCHECK(IsReloadableError(*committed_error_page_info_)); | |
397 | |
398 if (!online_) | |
399 return false; | |
400 | |
401 StartAutoReloadTimer(); | |
mmenke
2014/03/11 20:07:54
If there's an uncommitted load, we should not do t
Elly Fong-Jones
2014/03/12 15:08:58
Hm. I've made OnStartLoad update can_auto_reload_p
| |
402 return true; | |
403 } | |
404 | |
405 void NetErrorHelperCore::StartAutoReloadTimer() { | |
406 DCHECK(committed_error_page_info_); | |
407 DCHECK(can_auto_reload_page_); | |
408 base::TimeDelta delay = | |
409 GetAutoReloadTime(auto_reload_count_); | |
mmenke
2014/03/11 20:07:54
nit: May it on one line.
Elly Fong-Jones
2014/03/12 15:08:58
Done.
| |
410 auto_reload_count_++; | |
411 auto_reload_timer_->Stop(); | |
412 auto_reload_timer_->Start(FROM_HERE, delay, | |
413 base::Bind(&NetErrorHelperCore::Reload, | |
414 base::Unretained(this))); | |
415 } | |
416 | |
417 void NetErrorHelperCore::NetworkStateChanged(bool online) { | |
418 online_ = online; | |
419 if (auto_reload_timer_->IsRunning()) { | |
420 DCHECK(committed_error_page_info_); | |
421 // If there's an existing timer running, stop it and reset the retry count. | |
422 auto_reload_timer_->Stop(); | |
423 auto_reload_count_ = 0; | |
424 } | |
425 | |
426 // If the network state changed to online, maybe start auto-reloading again. | |
427 if (online) | |
428 MaybeStartAutoReloadTimer(); | |
429 } | |
430 | |
431 bool NetErrorHelperCore::ShouldSuppressErrorPage(FrameType frame_type, | |
432 const GURL& url) { | |
433 // Don't suppress child frame errors. | |
434 if (frame_type != MAIN_FRAME) | |
435 return false; | |
436 | |
437 // If |auto_reload_timer_| is still running, this error page isn't from an | |
438 // auto reload. | |
439 if (auto_reload_timer_->IsRunning()) | |
440 return false; | |
441 | |
442 // If there's no committed error page, this error page wasn't from an auto | |
443 // reload. | |
444 if (!committed_error_page_info_ || !can_auto_reload_page_) | |
445 return false; | |
446 | |
447 GURL error_url = committed_error_page_info_->error.unreachableURL; | |
448 if (error_url != url) | |
449 return false; | |
450 | |
451 MaybeStartAutoReloadTimer(); | |
452 return true; | |
453 } | |
454 | |
455 int NetErrorHelperCore::GetAutoReloadCount() const { | |
456 return auto_reload_count_; | |
457 } | |
OLD | NEW |