summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/net/net_error_helper.cc
diff options
context:
space:
mode:
authorttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-17 05:23:13 +0000
committerttuttle@chromium.org <ttuttle@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2013-07-17 05:23:13 +0000
commit2ea1efe9660ee70c8eefb98dde76caac1c918005 (patch)
treeb5b7e0ea619ae3df960f25d3c4ce23cbba335e2c /chrome/renderer/net/net_error_helper.cc
parent3793b5f264db5e0ce9950d0e28e8748e5b8c56ff (diff)
downloadchromium_src-2ea1efe9660ee70c8eefb98dde76caac1c918005.zip
chromium_src-2ea1efe9660ee70c8eefb98dde76caac1c918005.tar.gz
chromium_src-2ea1efe9660ee70c8eefb98dde76caac1c918005.tar.bz2
Display DNS probe results.
1. Modify the browser-side NetErrorTabHelper to send extra messages when it starts or declines to start a DNS probe. 2. Create a new error domain, "dnsprobe", with errors for "might run a DNS probe", "currently running a DNS probe", and all of the possible probe results. 3. Modify ChromeContentRendererClient to give the renderer-side NetErrorHelper a chance to choose the error strings before we call LocalizedError directly. 4. Catch DNS errors and provide the strings for the "might run a DNS probe" pseudo-error instead. 5. Add a function to neterror.html that lets us re-render the template with a new set of strings. 6. When we get a "probe started" message, replace the strings with those for the "currently running a DNS probe" pseudo-error. 7. When we get a "probe finished" message, replace the strings with those for the probe result. 8. When we get a "probe not run" message, replace the strings with those for the original error we received. BUG=156415 TEST=DnsProbeBrowserTest Review URL: https://chromiumcodereview.appspot.com/13270005 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@211950 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer/net/net_error_helper.cc')
-rw-r--r--chrome/renderer/net/net_error_helper.cc264
1 files changed, 164 insertions, 100 deletions
diff --git a/chrome/renderer/net/net_error_helper.cc b/chrome/renderer/net/net_error_helper.cc
index d73386d..46a8e0e 100644
--- a/chrome/renderer/net/net_error_helper.cc
+++ b/chrome/renderer/net/net_error_helper.cc
@@ -4,6 +4,10 @@
#include "chrome/renderer/net/net_error_helper.h"
+#include <string>
+
+#include "base/json/json_writer.h"
+#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/localized_error.h"
#include "chrome/common/net/net_error_info.h"
@@ -17,13 +21,16 @@
#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/web/WebDataSource.h"
#include "third_party/WebKit/public/web/WebFrame.h"
#include "url/gurl.h"
-using chrome_common_net::DnsProbeResult;
+using base::JSONWriter;
+using chrome_common_net::DnsProbeStatus;
+using chrome_common_net::DnsProbeStatusIsFinished;
+using chrome_common_net::DnsProbeStatusToString;
+using chrome_common_net::DnsProbesEnabledByFieldTrial;
using content::RenderThread;
using content::RenderView;
using content::RenderViewObserver;
@@ -31,75 +38,31 @@ using content::kUnreachableWebDataURL;
namespace {
-GURL GetProvisionallyLoadingURLFromWebFrame(WebKit::WebFrame* frame) {
- return frame->provisionalDataSource()->request().url();
+bool IsLoadingErrorPage(WebKit::WebFrame* frame) {
+ GURL url = frame->provisionalDataSource()->request().url();
+ return url.spec() == kUnreachableWebDataURL;
}
-bool IsErrorPage(const GURL& url) {
- return (url.spec() == kUnreachableWebDataURL);
+bool IsMainFrame(const WebKit::WebFrame* frame) {
+ return !frame->parent();
}
// 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(int net_error) {
- return net_error == net::ERR_NAME_NOT_RESOLVED ||
- net_error == net::ERR_NAME_RESOLUTION_FAILED;
-}
-
-NetErrorTracker::FrameType GetFrameType(WebKit::WebFrame* frame) {
- return frame->parent() ? NetErrorTracker::FRAME_SUB
- : NetErrorTracker::FRAME_MAIN;
-}
-
-NetErrorTracker::PageType GetPageType(WebKit::WebFrame* frame) {
- bool error_page = IsErrorPage(GetProvisionallyLoadingURLFromWebFrame(frame));
- return error_page ? NetErrorTracker::PAGE_ERROR
- : NetErrorTracker::PAGE_NORMAL;
-}
-
-NetErrorTracker::ErrorType GetErrorType(const WebKit::WebURLError& error) {
- return IsDnsError(error.reason) ? NetErrorTracker::ERROR_DNS
- : NetErrorTracker::ERROR_OTHER;
-}
-
-// Converts a DNS probe result into a net error. Returns OK if the error page
-// should not be changed from the original DNS error.
-int DnsProbeResultToNetError(DnsProbeResult result) {
- switch (result) {
- case chrome_common_net::DNS_PROBE_UNKNOWN:
- return net::OK;
- case chrome_common_net::DNS_PROBE_NO_INTERNET:
- // TODO(ttuttle): This is not the same error as when NCN returns this;
- // ideally we should have two separate error codes for "no network" and
- // "network with no internet".
- return net::ERR_INTERNET_DISCONNECTED;
- case chrome_common_net::DNS_PROBE_BAD_CONFIG:
- // This is unspecific enough that we should still show the full DNS error
- // page.
- return net::OK;
- case chrome_common_net::DNS_PROBE_NXDOMAIN:
- return net::ERR_NAME_NOT_RESOLVED;
- default:
- NOTREACHED();
- return net::OK;
- }
-}
-
-WebKit::WebURLError NetErrorToWebURLError(int net_error) {
- WebKit::WebURLError error;
- error.domain = WebKit::WebString::fromUTF8(net::kErrorDomain);
- error.reason = net_error;
- return error;
+bool IsDnsError(const WebKit::WebURLError& error) {
+ return std::string(error.domain.utf8()) == net::kErrorDomain &&
+ (error.reason == net::ERR_NAME_NOT_RESOLVED ||
+ error.reason == net::ERR_NAME_RESOLUTION_FAILED);
}
} // namespace
NetErrorHelper::NetErrorHelper(RenderView* render_view)
: RenderViewObserver(render_view),
- tracker_(base::Bind(&NetErrorHelper::TrackerCallback,
- base::Unretained(this))),
- dns_error_page_state_(NetErrorTracker::DNS_ERROR_PAGE_NONE),
- updated_error_page_(false),
+ 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) {
}
@@ -107,84 +70,185 @@ NetErrorHelper::~NetErrorHelper() {
}
void NetErrorHelper::DidStartProvisionalLoad(WebKit::WebFrame* frame) {
- tracker_.OnStartProvisionalLoad(GetFrameType(frame), GetPageType(frame));
+ OnStartLoad(IsMainFrame(frame), IsLoadingErrorPage(frame));
}
void NetErrorHelper::DidFailProvisionalLoad(WebKit::WebFrame* frame,
const WebKit::WebURLError& error) {
- WebKit::WebDataSource* data_source = frame->provisionalDataSource();
- const WebKit::WebURLRequest& failed_request = data_source->request();
- is_failed_post_ = EqualsASCII(failed_request.httpMethod(), "POST");
- tracker_.OnFailProvisionalLoad(GetFrameType(frame), GetErrorType(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;
+
+ WebKit::WebDataSource* data_source = frame->provisionalDataSource();
+ const WebKit::WebURLRequest& failed_request = data_source->request();
+ is_failed_post_ = EqualsASCII(failed_request.httpMethod(), "POST");
+ }
}
void NetErrorHelper::DidCommitProvisionalLoad(WebKit::WebFrame* frame,
bool is_new_navigation) {
- tracker_.OnCommitProvisionalLoad(GetFrameType(frame));
+ OnCommitLoad(IsMainFrame(frame));
}
void NetErrorHelper::DidFinishLoad(WebKit::WebFrame* frame) {
- tracker_.OnFinishLoad(GetFrameType(frame));
+ OnFinishLoad(IsMainFrame(frame));
}
-bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
- bool handled = true;
-
- IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
- IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
- IPC_MESSAGE_UNHANDLED(handled = false)
- IPC_END_MESSAGE_MAP()
+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;
- return handled;
+ last_start_was_error_page_ = is_error_page;
}
-void NetErrorHelper::OnNetErrorInfo(int dns_probe_result) {
- DVLOG(1) << "Received DNS probe result " << dns_probe_result;
+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 (dns_probe_result < 0 ||
- dns_probe_result >= chrome_common_net::DNS_PROBE_MAX) {
- DLOG(WARNING) << "Ignoring DNS probe result: invalid result "
- << dns_probe_result;
- NOTREACHED();
+ 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;
}
+}
- if (dns_error_page_state_ != NetErrorTracker::DNS_ERROR_PAGE_LOADED) {
- DVLOG(1) << "Ignoring DNS probe result: not on DNS error page.";
+void NetErrorHelper::OnCommitLoad(bool is_main_frame) {
+ DVLOG(1) << "OnCommitLoad(is_main_frame=" << is_main_frame << ")";
+
+ if (!is_main_frame)
return;
- }
- if (updated_error_page_) {
- DVLOG(1) << "Ignoring DNS probe result: already updated error page.";
+ // 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();
}
+}
+
+bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
+ bool handled = true;
- UpdateErrorPage(static_cast<DnsProbeResult>(dns_probe_result));
- updated_error_page_ = true;
+ IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
+ IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
+ IPC_MESSAGE_UNHANDLED(handled = false)
+ IPC_END_MESSAGE_MAP()
+
+ return handled;
}
-void NetErrorHelper::TrackerCallback(
- NetErrorTracker::DnsErrorPageState state) {
- dns_error_page_state_ = state;
+bool NetErrorHelper::GetErrorStringsForDnsProbe(
+ WebKit::WebFrame* frame,
+ const WebKit::WebURLError& error,
+ bool is_failed_post,
+ const std::string& locale,
+ base::DictionaryValue* error_strings) {
+ if (!IsMainFrame(frame))
+ return false;
- if (state == NetErrorTracker::DNS_ERROR_PAGE_LOADED)
- updated_error_page_ = false;
+ if (!IsDnsError(error))
+ return false;
+
+ // Get the strings for a fake "DNS probe possible" error.
+ WebKit::WebURLError fake_error;
+ fake_error.domain = WebKit::WebString::fromUTF8(
+ chrome_common_net::kDnsProbeErrorDomain);
+ fake_error.reason = chrome_common_net::DNS_PROBE_POSSIBLE;
+ fake_error.unreachableURL = error.unreachableURL;
+ LocalizedError::GetStrings(
+ fake_error, is_failed_post, locale, error_strings);
+ return true;
}
-void NetErrorHelper::UpdateErrorPage(DnsProbeResult dns_probe_result) {
- DVLOG(1) << "Updating error page with result " << dns_probe_result;
+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);
- int net_error = DnsProbeResultToNetError(dns_probe_result);
- if (net_error == net::OK)
+ 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";
return;
+ }
+
+ last_probe_status_ = status;
- DVLOG(1) << "net error code is " << net_error;
+ if (forwarding_probe_results_)
+ UpdateErrorPage();
+}
+
+void NetErrorHelper::UpdateErrorPage() {
+ DCHECK(forwarding_probe_results_);
base::DictionaryValue error_strings;
- LocalizedError::GetStrings(NetErrorToWebURLError(net_error),
+ LocalizedError::GetStrings(GetUpdatedError(),
is_failed_post_,
RenderThread::Get()->GetLocale(),
&error_strings);
- // TODO(ttuttle): Update error page with error_strings.
+ std::string json;
+ JSONWriter::Write(&error_strings, &json);
+
+ std::string js = "if (window.updateForDnsProbe) "
+ "updateForDnsProbe(" + json + ");";
+ string16 js16;
+ if (!UTF8ToUTF16(js.c_str(), js.length(), &js16)) {
+ NOTREACHED();
+ return;
+ }
+
+ DVLOG(1) << "Updating error page with status "
+ << chrome_common_net::DnsProbeStatusToString(last_probe_status_);
+ DVLOG(2) << "New strings: " << js;
+
+ string16 frame_xpath;
+ render_view()->EvaluateScript(frame_xpath, js16, 0, false);
+}
+
+WebKit::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_;
+ }
+
+ WebKit::WebURLError error;
+ error.domain = WebKit::WebString::fromUTF8(
+ chrome_common_net::kDnsProbeErrorDomain);
+ error.reason = last_probe_status_;
+ error.unreachableURL = last_error_.unreachableURL;
+
+ return error;
}