summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/net
diff options
context:
space:
mode:
authormmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-13 23:48:29 +0000
committermmenke@chromium.org <mmenke@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2014-01-13 23:48:29 +0000
commit3d612f5775f80b7d8f91a37c44aebc9c83faf3e6 (patch)
tree54db55c4e5cc4db841e86207da662d6d6ad07d04 /chrome/renderer/net
parent8f7c18685dd79743fc8aa8098b7ddf139730d7cc (diff)
downloadchromium_src-3d612f5775f80b7d8f91a37c44aebc9c83faf3e6.zip
chromium_src-3d612f5775f80b7d8f91a37c44aebc9c83faf3e6.tar.gz
chromium_src-3d612f5775f80b7d8f91a37c44aebc9c83faf3e6.tar.bz2
Move LinkDoctor out of content and into chrome.
This is in preparation for using the new LinkDoctor API. BUG=308232 R=darin@chromium.org, tsepez@chromium.org, ttuttle@chromium.org Review URL: https://codereview.chromium.org/67283002 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@244611 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/net')
-rw-r--r--chrome/renderer/net/net_error_helper.cc258
-rw-r--r--chrome/renderer/net/net_error_helper.h94
-rw-r--r--chrome/renderer/net/net_error_helper_core.cc318
-rw-r--r--chrome/renderer/net/net_error_helper_core.h131
-rw-r--r--chrome/renderer/net/net_error_helper_core_unittest.cc1304
-rw-r--r--chrome/renderer/net/net_error_helper_unittest.cc412
6 files changed, 1895 insertions, 622 deletions
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index 088b0ad..2c16add 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -18,18 +18,23 @@
#include "content/public/renderer/content_renderer_client.h"
#include "content/public/renderer/render_thread.h"
#include "content/public/renderer/render_view.h"
+#include "content/public/renderer/resource_fetcher.h"
+#include "grit/renderer_resources.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_message_macros.h"
-#include "net/base/net_errors.h"
#include "third_party/WebKit/public/platform/WebURL.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
#include "third_party/WebKit/public/platform/WebURLRequest.h"
+#include "third_party/WebKit/public/platform/WebURLResponse.h"
#include "third_party/WebKit/public/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebFrame.h"
+#include "third_party/WebKit/public/web/WebView.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "ui/base/webui/jstemplate_builder.h"
#include "url/gurl.h"
using base::JSONWriter;
using chrome_common_net::DnsProbeStatus;
-using chrome_common_net::DnsProbeStatusIsFinished;
using chrome_common_net::DnsProbeStatusToString;
using content::RenderThread;
using content::RenderView;
@@ -38,123 +43,49 @@ using content::kUnreachableWebDataURL;
namespace {
-bool IsLoadingErrorPage(blink::WebFrame* frame) {
- GURL url = frame->provisionalDataSource()->request().url();
- if (!url.is_valid())
- return false;
- return url.spec() == kUnreachableWebDataURL;
-}
+// Number of seconds to wait for the alternate error page server. If it takes
+// too long, just use the local error page.
+static const int kAlterErrorPageFetchTimeoutSec = 3000;
-bool IsMainFrame(const blink::WebFrame* frame) {
- return !frame->parent();
+NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) {
+ GURL url = frame->provisionalDataSource()->request().url();
+ if (!url.is_valid() || url.spec() != kUnreachableWebDataURL)
+ return NetErrorHelperCore::NON_ERROR_PAGE;
+ return NetErrorHelperCore::ERROR_PAGE;
}
-// Returns whether |net_error| is a DNS-related error (and therefore whether
-// the tab helper should start a DNS probe after receiving it.)
-bool IsDnsError(const blink::WebURLError& error) {
- return std::string(error.domain.utf8()) == net::kErrorDomain &&
- (error.reason == net::ERR_NAME_NOT_RESOLVED ||
- error.reason == net::ERR_NAME_RESOLUTION_FAILED);
+NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) {
+ if (!frame->parent())
+ return NetErrorHelperCore::MAIN_FRAME;
+ return NetErrorHelperCore::SUB_FRAME;
}
} // namespace
NetErrorHelper::NetErrorHelper(RenderView* render_view)
: RenderViewObserver(render_view),
- last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE),
- last_start_was_error_page_(false),
- last_fail_was_dns_error_(false),
- forwarding_probe_results_(false),
- is_failed_post_(false) {
+ content::RenderViewObserverTracker<NetErrorHelper>(render_view),
+ core_(this) {
}
NetErrorHelper::~NetErrorHelper() {
}
void NetErrorHelper::DidStartProvisionalLoad(blink::WebFrame* frame) {
- OnStartLoad(IsMainFrame(frame), IsLoadingErrorPage(frame));
-}
-
-void NetErrorHelper::DidFailProvisionalLoad(blink::WebFrame* frame,
- const blink::WebURLError& error) {
- const bool main_frame = IsMainFrame(frame);
- const bool dns_error = IsDnsError(error);
-
- OnFailLoad(main_frame, dns_error);
-
- if (main_frame && dns_error) {
- last_error_ = error;
-
- blink::WebDataSource* data_source = frame->provisionalDataSource();
- const blink::WebURLRequest& failed_request = data_source->request();
- is_failed_post_ = EqualsASCII(failed_request.httpMethod(), "POST");
- }
+ core_.OnStartLoad(GetFrameType(frame), GetLoadingPageType(frame));
}
void NetErrorHelper::DidCommitProvisionalLoad(blink::WebFrame* frame,
bool is_new_navigation) {
- OnCommitLoad(IsMainFrame(frame));
+ core_.OnCommitLoad(GetFrameType(frame));
}
void NetErrorHelper::DidFinishLoad(blink::WebFrame* frame) {
- OnFinishLoad(IsMainFrame(frame));
+ core_.OnFinishLoad(GetFrameType(frame));
}
-void NetErrorHelper::OnStartLoad(bool is_main_frame, bool is_error_page) {
- DVLOG(1) << "OnStartLoad(is_main_frame=" << is_main_frame
- << ", is_error_page=" << is_error_page << ")";
- if (!is_main_frame)
- return;
-
- last_start_was_error_page_ = is_error_page;
-}
-
-void NetErrorHelper::OnFailLoad(bool is_main_frame, bool is_dns_error) {
- DVLOG(1) << "OnFailLoad(is_main_frame=" << is_main_frame
- << ", is_dns_error=" << is_dns_error << ")";
-
- if (!is_main_frame)
- return;
-
- last_fail_was_dns_error_ = is_dns_error;
-
- if (is_dns_error) {
- last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE;
- // If the helper was forwarding probe results and another DNS error has
- // occurred, stop forwarding probe results until the corresponding (new)
- // error page loads.
- forwarding_probe_results_ = false;
- }
-}
-
-void NetErrorHelper::OnCommitLoad(bool is_main_frame) {
- DVLOG(1) << "OnCommitLoad(is_main_frame=" << is_main_frame << ")";
-
- if (!is_main_frame)
- return;
-
- // Stop forwarding results. If the page is a DNS error page, forwarding
- // will resume once the page is loaded; if not, it should stay stopped until
- // the next DNS error page.
- forwarding_probe_results_ = false;
-}
-
-void NetErrorHelper::OnFinishLoad(bool is_main_frame) {
- DVLOG(1) << "OnFinishLoad(is_main_frame=" << is_main_frame << ")";
-
- if (!is_main_frame)
- return;
-
- // If a DNS error page just finished loading, start forwarding probe results
- // to it.
- forwarding_probe_results_ =
- last_fail_was_dns_error_ && last_start_was_error_page_;
-
- if (forwarding_probe_results_ &&
- last_probe_status_ != chrome_common_net::DNS_PROBE_POSSIBLE) {
- DVLOG(1) << "Error page finished loading; sending saved status.";
- UpdateErrorPage();
- }
+void NetErrorHelper::OnStop() {
+ core_.OnStop();
}
bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
@@ -162,63 +93,59 @@ bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
+ IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL);
IPC_MESSAGE_UNHANDLED(handled = false)
IPC_END_MESSAGE_MAP()
return handled;
}
-// static
-bool NetErrorHelper::GetErrorStringsForDnsProbe(
+void NetErrorHelper::GetErrorHTML(
blink::WebFrame* frame,
const blink::WebURLError& error,
bool is_failed_post,
- const std::string& locale,
- const std::string& accept_languages,
- base::DictionaryValue* error_strings) {
- if (!IsMainFrame(frame))
- return false;
-
- if (!IsDnsError(error))
- return false;
-
- // Get the strings for a fake "DNS probe possible" error.
- LocalizedError::GetStrings(
- chrome_common_net::DNS_PROBE_POSSIBLE,
- chrome_common_net::kDnsProbeErrorDomain,
- error.unreachableURL,
- is_failed_post, locale, accept_languages, error_strings);
- return true;
+ std::string* error_html) {
+ core_.GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html);
+}
+
+void NetErrorHelper::GenerateLocalizedErrorPage(const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html) const {
+ error_html->clear();
+
+ int resource_id = IDR_NET_ERROR_HTML;
+ const base::StringPiece template_html(
+ ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
+ if (template_html.empty()) {
+ NOTREACHED() << "unable to load template.";
+ } else {
+ base::DictionaryValue error_strings;
+ LocalizedError::GetStrings(error.reason, error.domain.utf8(),
+ error.unreachableURL, is_failed_post,
+ RenderThread::Get()->GetLocale(),
+ render_view()->GetAcceptLanguages(),
+ &error_strings);
+ // "t" is the id of the template's root node.
+ *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t");
+ }
}
-void NetErrorHelper::OnNetErrorInfo(int status_num) {
- DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX);
-
- DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num);
-
- DnsProbeStatus status = static_cast<DnsProbeStatus>(status_num);
- DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status);
-
- if (!(last_fail_was_dns_error_ || forwarding_probe_results_)) {
- DVLOG(1) << "Ignoring NetErrorInfo: no DNS error";
+void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html,
+ const GURL& failed_url) {
+ blink::WebView* web_view = render_view()->GetWebView();
+ if (!web_view)
return;
- }
-
- last_probe_status_ = status;
-
- if (forwarding_probe_results_)
- UpdateErrorPage();
+ blink::WebFrame* frame = web_view->mainFrame();
+ frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true);
}
-void NetErrorHelper::UpdateErrorPage() {
- DCHECK(forwarding_probe_results_);
-
- blink::WebURLError error = GetUpdatedError();
+void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error,
+ bool is_failed_post) {
base::DictionaryValue error_strings;
LocalizedError::GetStrings(error.reason,
error.domain.utf8(),
error.unreachableURL,
- is_failed_post_,
+ is_failed_post,
RenderThread::Get()->GetLocale(),
render_view()->GetAcceptLanguages(),
&error_strings);
@@ -234,31 +161,54 @@ void NetErrorHelper::UpdateErrorPage() {
return;
}
- DVLOG(1) << "Updating error page with status "
- << chrome_common_net::DnsProbeStatusToString(last_probe_status_);
- DVLOG(2) << "New strings: " << js;
-
base::string16 frame_xpath;
render_view()->EvaluateScript(frame_xpath, js16, 0, false);
+}
+
+void NetErrorHelper::FetchErrorPage(const GURL& url) {
+ DCHECK(!alt_error_page_fetcher_.get());
- UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus",
- last_probe_status_,
- chrome_common_net::DNS_PROBE_MAX);
+ blink::WebView* web_view = render_view()->GetWebView();
+ if (!web_view)
+ return;
+ blink::WebFrame* frame = web_view->mainFrame();
+
+ alt_error_page_fetcher_.reset(
+ content::ResourceFetcher::Create(
+ url, frame, blink::WebURLRequest::TargetIsMainFrame,
+ base::Bind(&NetErrorHelper::OnAlternateErrorPageRetrieved,
+ base::Unretained(this))));
+
+ alt_error_page_fetcher_->SetTimeout(
+ base::TimeDelta::FromSeconds(kAlterErrorPageFetchTimeoutSec));
}
-blink::WebURLError NetErrorHelper::GetUpdatedError() const {
- // If a probe didn't run or wasn't conclusive, restore the original error.
- if (last_probe_status_ == chrome_common_net::DNS_PROBE_NOT_RUN ||
- last_probe_status_ ==
- chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE) {
- return last_error_;
- }
+void NetErrorHelper::CancelFetchErrorPage() {
+ alt_error_page_fetcher_.reset();
+}
+
+void NetErrorHelper::OnNetErrorInfo(int status_num) {
+ DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX);
+
+ DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num);
- blink::WebURLError error;
- error.domain = blink::WebString::fromUTF8(
- chrome_common_net::kDnsProbeErrorDomain);
- error.reason = last_probe_status_;
- error.unreachableURL = last_error_.unreachableURL;
+ core_.OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num));
+}
- return error;
+void NetErrorHelper::OnSetAltErrorPageURL(const GURL& alt_error_page_url) {
+ core_.set_alt_error_page_url(alt_error_page_url);
+}
+
+void NetErrorHelper::OnAlternateErrorPageRetrieved(
+ const blink::WebURLResponse& response,
+ const std::string& data) {
+ // The fetcher may only be deleted after |data| is passed to |core_|. Move
+ // it to a temporary to prevent any potential re-entrancy issues.
+ scoped_ptr<content::ResourceFetcher> fetcher(
+ alt_error_page_fetcher_.release());
+ if (!response.isNull() && response.httpStatusCode() == 200) {
+ core_.OnAlternateErrorPageFetched(data);
+ } else {
+ core_.OnAlternateErrorPageFetched("");
+ }
}
diff --git a/chrome/renderer/net/net_error_helper.h b/chrome/renderer/net/net_error_helper.h
index 3f464b8..2af13da 100644
--- a/chrome/renderer/net/net_error_helper.h
+++ b/chrome/renderer/net/net_error_helper.h
@@ -8,34 +8,39 @@
#include <string>
#include "chrome/common/net/net_error_info.h"
+#include "chrome/renderer/net/net_error_helper_core.h"
#include "content/public/renderer/render_view_observer.h"
-#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "content/public/renderer/render_view_observer_tracker.h"
-namespace base {
-class DictionaryValue;
+class GURL;
+
+namespace content {
+class ResourceFetcher;
}
namespace blink {
class WebFrame;
+class WebURLResponse;
+struct WebURLError;
}
// Listens for NetErrorInfo messages from the NetErrorTabHelper on the
// browser side and updates the error page with more details (currently, just
// DNS probe results) if/when available.
-class NetErrorHelper : public content::RenderViewObserver {
+class NetErrorHelper
+ : public content::RenderViewObserver,
+ public content::RenderViewObserverTracker<NetErrorHelper>,
+ public NetErrorHelperCore::Delegate {
public:
explicit NetErrorHelper(content::RenderView* render_view);
virtual ~NetErrorHelper();
// RenderViewObserver implementation.
virtual void DidStartProvisionalLoad(blink::WebFrame* frame) OVERRIDE;
- virtual void DidFailProvisionalLoad(
- blink::WebFrame* frame,
- const blink::WebURLError& error) OVERRIDE;
- virtual void DidCommitProvisionalLoad(
- blink::WebFrame* frame,
- bool is_new_navigation) OVERRIDE;
+ virtual void DidCommitProvisionalLoad(blink::WebFrame* frame,
+ bool is_new_navigation) OVERRIDE;
virtual void DidFinishLoad(blink::WebFrame* frame) OVERRIDE;
+ virtual void OnStop() OVERRIDE;
// IPC::Listener implementation.
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -45,58 +50,35 @@ class NetErrorHelper : public content::RenderViewObserver {
// |is_failed_post|, and |locale| with suitable strings and returns true.
// If not, returns false, in which case the caller should look up error
// strings directly using LocalizedError::GetNavigationErrorStrings.
- static bool GetErrorStringsForDnsProbe(
- blink::WebFrame* frame,
- const blink::WebURLError& error,
- bool is_failed_post,
- const std::string& locale,
- const std::string& accept_languages,
- base::DictionaryValue* error_strings);
-
- protected:
- // These methods handle tracking the actual state of the page; this allows
- // unit-testing of the state tracking without having to mock out WebFrames
- // and such.
- void OnStartLoad(bool is_main_frame, bool is_error_page);
- void OnFailLoad(bool is_main_frame, bool is_dns_error);
- void OnCommitLoad(bool is_main_frame);
- void OnFinishLoad(bool is_main_frame);
-
- void OnNetErrorInfo(int status);
-
- // |UpdateErrorPage| is virtual so it can be mocked out in the unittest.
- virtual void UpdateErrorPage();
-
- // The last DnsProbeStatus received from the browser.
- chrome_common_net::DnsProbeStatus last_probe_status_;
+ //
+ // Updates the NetErrorHelper with the assumption the page will be loaded
+ // immediately.
+ void GetErrorHTML(blink::WebFrame* frame,
+ const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html);
private:
- blink::WebURLError GetUpdatedError() const;
-
- // Whether the last provisional load started was for an error page.
- bool last_start_was_error_page_;
+ // NetErrorHelperCore::Delegate implementation:
+ virtual void GenerateLocalizedErrorPage(const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* html) const OVERRIDE;
+ virtual void LoadErrorPageInMainFrame(const std::string& html,
+ const GURL& failed_url) OVERRIDE;
+ virtual void UpdateErrorPage(const blink::WebURLError& error,
+ bool is_failed_post) OVERRIDE;
+ virtual void FetchErrorPage(const GURL& url) OVERRIDE;
+ virtual void CancelFetchErrorPage() OVERRIDE;
- // Whether the last provisional load failure failed with a DNS error.
- bool last_fail_was_dns_error_;
+ void OnNetErrorInfo(int status);
+ void OnSetAltErrorPageURL(const GURL& alternate_error_page_url);
- // Ideally, this would be simply "last_commit_was_dns_error_page_".
- //
- // Unfortunately, that breaks if two DNS errors occur in a row; after the
- // second failure, but before the second page commits, the helper can receive
- // probe results. If all it knows is that the last commit was a DNS error
- // page, it will cheerfully forward the results for the second probe to the
- // first page.
- //
- // Thus, the semantics of this flag are a little weird. It is set whenever
- // a DNS error page commits, and cleared whenever any other page commits,
- // but it is also cleared whenever a DNS error occurs, to prevent the race
- // described above.
- bool forwarding_probe_results_;
+ void OnAlternateErrorPageRetrieved(const blink::WebURLResponse& response,
+ const std::string& data);
- // The last main frame error seen by the helper.
- blink::WebURLError last_error_;
+ scoped_ptr<content::ResourceFetcher> alt_error_page_fetcher_;
- bool is_failed_post_;
+ NetErrorHelperCore core_;
};
#endif // CHROME_RENDERER_NET_NET_ERROR_HELPER_H_
diff --git a/chrome/renderer/net/net_error_helper_core.cc b/chrome/renderer/net/net_error_helper_core.cc
new file mode 100644
index 0000000..55cb771
--- /dev/null
+++ b/chrome/renderer/net/net_error_helper_core.cc
@@ -0,0 +1,318 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/net/net_error_helper_core.h"
+
+#include <string>
+
+#include "base/metrics/histogram.h"
+#include "chrome/common/localized_error.h"
+#include "net/base/escape.h"
+#include "net/base/net_errors.h"
+#include "third_party/WebKit/public/platform/WebString.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+#include "url/gurl.h"
+
+namespace {
+
+// Returns whether |net_error| is a DNS-related error (and therefore whether
+// the tab helper should start a DNS probe after receiving it.)
+bool IsDnsError(const blink::WebURLError& error) {
+ return error.domain.utf8() == net::kErrorDomain &&
+ (error.reason == net::ERR_NAME_NOT_RESOLVED ||
+ error.reason == net::ERR_NAME_RESOLUTION_FAILED);
+}
+
+// If an alternate error page should be retrieved remotely for a main frame load
+// that failed with |error|, returns true and sets |error_page_url| to the URL
+// of the remote error page.
+bool GetErrorPageURL(const blink::WebURLError& error,
+ const GURL& alt_error_page_url,
+ GURL* error_page_url) {
+ if (!alt_error_page_url.is_valid())
+ return false;
+
+ // Parameter to send to the error page indicating the error type.
+ std::string error_param;
+
+ std::string domain = error.domain.utf8();
+ if (domain == "http" && error.reason == 404) {
+ error_param = "http404";
+ } else if (IsDnsError(error)) {
+ error_param = "dnserror";
+ } else if (domain == net::kErrorDomain &&
+ (error.reason == net::ERR_CONNECTION_FAILED ||
+ error.reason == net::ERR_CONNECTION_REFUSED ||
+ error.reason == net::ERR_ADDRESS_UNREACHABLE ||
+ error.reason == net::ERR_CONNECTION_TIMED_OUT)) {
+ error_param = "connectionfailure";
+ } else {
+ return false;
+ }
+
+ // Don't use the Link Doctor for HTTPS (for privacy reasons).
+ GURL unreachable_url(error.unreachableURL);
+ if (unreachable_url.SchemeIsSecure())
+ return false;
+
+ // Sanitize the unreachable URL.
+ GURL::Replacements remove_params;
+ remove_params.ClearUsername();
+ remove_params.ClearPassword();
+ remove_params.ClearQuery();
+ remove_params.ClearRef();
+ // TODO(yuusuke): change to net::FormatUrl when Link Doctor becomes
+ // unicode-capable.
+ std::string spec_to_send =
+ unreachable_url.ReplaceComponents(remove_params).spec();
+
+ // Notify Link Doctor of the url truncation by sending of "?" at the end.
+ if (unreachable_url.has_query())
+ spec_to_send.append("?");
+
+ std::string params(alt_error_page_url.query());
+ params.append("&url=");
+ params.append(net::EscapeQueryParamValue(spec_to_send, true));
+ params.append("&sourceid=chrome");
+ params.append("&error=");
+ params.append(error_param);
+
+ // Build the final url to request.
+ GURL::Replacements link_doctor_params;
+ link_doctor_params.SetQueryStr(params);
+ *error_page_url = alt_error_page_url.ReplaceComponents(link_doctor_params);
+ return true;
+}
+
+} // namespace
+
+struct NetErrorHelperCore::ErrorPageInfo {
+ ErrorPageInfo(blink::WebURLError error, bool was_failed_post)
+ : error(error),
+ was_failed_post(was_failed_post),
+ needs_dns_updates(false),
+ is_finished_loading(false) {
+ }
+
+ // Information about the failed page load.
+ blink::WebURLError error;
+ bool was_failed_post;
+
+ // Information about the status of the error page.
+
+ // True if a page is a DNS error page and has not yet received a final DNS
+ // probe status.
+ bool needs_dns_updates;
+
+ // URL of an alternate error page to repace this error page with, if it's a
+ // valid URL. Request will be issued when the error page finishes loading.
+ // This is done on load complete to ensure that there are two complete loads
+ // for tests to wait for.
+ GURL alternate_error_page_url;
+
+ // True if a page has completed loading, at which point it can receive
+ // updates.
+ bool is_finished_loading;
+};
+
+NetErrorHelperCore::NetErrorHelperCore(Delegate* delegate)
+ : delegate_(delegate),
+ last_probe_status_(chrome_common_net::DNS_PROBE_POSSIBLE) {
+}
+
+NetErrorHelperCore::~NetErrorHelperCore() {
+}
+
+void NetErrorHelperCore::OnStop() {
+ // On stop, cancel loading the alternate error page, and prevent any pending
+ // error page load from starting a new error page load. Swapping in the error
+ // page when it's finished loading could abort the navigation, otherwise.
+ if (committed_error_page_info_)
+ committed_error_page_info_->alternate_error_page_url = GURL();
+ if (pending_error_page_info_)
+ pending_error_page_info_->alternate_error_page_url = GURL();
+ delegate_->CancelFetchErrorPage();
+}
+
+void NetErrorHelperCore::OnStartLoad(FrameType frame_type, PageType page_type) {
+ if (frame_type != MAIN_FRAME)
+ return;
+
+ // If there's no pending error page information associated with the page load,
+ // or the new page is not an error page, then reset pending error page state.
+ if (!pending_error_page_info_ || page_type != ERROR_PAGE) {
+ OnStop();
+ }
+}
+
+void NetErrorHelperCore::OnCommitLoad(FrameType frame_type) {
+ if (frame_type != MAIN_FRAME)
+ return;
+
+ committed_error_page_info_.reset(pending_error_page_info_.release());
+}
+
+void NetErrorHelperCore::OnFinishLoad(FrameType frame_type) {
+ if (frame_type != MAIN_FRAME || !committed_error_page_info_)
+ return;
+
+ committed_error_page_info_->is_finished_loading = true;
+
+ if (committed_error_page_info_->alternate_error_page_url.is_valid()) {
+ // If there is another pending error page load,
+ // |replace_with_alternate_error_page| should have been set to false.
+ DCHECK(!pending_error_page_info_);
+ DCHECK(!committed_error_page_info_->needs_dns_updates);
+ GURL error_page_url;
+ delegate_->FetchErrorPage(
+ committed_error_page_info_->alternate_error_page_url);
+ }
+
+ if (!committed_error_page_info_->needs_dns_updates ||
+ last_probe_status_ == chrome_common_net::DNS_PROBE_POSSIBLE) {
+ return;
+ }
+ DVLOG(1) << "Error page finished loading; sending saved status.";
+ UpdateErrorPage();
+}
+
+void NetErrorHelperCore::GetErrorHTML(
+ FrameType frame_type,
+ const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html) {
+ if (frame_type == MAIN_FRAME) {
+ // If an alternate error page was going to be fetched, that should have been
+ // cancelled by loading a new page load (Which has now failed to load).
+ DCHECK(!committed_error_page_info_ ||
+ !committed_error_page_info_->alternate_error_page_url.is_valid());
+
+ // The last probe status needs to be reset if this is a DNS error. This
+ // means that if a DNS error page is committed but has not yet finished
+ // loading, a DNS probe status scheduled to be sent to it may be thrown
+ // out, but since the new error page should trigger a new DNS probe, it
+ // will just get the results for the next page load.
+ if (IsDnsError(error))
+ last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE;
+
+ GURL error_page_url;
+ if (GetErrorPageURL(error, alt_error_page_url_, &error_page_url)) {
+ pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post));
+ pending_error_page_info_->alternate_error_page_url = error_page_url;
+ return;
+ }
+ }
+
+ GenerateLocalErrorPage(frame_type, error, is_failed_post, error_html);
+}
+
+void NetErrorHelperCore::GenerateLocalErrorPage(
+ FrameType frame_type,
+ const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html) {
+ if (frame_type == MAIN_FRAME) {
+ pending_error_page_info_.reset(new ErrorPageInfo(error, is_failed_post));
+ if (IsDnsError(error)) {
+ // This is not strictly necessary, but waiting for a new status to be
+ // sent as a result of the DidFinishLoading call keeps the histograms
+ // consistent with older versions of the code, at no real cost.
+ last_probe_status_ = chrome_common_net::DNS_PROBE_POSSIBLE;
+
+ delegate_->GenerateLocalizedErrorPage(
+ GetUpdatedError(error), is_failed_post, error_html);
+ pending_error_page_info_->needs_dns_updates = true;
+ return;
+ }
+ }
+ delegate_->GenerateLocalizedErrorPage(error, is_failed_post, error_html);
+}
+
+void NetErrorHelperCore::OnNetErrorInfo(
+ chrome_common_net::DnsProbeStatus status) {
+ DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, status);
+
+ last_probe_status_ = status;
+
+ if (!committed_error_page_info_ ||
+ !committed_error_page_info_->needs_dns_updates ||
+ !committed_error_page_info_->is_finished_loading) {
+ return;
+ }
+
+ UpdateErrorPage();
+}
+
+void NetErrorHelperCore::UpdateErrorPage() {
+ DCHECK(committed_error_page_info_->needs_dns_updates);
+ DCHECK(committed_error_page_info_->is_finished_loading);
+ DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_probe_status_);
+
+ UMA_HISTOGRAM_ENUMERATION("DnsProbe.ErrorPageUpdateStatus",
+ last_probe_status_,
+ chrome_common_net::DNS_PROBE_MAX);
+ // Every status other than DNS_PROBE_POSSIBLE and DNS_PROBE_STARTED is a
+ // final status code. Once one is reached, the page does not need further
+ // updates.
+ if (last_probe_status_ != chrome_common_net::DNS_PROBE_STARTED)
+ committed_error_page_info_->needs_dns_updates = false;
+
+ delegate_->UpdateErrorPage(
+ GetUpdatedError(committed_error_page_info_->error),
+ committed_error_page_info_->was_failed_post);
+}
+
+void NetErrorHelperCore::OnAlternateErrorPageFetched(const std::string& data) {
+ // Alternate error page load only starts when an error page finishes loading,
+ // and is cancelled with a new load
+ DCHECK(!pending_error_page_info_);
+ DCHECK(committed_error_page_info_->is_finished_loading);
+
+ const std::string* error_html = NULL;
+ std::string generated_html;
+ if (!data.empty()) {
+ // If the request succeeded, use the response in place of a generated error
+ // page.
+ pending_error_page_info_.reset(
+ new ErrorPageInfo(committed_error_page_info_->error,
+ committed_error_page_info_->was_failed_post));
+ error_html = &data;
+ } else {
+ // Otherwise, generate a local error page. |pending_error_page_info_| will
+ // be set by GenerateLocalErrorPage.
+ GenerateLocalErrorPage(MAIN_FRAME,
+ committed_error_page_info_->error,
+ committed_error_page_info_->was_failed_post,
+ &generated_html);
+ error_html = &generated_html;
+ }
+
+ // |error_page_info| may have been destroyed by this point, since
+ // |pending_error_page_info_| was set to a new ErrorPageInfo.
+
+ // TODO(mmenke): Once the new API is in place, look into replacing this
+ // double page load by just updating the error page, like DNS
+ // probes do.
+ delegate_->LoadErrorPageInMainFrame(
+ *error_html,
+ pending_error_page_info_->error.unreachableURL);
+}
+
+blink::WebURLError NetErrorHelperCore::GetUpdatedError(
+ const blink::WebURLError& error) const {
+ // If a probe didn't run or wasn't conclusive, restore the original error.
+ if (last_probe_status_ == chrome_common_net::DNS_PROBE_NOT_RUN ||
+ last_probe_status_ ==
+ chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE) {
+ return error;
+ }
+
+ blink::WebURLError updated_error;
+ updated_error.domain = blink::WebString::fromUTF8(
+ chrome_common_net::kDnsProbeErrorDomain);
+ updated_error.reason = last_probe_status_;
+ updated_error.unreachableURL = error.unreachableURL;
+
+ return updated_error;
+}
diff --git a/chrome/renderer/net/net_error_helper_core.h b/chrome/renderer/net/net_error_helper_core.h
new file mode 100644
index 0000000..cfbc8a1
--- /dev/null
+++ b/chrome/renderer/net/net_error_helper_core.h
@@ -0,0 +1,131 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
+#define CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
+
+#include <string>
+
+#include "base/memory/weak_ptr.h"
+#include "chrome/common/net/net_error_info.h"
+#include "url/gurl.h"
+
+namespace blink {
+struct WebURLError;
+}
+
+// Class that contains the logic for how the NetErrorHelper. This allows for
+// testing the logic without a RenderView or WebFrame, which are difficult to
+// mock, and for testing races which are impossible to reliably reproduce
+// with real RenderViews or WebFrames.
+class NetErrorHelperCore {
+ public:
+ enum FrameType {
+ MAIN_FRAME,
+ SUB_FRAME,
+ };
+
+ enum PageType {
+ NON_ERROR_PAGE,
+ ERROR_PAGE,
+ };
+
+ // The Delegate handles all interaction with the RenderView, WebFrame, and
+ // the network, as well as the generation of error pages.
+ class Delegate {
+ public:
+ // Generates an error page's HTML for the given error.
+ virtual void GenerateLocalizedErrorPage(const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* html) const = 0;
+
+ // Loads the given HTML in the main frame for use as an error page.
+ virtual void LoadErrorPageInMainFrame(const std::string& html,
+ const GURL& failed_url) = 0;
+
+ // Updates the currently displayed error page with a new error code. The
+ // currently displayed error page must have finished loading, and must have
+ // been generated by a call to GenerateLocalizedErrorPage.
+ virtual void UpdateErrorPage(const blink::WebURLError& error,
+ bool is_failed_post) = 0;
+
+ // Fetches an error page and calls into OnErrorPageFetched when done. Any
+ // previous fetch must either be canceled or finished before calling. Can't
+ // be called synchronously after a previous fetch completes.
+ virtual void FetchErrorPage(const GURL& url) = 0;
+
+ // Cancels an error page fetch. Does nothing if no fetch is ongoing.
+ virtual void CancelFetchErrorPage() = 0;
+
+ protected:
+ virtual ~Delegate() {}
+ };
+
+ explicit NetErrorHelperCore(Delegate* delegate);
+ ~NetErrorHelperCore();
+
+ // Examines |frame| and |error| to see if this is an error worthy of a DNS
+ // probe. If it is, initializes |error_strings| based on |error|,
+ // |is_failed_post|, and |locale| with suitable strings and returns true.
+ // If not, returns false, in which case the caller should look up error
+ // strings directly using LocalizedError::GetNavigationErrorStrings.
+ //
+ // Updates the NetErrorHelper with the assumption the page will be loaded
+ // immediately.
+ void GetErrorHTML(FrameType frame_type,
+ const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html);
+
+ // These methods handle tracking the actual state of the page.
+ void OnStartLoad(FrameType frame_type, PageType page_type);
+ void OnCommitLoad(FrameType frame_type);
+ void OnFinishLoad(FrameType frame_type);
+ void OnStop();
+
+ // Called when an error page have has been retrieved over the network. |html|
+ // must be an empty string on error.
+ void OnAlternateErrorPageFetched(const std::string& html);
+
+ // Notifies |this| that network error information from the browser process
+ // has been received.
+ void OnNetErrorInfo(chrome_common_net::DnsProbeStatus status);
+
+ void set_alt_error_page_url(const GURL& alt_error_page_url) {
+ alt_error_page_url_ = alt_error_page_url;
+ }
+
+ private:
+ struct ErrorPageInfo;
+
+ // Updates the currently displayed error page with a new error based on the
+ // most recently received DNS probe result. The page must have finished
+ // loading before this is called.
+ void UpdateErrorPage();
+
+ void GenerateLocalErrorPage(
+ FrameType frame_type,
+ const blink::WebURLError& error,
+ bool is_failed_post,
+ std::string* error_html);
+
+ blink::WebURLError GetUpdatedError(const blink::WebURLError& error) const;
+
+ Delegate* delegate_;
+
+ // The last DnsProbeStatus received from the browser.
+ chrome_common_net::DnsProbeStatus last_probe_status_;
+
+ // Information for the provisional / "pre-provisional" error page. NULL when
+ // there's no page pending, or the pending page is not an error page.
+ scoped_ptr<ErrorPageInfo> pending_error_page_info_;
+
+ // Information for the committed error page. NULL when the committed page is
+ // not an error page.
+ scoped_ptr<ErrorPageInfo> committed_error_page_info_;
+
+ GURL alt_error_page_url_;
+};
+
+#endif // CHROME_RENDERER_NET_NET_ERROR_HELPER_CORE_H_
diff --git a/chrome/renderer/net/net_error_helper_core_unittest.cc b/chrome/renderer/net/net_error_helper_core_unittest.cc
new file mode 100644
index 0000000..bd451d6
--- /dev/null
+++ b/chrome/renderer/net/net_error_helper_core_unittest.cc
@@ -0,0 +1,1304 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/net/net_error_helper_core.h"
+
+#include "base/logging.h"
+#include "base/strings/stringprintf.h"
+#include "chrome/common/net/net_error_info.h"
+#include "net/base/net_errors.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/public/platform/WebURLError.h"
+
+using blink::WebURLError;
+using chrome_common_net::DnsProbeStatus;
+using chrome_common_net::DnsProbeStatusToString;
+
+const char kFailedUrl[] = "http://failed/";
+const char kFailedHttpsUrl[] = "https://failed/";
+const char kLinkDoctorUrl[] = "http://link.doctor/";
+const char kLinkDoctorBody[] = "Link Doctor Body";
+
+// Creates a string from an error that is used as a mock locally generated
+// error page for that error.
+std::string ErrorToString(const WebURLError& error, bool is_failed_post) {
+ return base::StringPrintf("(%s, %s, %i, %s)",
+ error.unreachableURL.string().utf8().c_str(),
+ error.domain.utf8().c_str(), error.reason,
+ is_failed_post ? "POST" : "NOT POST");
+}
+
+WebURLError ProbeError(DnsProbeStatus status) {
+ WebURLError error;
+ error.unreachableURL = GURL(kFailedUrl);
+ error.domain = blink::WebString::fromUTF8(
+ chrome_common_net::kDnsProbeErrorDomain);
+ error.reason = status;
+ return error;
+}
+
+WebURLError NetError(net::Error net_error) {
+ WebURLError error;
+ error.unreachableURL = GURL(kFailedUrl);
+ error.domain = blink::WebString::fromUTF8(net::kErrorDomain);
+ error.reason = net_error;
+ return error;
+}
+
+WebURLError HttpError(int status_code) {
+ WebURLError error;
+ error.unreachableURL = GURL(kFailedUrl);
+ error.domain = blink::WebString::fromUTF8("http");
+ error.reason = status_code;
+ return error;
+}
+
+// Convenience functions that create an error string for a non-POST request.
+
+std::string ProbeErrorString(DnsProbeStatus status) {
+ return ErrorToString(ProbeError(status), false);
+}
+
+std::string NetErrorString(net::Error net_error) {
+ return ErrorToString(NetError(net_error), false);
+}
+
+class NetErrorHelperCoreTest : public testing::Test,
+ public NetErrorHelperCore::Delegate {
+ public:
+ NetErrorHelperCoreTest() : core_(this),
+ update_count_(0),
+ error_html_update_count_(0) {
+ }
+
+ virtual ~NetErrorHelperCoreTest() {
+ // No test finishes while an error page is being fetched.
+ EXPECT_FALSE(is_url_being_fetched());
+ }
+
+ NetErrorHelperCore& core() { return core_; }
+
+ const GURL& url_being_fetched() const { return url_being_fetched_; }
+ bool is_url_being_fetched() const { return !url_being_fetched_.is_empty(); }
+
+ const std::string& last_update_string() const { return last_update_string_; }
+ int update_count() const { return update_count_; }
+
+ const std::string& last_error_html() const { return last_error_html_; }
+ int error_html_update_count() const { return error_html_update_count_; }
+
+ void LinkDoctorLoadSuccess() {
+ LinkDoctorLoadFinished(kLinkDoctorBody);
+ }
+
+ void LinkDoctorLoadFailure() {
+ LinkDoctorLoadFinished("");
+ }
+
+ private:
+ void LinkDoctorLoadFinished(const std::string& result) {
+ url_being_fetched_ = GURL();
+ core().OnAlternateErrorPageFetched(result);
+ }
+
+ // NetErrorHelperCore::Delegate implementation:
+ virtual void GenerateLocalizedErrorPage(const WebURLError& error,
+ bool is_failed_post,
+ std::string* html) const OVERRIDE {
+ *html = ErrorToString(error, is_failed_post);
+ }
+
+ virtual void LoadErrorPageInMainFrame(const std::string& html,
+ const GURL& failed_url) OVERRIDE {
+ error_html_update_count_++;
+ last_error_html_ = html;
+ }
+
+ virtual void UpdateErrorPage(const WebURLError& error,
+ bool is_failed_post) OVERRIDE {
+ update_count_++;
+ last_error_html_ = ErrorToString(error, is_failed_post);
+ }
+
+ virtual void FetchErrorPage(const GURL& url) OVERRIDE {
+ EXPECT_TRUE(url_being_fetched_.is_empty());
+ EXPECT_TRUE(url.is_valid());
+ EXPECT_NE(std::string::npos, url.spec().find(kLinkDoctorUrl));
+
+ url_being_fetched_ = url;
+ }
+
+ virtual void CancelFetchErrorPage() OVERRIDE {
+ url_being_fetched_ = GURL();
+ }
+
+ NetErrorHelperCore core_;
+
+ GURL url_being_fetched_;
+
+ // Contains the information passed to the last call to UpdateErrorPage, as a
+ // string.
+ std::string last_update_string_;
+ // Number of times |last_update_string_| has been changed.
+ int update_count_;
+
+ // Contains the HTML set by the last call to LoadErrorPageInMainFrame.
+ std::string last_error_html_;
+ // Number of times |last_error_html_| has been changed.
+ int error_html_update_count_;
+};
+
+//------------------------------------------------------------------------------
+// Basic tests that don't update the error page for probes or load the Link
+// Doctor.
+//------------------------------------------------------------------------------
+
+TEST_F(NetErrorHelperCoreTest, Null) {
+}
+
+TEST_F(NetErrorHelperCoreTest, SuccessfulPageLoad) {
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+TEST_F(NetErrorHelperCoreTest, SuccessfulPageLoadWithLinkDoctor) {
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+TEST_F(NetErrorHelperCoreTest, MainFrameNonDnsError) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_CONNECTION_RESET), false, &html);
+ // Should have returned a local error page.
+ EXPECT_FALSE(html.empty());
+ EXPECT_EQ(NetErrorString(net::ERR_CONNECTION_RESET), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+TEST_F(NetErrorHelperCoreTest, MainFrameNonDnsErrorWithLinkDoctor) {
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_CONNECTION_RESET), false, &html);
+ // Should have returned a local error page.
+ EXPECT_FALSE(html.empty());
+ EXPECT_EQ(NetErrorString(net::ERR_CONNECTION_RESET), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Much like above tests, but with a bunch of spurious DNS status messages that
+// should have no effect.
+TEST_F(NetErrorHelperCoreTest, MainFrameNonDnsErrorSpuriousStatus) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_CONNECTION_RESET),
+ false, &html);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ // Should have returned a local error page.
+ EXPECT_FALSE(html.empty());
+ EXPECT_EQ(NetErrorString(net::ERR_CONNECTION_RESET), html);
+
+ // Error page loads.
+
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+TEST_F(NetErrorHelperCoreTest, SubFrameDnsError) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::SUB_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page.
+ EXPECT_EQ(NetErrorString(net::ERR_NAME_NOT_RESOLVED), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::SUB_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::SUB_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+TEST_F(NetErrorHelperCoreTest, SubFrameDnsErrorWithLinkDoctor) {
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::SUB_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page.
+ EXPECT_EQ(NetErrorString(net::ERR_NAME_NOT_RESOLVED), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::SUB_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::SUB_FRAME);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Much like above tests, but with a bunch of spurious DNS status messages that
+// should have no effect.
+TEST_F(NetErrorHelperCoreTest, SubFrameDnsErrorSpuriousStatus) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::SUB_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ // Should have returned a local error page.
+ EXPECT_EQ(NetErrorString(net::ERR_NAME_NOT_RESOLVED), html);
+
+ // Error page loads.
+
+ core().OnStartLoad(NetErrorHelperCore::SUB_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ core().OnCommitLoad(NetErrorHelperCore::SUB_FRAME);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ core().OnFinishLoad(NetErrorHelperCore::SUB_FRAME);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+//------------------------------------------------------------------------------
+// Tests for updating the error page in response to DNS probe results. None
+// of these have the Link Doctor enabled.
+//------------------------------------------------------------------------------
+
+// Test case where the error page finishes loading before receiving any DNS
+// probe messages.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbe) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Same as above, but the probe is not run.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbeNotRun) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ // When the not run status arrives, the page should revert to the normal dns
+ // error page.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_NOT_RUN);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(NetErrorString(net::ERR_NAME_NOT_RESOLVED), last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Same as above, but the probe result is inconclusive.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbeInconclusive) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ // When the inconclusive status arrives, the page should revert to the normal
+ // dns error page.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(NetErrorString(net::ERR_NAME_NOT_RESOLVED), last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_INCONCLUSIVE);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Same as above, but the probe result is no internet.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbeNoInternet) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ // When the inconclusive status arrives, the page should revert to the normal
+ // dns error page.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET),
+ last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Same as above, but the probe result is bad config.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbeBadConfig) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ // When the inconclusive status arrives, the page should revert to the normal
+ // dns error page.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG),
+ last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_BAD_CONFIG);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Test case where the error page finishes loading after receiving the start
+// DNS probe message.
+TEST_F(NetErrorHelperCoreTest, FinishedAfterStartProbe) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Nothing should be done when a probe status comes in before loading
+ // finishes.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(0, update_count());
+
+ // When loading finishes, however, the buffered probe status should be sent
+ // to the page.
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ // Should update the page again when the probe result comes in.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_NOT_RUN);
+ EXPECT_EQ(2, update_count());
+}
+
+// Test case where the error page finishes loading before receiving any DNS
+// probe messages and the request is a POST.
+TEST_F(NetErrorHelperCoreTest, FinishedBeforeProbePost) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ true, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ErrorToString(
+ ProbeError(chrome_common_net::DNS_PROBE_POSSIBLE),
+ true),
+ html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ErrorToString(
+ ProbeError(chrome_common_net::DNS_PROBE_STARTED), true),
+ last_error_html());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ErrorToString(
+ ProbeError(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ true),
+ last_error_html());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Test case where the probe finishes before the page is committed.
+TEST_F(NetErrorHelperCoreTest, ProbeFinishesEarly) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+
+ // Nothing should be done when the probe statuses come in before loading
+ // finishes.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(0, update_count());
+
+ // When loading finishes, however, the buffered probe status should be sent
+ // to the page.
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // Any other probe updates should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(1, update_count());
+}
+
+// Test case where one error page loads completely before a new navigation
+// results in another error page. Probes are run for both pages.
+TEST_F(NetErrorHelperCoreTest, TwoErrorsWithProbes) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Probe results come in.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // The process starts again.
+
+ // Normal page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(2, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(3, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ // The probe returns a different result this time.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
+ EXPECT_EQ(4, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET),
+ last_error_html());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Test case where one error page loads completely before a new navigation
+// results in another error page. Probe results for the first probe are only
+// received after the second load starts, but before it commits.
+TEST_F(NetErrorHelperCoreTest, TwoErrorsWithProbesAfterSecondStarts) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // The process starts again.
+
+ // Normal page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page starts to load.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+
+ // Probe results come in, and the first page is updated.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // Second page finishes loading, and is updated using the same probe result.
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(3, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // Other probe results should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
+ EXPECT_EQ(3, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// Same as above, but a new page is loaded before the error page commits.
+TEST_F(NetErrorHelperCoreTest, ErrorPageLoadInterrupted) {
+ // Original page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and an error page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ // Probe statuses come in, but should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+
+ // A new navigation begins while the error page is loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // And fails.
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ // Should have returned a local error page indicating a probe may run.
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE), html);
+
+ // Error page finishes loading.
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Probe results come in.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NO_INTERNET),
+ last_error_html());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+//------------------------------------------------------------------------------
+// Link Doctor tests.
+//------------------------------------------------------------------------------
+
+// Check that the Link Doctor is not used for HTTPS URLs.
+TEST_F(NetErrorHelperCoreTest, NoLinkDoctorForHttps) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // The HTTPS page fails to load.
+ std::string html;
+ blink::WebURLError error = NetError(net::ERR_NAME_NOT_RESOLVED);
+ error.unreachableURL = GURL(kFailedHttpsUrl);
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME, error, false, &html);
+
+ blink::WebURLError probe_error =
+ ProbeError(chrome_common_net::DNS_PROBE_POSSIBLE);
+ probe_error.unreachableURL = GURL(kFailedHttpsUrl);
+ EXPECT_EQ(ErrorToString(probe_error, false), html);
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // The blank page loads, no error page is loaded.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Page is updated in response to DNS probes as normal.
+ EXPECT_EQ(0, update_count());
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ blink::WebURLError final_probe_error =
+ ProbeError(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ final_probe_error.unreachableURL = GURL(kFailedHttpsUrl);
+ EXPECT_EQ(ErrorToString(final_probe_error, false), last_error_html());
+}
+
+// The blank page loads, then the Link Doctor request succeeds and is loaded.
+// Then the probe results come in.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorSucceedsBeforeProbe) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Link doctor retrieval starts when the error page finishes loading.
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_TRUE(is_url_being_fetched());
+
+ // Link Doctor is retrieved.
+ LinkDoctorLoadSuccess();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(kLinkDoctorBody, last_error_html());
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Link Doctor page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Any probe statuses should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(1, error_html_update_count());
+}
+
+// The blank page finishes loading, then probe results come in, and then
+// the Link Doctor request succeeds.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorSucceedsAfterProbes) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_TRUE(is_url_being_fetched());
+
+
+ // Probe statuses should be ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+
+ // Link Doctor is retrieved.
+ EXPECT_TRUE(is_url_being_fetched());
+ LinkDoctorLoadSuccess();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(kLinkDoctorBody, last_error_html());
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Link Doctor page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(0, update_count());
+}
+
+// The Link Doctor request fails and then the error page loads for an error that
+// does not trigger DNS probes.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorFailsLoadNoProbes) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_CONNECTION_FAILED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Link Doctor load fails, final error page is shown.
+ EXPECT_TRUE(is_url_being_fetched());
+ LinkDoctorLoadFailure();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(last_error_html(), NetErrorString(net::ERR_CONNECTION_FAILED));
+ EXPECT_FALSE(is_url_being_fetched());
+ EXPECT_EQ(0, update_count());
+
+ // Error page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // If probe statuses come in last from another page load, they should be
+ // ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(1, error_html_update_count());
+}
+
+// The Link Doctor request fails and then the error page loads before probe
+// results are received.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorFailsLoadBeforeProbe) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Link Doctor load fails, probe pending page shown.
+ EXPECT_TRUE(is_url_being_fetched());
+ LinkDoctorLoadFailure();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(last_error_html(),
+ ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE));
+ EXPECT_FALSE(is_url_being_fetched());
+ EXPECT_EQ(0, update_count());
+
+ // Probe page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Probe statuses comes in, and page is updated.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+
+ // The commit results in sending a second probe status, which is ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(1, error_html_update_count());
+}
+
+// The Link Doctor request fails after receiving probe results.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorFailsAfterProbe) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Results come in, but end up being ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+
+ // Link Doctor load fails, probe pending page shown.
+ EXPECT_TRUE(is_url_being_fetched());
+ LinkDoctorLoadFailure();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(last_error_html(),
+ ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE));
+ EXPECT_FALSE(is_url_being_fetched());
+ EXPECT_EQ(0, update_count());
+
+ // Probe page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Probe statuses comes in, and page is updated.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(1, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+ EXPECT_EQ(1, error_html_update_count());
+}
+
+// An error page load that would normally load the Link Doctor is interrupted
+// by a new navigation before the blank page commits.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorInterruptedBeforeCommit) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page starts loading.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+
+ // A new page load starts.
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // A new page load interrupts the original load.
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ EXPECT_FALSE(is_url_being_fetched());
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// An error page load that would normally load the Link Doctor is interrupted
+// by a new navigation before the blank page finishes loading.
+TEST_F(NetErrorHelperCoreTest, LinkDoctorInterruptedBeforeLoad) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page starts loading and is committed.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // A new page load interrupts the original load.
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ EXPECT_FALSE(is_url_being_fetched());
+ EXPECT_EQ(0, update_count());
+ EXPECT_EQ(0, error_html_update_count());
+}
+
+// The Link Doctor request is cancelled due to a new navigation. The new
+// navigation fails and then loads the link doctor page again (Successfully).
+TEST_F(NetErrorHelperCoreTest, LinkDoctorInterrupted) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_TRUE(is_url_being_fetched());
+
+ // Results come in, but end up being ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+
+ // A new load appears!
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // It fails, and a Link Doctor page is requested again once a blank page is
+ // loaded.
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_FALSE(is_url_being_fetched());
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_TRUE(is_url_being_fetched());
+
+ // Link Doctor load succeeds.
+ LinkDoctorLoadSuccess();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(kLinkDoctorBody, last_error_html());
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Probe statuses come in, and are ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+}
+
+// The Link Doctor request is cancelled due to call to Stop(). The cross
+// process navigation is cancelled, and then a new load fails and tries to load
+// the link doctor page again (Which fails).
+TEST_F(NetErrorHelperCoreTest, LinkDoctorStopped) {
+ // Original page starts loading.
+ core().set_alt_error_page_url(GURL(kLinkDoctorUrl));
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested.
+ std::string html;
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ EXPECT_TRUE(is_url_being_fetched());
+ core().OnStop();
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Results come in, but end up being ignored.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(0, update_count());
+
+ // Cross process navigation must have been cancelled, and a new load appears!
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::NON_ERROR_PAGE);
+
+ // It fails, and a Link Doctor page is requested again.
+ core().GetErrorHTML(NetErrorHelperCore::MAIN_FRAME,
+ NetError(net::ERR_NAME_NOT_RESOLVED),
+ false, &html);
+ EXPECT_TRUE(html.empty());
+
+ // The blank page loads again.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+ EXPECT_TRUE(is_url_being_fetched());
+
+ // Link Doctor load fails, probe pending page shown.
+ LinkDoctorLoadFailure();
+ EXPECT_EQ(1, error_html_update_count());
+ EXPECT_EQ(last_error_html(),
+ ProbeErrorString(chrome_common_net::DNS_PROBE_POSSIBLE));
+ EXPECT_FALSE(is_url_being_fetched());
+
+ // Probe page loads.
+ core().OnStartLoad(NetErrorHelperCore::MAIN_FRAME,
+ NetErrorHelperCore::ERROR_PAGE);
+ core().OnCommitLoad(NetErrorHelperCore::MAIN_FRAME);
+ core().OnFinishLoad(NetErrorHelperCore::MAIN_FRAME);
+
+ // Probe statuses comes in, and page is updated.
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_STARTED);
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_STARTED),
+ last_error_html());
+ EXPECT_EQ(1, update_count());
+
+ core().OnNetErrorInfo(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
+ EXPECT_EQ(2, update_count());
+ EXPECT_EQ(ProbeErrorString(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN),
+ last_error_html());
+ EXPECT_EQ(1, error_html_update_count());
+}
diff --git a/chrome/renderer/net/net_error_helper_unittest.cc b/chrome/renderer/net/net_error_helper_unittest.cc
deleted file mode 100644
index 828c34e..0000000
--- a/chrome/renderer/net/net_error_helper_unittest.cc
+++ /dev/null
@@ -1,412 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "chrome/renderer/net/net_error_helper.h"
-
-#include "base/logging.h"
-#include "chrome/common/net/net_error_info.h"
-#include "testing/gtest/include/gtest/gtest.h"
-
-using chrome_common_net::DnsProbeStatus;
-using chrome_common_net::DnsProbeStatusToString;
-
-// NetErrorHelperTest cases consist of a string of these steps.
-enum TestStep {
- // Simulate a provisional load start, fail, commit or a finish-load event.
- // (Start and fail differentiate between normal and error pages.)
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START,
- LOAD_COMMIT, LOAD_FINISH,
-
- // Simulate an IPC from the browser with DNS_PROBE_STARTED, _NOT_RUN, or
- // _FINISHED_NXDOMAIN.
- STATUS_STARTED, STATUS_NOT_RUN, STATUS_FINISHED,
-
- // Expect that the *next* step will cause an update. (Any step that is not
- // prefixed by this pseudo-step is expected *not* to cause an update.)
- EXPECT_UPDATE
-};
-
-class TestNetErrorHelper : public NetErrorHelper {
- public:
- TestNetErrorHelper()
- : NetErrorHelper(NULL),
- mock_page_update_count_(0),
- mock_displayed_probe_status_(chrome_common_net::DNS_PROBE_MAX) {}
-
- virtual ~TestNetErrorHelper() {}
-
- void StartLoad(bool is_main_frame, bool is_error_page) {
- OnStartLoad(is_main_frame, is_error_page);
- }
-
- void FailLoad(bool is_main_frame, bool is_dns_error) {
- OnFailLoad(is_main_frame, is_dns_error);
- }
-
- void CommitLoad(bool is_main_frame) {
- OnCommitLoad(is_main_frame);
- }
-
- void FinishLoad(bool is_main_frame) {
- OnFinishLoad(is_main_frame);
- }
-
- void ReceiveProbeStatus(DnsProbeStatus status) {
- OnNetErrorInfo(static_cast<int>(status));
- }
-
- int mock_page_update_count() const { return mock_page_update_count_; }
- DnsProbeStatus mock_displayed_probe_status() const {
- return mock_displayed_probe_status_;
- }
-
- protected:
- virtual void UpdateErrorPage() OVERRIDE {
- DVLOG(1) << "Updating error page with status "
- << DnsProbeStatusToString(last_probe_status_);
- mock_page_update_count_++;
- mock_displayed_probe_status_ = last_probe_status_;
- }
-
- private:
- int mock_page_update_count_;
- DnsProbeStatus mock_displayed_probe_status_;
-};
-
-class NetErrorHelperTest : public testing::Test {
- protected:
- enum MainFrame { SUB_FRAME, MAIN_FRAME };
- enum ErrorPage { NORMAL_PAGE, ERROR_PAGE };
- enum ErrorType { OTHER_ERROR, DNS_ERROR };
-
- void StartLoad(MainFrame main_frame, ErrorPage error_page) {
- helper_.StartLoad(main_frame == MAIN_FRAME, error_page == ERROR_PAGE);
- }
-
- void FailLoad(MainFrame main_frame, ErrorType error_type) {
- helper_.FailLoad(main_frame == MAIN_FRAME, error_type == DNS_ERROR);
- }
-
- void CommitLoad(MainFrame main_frame) {
- helper_.CommitLoad(main_frame == MAIN_FRAME);
- }
-
- void FinishLoad(MainFrame main_frame) {
- helper_.FinishLoad(main_frame == MAIN_FRAME);
- }
-
- void ReceiveProbeStatus(DnsProbeStatus status) {
- helper_.ReceiveProbeStatus(status);
- }
-
- void RunTest(const TestStep steps[], int step_count);
-
- int page_update_count() const { return helper_.mock_page_update_count(); }
- DnsProbeStatus displayed_probe_status() const {
- return helper_.mock_displayed_probe_status();
- }
-
- private:
- TestNetErrorHelper helper_;
-};
-
-void NetErrorHelperTest::RunTest(const TestStep steps[], int step_count) {
- // Whether the next instruction is expected to cause an update (since the
- // step right before it was EXPECT_UPDATE) or not.
- bool update_expected = false;
- int expected_update_count = page_update_count();
- // The last status that the test simulated receiving from the browser.
- // When an update is expected, the status is expected to match this.
- chrome_common_net::DnsProbeStatus last_status_received =
- chrome_common_net::DNS_PROBE_POSSIBLE;
-
- for (int i = 0; i < step_count; i++) {
- switch (steps[i]) {
- case LOAD_NORMAL_START:
- StartLoad(MAIN_FRAME, NORMAL_PAGE);
- break;
- case LOAD_NORMAL_FAIL:
- FailLoad(MAIN_FRAME, DNS_ERROR);
- break;
- case LOAD_ERROR_START:
- StartLoad(MAIN_FRAME, ERROR_PAGE);
- break;
- case LOAD_COMMIT:
- CommitLoad(MAIN_FRAME);
- break;
- case LOAD_FINISH:
- FinishLoad(MAIN_FRAME);
- break;
- case STATUS_STARTED:
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_STARTED);
- last_status_received = chrome_common_net::DNS_PROBE_STARTED;
- break;
- case STATUS_NOT_RUN:
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_NOT_RUN);
- last_status_received = chrome_common_net::DNS_PROBE_NOT_RUN;
- break;
- case STATUS_FINISHED:
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
- last_status_received = chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN;
- break;
- case EXPECT_UPDATE:
- ASSERT_FALSE(update_expected);
- update_expected = true;
- // Skip to next step to see if it updates the status, instead of
- // checking whether EXPECT_UPDATE itself caused an update.
- continue;
- }
-
- if (update_expected) {
- DCHECK_NE(chrome_common_net::DNS_PROBE_POSSIBLE, last_status_received);
- ++expected_update_count;
-
- EXPECT_EQ(last_status_received, displayed_probe_status());
- if (displayed_probe_status() != last_status_received) {
- LOG(ERROR) << "Unexpected status at step " << i << ".";
- return;
- }
- }
-
- EXPECT_EQ(expected_update_count, page_update_count());
- if (page_update_count() != expected_update_count) {
- LOG(ERROR) << (update_expected ? "Missing" : "Spurious")
- << " update at step " << i << ".";
- return;
- }
-
- update_expected = false;
- }
-
- DCHECK(!update_expected);
-}
-
-TEST_F(NetErrorHelperTest, Null) {
- // Test that we can simply create and destroy a NetErrorHelper.
-}
-
-TEST_F(NetErrorHelperTest, SuccessfulPageLoad) {
- StartLoad(MAIN_FRAME, NORMAL_PAGE);
- CommitLoad(MAIN_FRAME);
- FinishLoad(MAIN_FRAME);
-
- // Ignore spurious status.
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
- EXPECT_EQ(0, page_update_count());
-}
-
-TEST_F(NetErrorHelperTest, MainFrameNonDnsError) {
- StartLoad(MAIN_FRAME, NORMAL_PAGE);
- FailLoad(MAIN_FRAME, OTHER_ERROR);
- StartLoad(MAIN_FRAME, ERROR_PAGE);
- CommitLoad(MAIN_FRAME);
- FinishLoad(MAIN_FRAME);
-
- // Ignore spurious status.
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
- EXPECT_EQ(0, page_update_count());
-}
-
-TEST_F(NetErrorHelperTest, SubFrameDnsError) {
- StartLoad(SUB_FRAME, NORMAL_PAGE);
- FailLoad(SUB_FRAME, DNS_ERROR);
- StartLoad(SUB_FRAME, ERROR_PAGE);
- CommitLoad(SUB_FRAME);
- FinishLoad(SUB_FRAME);
-
- // Ignore spurious status.
- ReceiveProbeStatus(chrome_common_net::DNS_PROBE_FINISHED_NXDOMAIN);
- EXPECT_EQ(0, page_update_count());
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_FINISHED, LOAD_ERROR_START,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFail_StartedAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, STATUS_FINISHED,
- LOAD_ERROR_START, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_FINISHED,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterStart_StartedAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterStart_StartedAfterStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterCommit) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- LOAD_COMMIT, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_STARTED,
- LOAD_ERROR_START, LOAD_COMMIT, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterCommit_StartedAfterCommit) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- STATUS_STARTED, STATUS_FINISHED, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFinish) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_STARTED,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterCommit) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- STATUS_STARTED, EXPECT_UPDATE, LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterFinish_StartAfterFinish) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, EXPECT_UPDATE, STATUS_STARTED, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterNewStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, LOAD_NORMAL_START, EXPECT_UPDATE, STATUS_FINISHED,
- LOAD_COMMIT, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, NotRunAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_NOT_RUN, LOAD_ERROR_START,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, NotRunAfterStart) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, STATUS_NOT_RUN,
- LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, NotRunAfterCommit) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- STATUS_NOT_RUN, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, NotRunAfterFinish) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, EXPECT_UPDATE, STATUS_NOT_RUN
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterNewCommit) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, LOAD_NORMAL_START, LOAD_COMMIT, STATUS_FINISHED, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-TEST_F(NetErrorHelperTest, FinishedAfterNewFinish) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, LOAD_NORMAL_START, LOAD_COMMIT, LOAD_FINISH, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}
-
-// Two iterations of FinishedAfterStart_StartAfterFail
-TEST_F(NetErrorHelperTest, TwoProbes_FinishedAfterStart_StartAfterFail) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH,
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, STATUS_STARTED, LOAD_ERROR_START,
- STATUS_FINISHED, LOAD_COMMIT, EXPECT_UPDATE, LOAD_FINISH
- };
- RunTest(steps, arraysize(steps));
-}
-
-// Two iterations of FinishedAfterFinish
-TEST_F(NetErrorHelperTest, TwoProbes_FinishedAfterFinish) {
- const TestStep steps[] = {
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED,
- LOAD_NORMAL_START, LOAD_NORMAL_FAIL, LOAD_ERROR_START, LOAD_COMMIT,
- LOAD_FINISH, EXPECT_UPDATE, STATUS_FINISHED
- };
- RunTest(steps, arraysize(steps));
-}