Chromium Code Reviews| 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 GetAutoReloadBackoff(size_t reloads) { | |
|
mmenke
2014/02/05 23:31:43
I suggest reload_count or num_reloads. I generall
mmenke
2014/02/05 23:31:43
I suggest "GetAutoReloadTime" or "GetAutoReloadTim
Elly Fong-Jones
2014/02/10 21:42:06
Done.
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 23 static const int kDelaysMs[] = { | |
| 24 5000, 30000, 60000, 300000, 600000, 1800000 | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
I'd like to have some UMA as to when we succeed on
| |
| 25 }; | |
| 26 if (reloads >= arraysize(kDelaysMs)) | |
| 27 reloads = arraysize(kDelaysMs) - 1; | |
| 28 return base::TimeDelta::FromMilliseconds(kDelaysMs[reloads]); | |
| 29 } | |
| 30 | |
| 19 // Returns whether |net_error| is a DNS-related error (and therefore whether | 31 // Returns whether |net_error| is a DNS-related error (and therefore whether |
| 20 // the tab helper should start a DNS probe after receiving it.) | 32 // the tab helper should start a DNS probe after receiving it.) |
| 21 bool IsDnsError(const blink::WebURLError& error) { | 33 bool IsDnsError(const blink::WebURLError& error) { |
| 22 return error.domain.utf8() == net::kErrorDomain && | 34 return error.domain.utf8() == net::kErrorDomain && |
| 23 (error.reason == net::ERR_NAME_NOT_RESOLVED || | 35 (error.reason == net::ERR_NAME_NOT_RESOLVED || |
| 24 error.reason == net::ERR_NAME_RESOLUTION_FAILED); | 36 error.reason == net::ERR_NAME_RESOLUTION_FAILED); |
| 25 } | 37 } |
| 26 | 38 |
| 39 bool IsReloadableError(const blink::WebURLError& error) { | |
|
mmenke
2014/02/05 23:31:43
You should check the error domain, too, rather tha
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 40 return error.reason != net::ERR_ABORTED; | |
| 41 /* | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
Why commented out?
Elly Fong-Jones
2014/02/10 21:42:06
leftover from earlier, oops
Done.
| |
| 42 return error.reason == net::ERR_NAME_NOT_RESOLVED || | |
| 43 error.reason == net::ERR_INTERNET_DISCONNECTED || | |
| 44 error.reason == net::ERR_ADDRESS_UNREACHABLE || | |
| 45 error.reason == net::ERR_CONNECTION_TIMED_OUT || | |
| 46 error.reason == net::ERR_NETWORK_CHANGED; | |
| 47 */ | |
| 48 } | |
| 49 | |
| 27 // If an alternate error page should be retrieved remotely for a main frame load | 50 // 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 | 51 // that failed with |error|, returns true and sets |error_page_url| to the URL |
| 29 // of the remote error page. | 52 // of the remote error page. |
| 30 bool GetErrorPageURL(const blink::WebURLError& error, | 53 bool GetErrorPageURL(const blink::WebURLError& error, |
| 31 const GURL& alt_error_page_url, | 54 const GURL& alt_error_page_url, |
| 32 GURL* error_page_url) { | 55 GURL* error_page_url) { |
| 33 if (!alt_error_page_url.is_valid()) | 56 if (!alt_error_page_url.is_valid()) |
| 34 return false; | 57 return false; |
| 35 | 58 |
| 36 // Parameter to send to the error page indicating the error type. | 59 // Parameter to send to the error page indicating the error type. |
| (...skipping 74 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 111 // for tests to wait for. | 134 // for tests to wait for. |
| 112 GURL alternate_error_page_url; | 135 GURL alternate_error_page_url; |
| 113 | 136 |
| 114 // True if a page has completed loading, at which point it can receive | 137 // True if a page has completed loading, at which point it can receive |
| 115 // updates. | 138 // updates. |
| 116 bool is_finished_loading; | 139 bool is_finished_loading; |
| 117 }; | 140 }; |
| 118 | 141 |
| 119 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) | 142 NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate) |
| 120 : delegate_(delegate), | 143 : delegate_(delegate), |
| 121 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) { | 144 last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE), |
| 145 auto_reload_enabled_(false), | |
| 146 auto_reload_count_(0) { | |
| 122 } | 147 } |
| 123 | 148 |
| 124 NetErrorHelperCore::~NetErrorHelperCore() { | 149 NetErrorHelperCore::~NetErrorHelperCore() { |
| 125 } | 150 } |
| 126 | 151 |
| 127 void NetErrorHelperCore::OnStop() { | 152 void NetErrorHelperCore::OnStop() { |
| 128 // On stop, cancel loading the alternate error page, and prevent any pending | 153 // On stop, cancel loading the alternate error page, and prevent any pending |
| 129 // error page load from starting a new error page load. Swapping in the error | 154 // error page load from starting a new error page load. Swapping in the error |
| 130 // page when it's finished loading could abort the navigation, otherwise. | 155 // page when it's finished loading could abort the navigation, otherwise. |
| 131 if (committed_error_page_info_) | 156 if (committed_error_page_info_) |
| 132 committed_error_page_info_->alternate_error_page_url = GURL(); | 157 committed_error_page_info_->alternate_error_page_url = GURL(); |
| 133 if (pending_error_page_info_) | 158 if (pending_error_page_info_) |
| 134 pending_error_page_info_->alternate_error_page_url = GURL(); | 159 pending_error_page_info_->alternate_error_page_url = GURL(); |
| 135 delegate_->CancelFetchErrorPage(); | 160 delegate_->CancelFetchErrorPage(); |
| 161 if (auto_reload_timer_.get()) | |
| 162 auto_reload_timer_->Stop(); | |
|
mmenke
2014/02/05 23:31:43
Can't these two lines just be replaced with "auto_
mmenke
2014/02/05 23:31:43
auto_reload_count_ = 0;?
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 136 } | 163 } |
| 137 | 164 |
| 138 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { | 165 void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) { |
| 139 if (frame_type != MAIN_FRAME) | 166 if (frame_type != MAIN_FRAME) |
| 140 return; | 167 return; |
| 141 | 168 |
| 142 // If there's no pending error page information associated with the page load, | 169 // 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. | 170 // 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) { | 171 if (!pending_error_page_info_ || page_type != ERROR_PAGE) { |
| 145 OnStop(); | 172 OnStop(); |
| 146 } | 173 } |
| 147 } | 174 } |
| 148 | 175 |
| 149 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { | 176 void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) { |
| 150 if (frame_type != MAIN_FRAME) | 177 if (frame_type != MAIN_FRAME) |
| 151 return; | 178 return; |
| 152 | 179 |
| 153 committed_error_page_info_.reset(pending_error_page_info_.release()); | 180 committed_error_page_info_.reset(pending_error_page_info_.release()); |
| 154 } | 181 } |
| 155 | 182 |
| 156 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { | 183 void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) { |
| 157 if (frame_type != MAIN_FRAME || !committed_error_page_info_) | 184 if (frame_type != MAIN_FRAME || !committed_error_page_info_) { |
| 185 if (frame_type == MAIN_FRAME && !committed_error_page_info_) { | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
I find this cascade of conditionals confusing. Ma
Elly Fong-Jones
2014/02/10 21:42:06
Aha, good catch.
| |
| 186 // Just finished a non-error page load. Clear the auto-reload backoff | |
| 187 // count. | |
| 188 auto_reload_count_ = 0; | |
| 189 } | |
| 158 return; | 190 return; |
| 191 } | |
| 159 | 192 |
| 160 committed_error_page_info_->is_finished_loading = true; | 193 committed_error_page_info_->is_finished_loading = true; |
| 161 | 194 |
| 162 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { | 195 if (committed_error_page_info_->alternate_error_page_url.is_valid()) { |
| 163 // If there is another pending error page load, | 196 // If there is another pending error page load, |
| 164 // |replace_with_alternate_error_page| should have been set to false. | 197 // |replace_with_alternate_error_page| should have been set to false. |
| 165 DCHECK(!pending_error_page_info_); | 198 DCHECK(!pending_error_page_info_); |
| 166 DCHECK(!committed_error_page_info_->needs_dns_updates); | 199 DCHECK(!committed_error_page_info_->needs_dns_updates); |
| 167 GURL error_page_url; | 200 GURL error_page_url; |
| 168 delegate_->FetchErrorPage( | 201 delegate_->FetchErrorPage( |
| 169 committed_error_page_info_->alternate_error_page_url); | 202 committed_error_page_info_->alternate_error_page_url); |
| 203 } else if (auto_reload_enabled_) { | |
| 204 blink::WebURLError error = committed_error_page_info_->error; | |
| 205 bool was_failed_post = committed_error_page_info_->was_failed_post; | |
| 206 if (IsReloadableError(error) && !was_failed_post) | |
| 207 StartAutoReloadTimer(); | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
Hmmm. My preference would be to only start the ti
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 208 else | |
| 209 auto_reload_count_ = 0; | |
| 170 } | 210 } |
| 171 | 211 |
| 172 if (!committed_error_page_info_->needs_dns_updates || | 212 if (!committed_error_page_info_->needs_dns_updates || |
| 173 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { | 213 last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) { |
| 174 return; | 214 return; |
| 175 } | 215 } |
| 176 DVLOG(1) << "Error page finished loading; sending saved status."; | 216 DVLOG(1) << "Error page finished loading; sending saved status."; |
| 177 UpdateErrorPage(); | 217 UpdateErrorPage(); |
| 178 } | 218 } |
| 179 | 219 |
| (...skipping 129 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 309 } | 349 } |
| 310 | 350 |
| 311 blink::WebURLError updated_error; | 351 blink::WebURLError updated_error; |
| 312 updated_error.domain = blink::WebString::fromUTF8( | 352 updated_error.domain = blink::WebString::fromUTF8( |
| 313 chrome_common_net::kDnsProbeErrorDomain); | 353 chrome_common_net::kDnsProbeErrorDomain); |
| 314 updated_error.reason = last_probe_status_; | 354 updated_error.reason = last_probe_status_; |
| 315 updated_error.unreachableURL = error.unreachableURL; | 355 updated_error.unreachableURL = error.unreachableURL; |
| 316 | 356 |
| 317 return updated_error; | 357 return updated_error; |
| 318 } | 358 } |
| 359 | |
| 360 void NetErrorHelperCore::AutoReload() { | |
| 361 if (!committed_error_page_info_) { | |
| 362 return; | |
| 363 } | |
| 364 delegate_->ReloadPage(); | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
Confirming, just because I'm not sure which of the
| |
| 365 } | |
| 366 | |
| 367 void NetErrorHelperCore::StartAutoReloadTimer() { | |
| 368 base::TimeDelta delay = GetAutoReloadBackoff(auto_reload_count_); | |
| 369 auto_reload_count_++; | |
| 370 auto_reload_timer_.reset(delegate_->NewMockableOneShotTimer()); | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
It looks to me as if OneShotTimer can be re-used (
Elly Fong-Jones
2014/02/10 21:42:06
Good idea, I like it.
Done.
| |
| 371 auto_reload_timer_->Start(FROM_HERE, delay, | |
| 372 base::Bind(&NetErrorHelperCore::AutoReload, | |
| 373 base::Unretained(this))); | |
| 374 } | |
| 375 | |
| 376 bool NetErrorHelperCore::IsAutoReloading() const { | |
| 377 return auto_reload_count_ != 0; | |
| 378 } | |
| 379 | |
| 380 void NetErrorHelperCore::NetworkStateChanged(bool online) { | |
| 381 if (online && auto_reload_timer_->IsRunning()) { | |
|
Randy Smith (Not in Mondays)
2014/02/06 16:47:16
Should we stop the timer if the change was to offl
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 382 // start over | |
|
mmenke
2014/02/05 23:31:43
nit: Start over. (Per style guide, comments shoul
Elly Fong-Jones
2014/02/10 21:42:06
Done.
| |
| 383 auto_reload_count_ = 0; | |
| 384 auto_reload_timer_->Stop(); | |
| 385 StartAutoReloadTimer(); | |
| 386 } | |
| 387 } | |
| OLD | NEW |