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

Side by Side Diff: chrome/renderer/net/net_error_helper.cc

Issue 13270005: Display DNS probe results. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Round two. Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/renderer/net/net_error_helper.h" 5 #include "chrome/renderer/net/net_error_helper.h"
6 6
7 #include <string>
8
9 #include "base/json/json_writer.h"
10 #include "base/utf_string_conversions.h"
7 #include "base/values.h" 11 #include "base/values.h"
8 #include "chrome/common/localized_error.h" 12 #include "chrome/common/localized_error.h"
9 #include "chrome/common/render_messages.h" 13 #include "chrome/common/render_messages.h"
10 #include "chrome/common/net/net_error_info.h" 14 #include "chrome/common/net/net_error_info.h"
15 #include "chrome/common/net/net_error_tracker.h"
11 #include "content/public/common/content_client.h" 16 #include "content/public/common/content_client.h"
12 #include "content/public/common/url_constants.h" 17 #include "content/public/common/url_constants.h"
13 #include "content/public/renderer/content_renderer_client.h" 18 #include "content/public/renderer/content_renderer_client.h"
14 #include "content/public/renderer/render_thread.h" 19 #include "content/public/renderer/render_thread.h"
15 #include "content/public/renderer/render_view.h" 20 #include "content/public/renderer/render_view.h"
16 #include "googleurl/src/gurl.h" 21 #include "googleurl/src/gurl.h"
17 #include "ipc/ipc_message.h" 22 #include "ipc/ipc_message.h"
18 #include "ipc/ipc_message_macros.h" 23 #include "ipc/ipc_message_macros.h"
19 #include "net/base/net_errors.h" 24 #include "net/base/net_errors.h"
20 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h" 25 #include "third_party/WebKit/Source/Platform/chromium/public/WebURL.h"
21 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLError.h" 26 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLError.h"
22 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h" 27 #include "third_party/WebKit/Source/Platform/chromium/public/WebURLRequest.h"
23 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h" 28 #include "third_party/WebKit/Source/WebKit/chromium/public/WebDataSource.h"
24 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h" 29 #include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
25 30
26 using base::DictionaryValue; 31 using base::DictionaryValue;
27 using chrome_common_net::DnsProbeResult; 32 using base::JSONWriter;
33 using chrome_common_net::DnsProbeStatus;
34 using chrome_common_net::DnsProbeStatusToString;
35 using chrome_common_net::DnsProbesEnabledByFieldTrial;
28 using content::RenderThread; 36 using content::RenderThread;
29 using content::RenderView; 37 using content::RenderView;
30 using content::RenderViewObserver; 38 using content::RenderViewObserver;
31 using content::kUnreachableWebDataURL; 39 using content::kUnreachableWebDataURL;
32 40
33 namespace { 41 namespace {
34 42
35 GURL GetProvisionallyLoadingURLFromWebFrame(WebKit::WebFrame* frame) { 43 GURL GetProvisionallyLoadingURLFromWebFrame(WebKit::WebFrame* frame) {
36 return frame->provisionalDataSource()->request().url(); 44 return frame->provisionalDataSource()->request().url();
37 } 45 }
38 46
39 bool IsErrorPage(const GURL& url) { 47 bool IsErrorPage(const GURL& url) {
40 return (url.spec() == kUnreachableWebDataURL); 48 return (url.spec() == kUnreachableWebDataURL);
41 } 49 }
42 50
43 // Returns whether |net_error| is a DNS-related error (and therefore whether 51 // Returns whether |net_error| is a DNS-related error (and therefore whether
44 // the tab helper should start a DNS probe after receiving it.) 52 // the tab helper should start a DNS probe after receiving it.)
45 bool IsDnsError(int net_error) { 53 bool IsDnsError(const WebKit::WebURLError& error) {
46 return net_error == net::ERR_NAME_NOT_RESOLVED || 54 return std::string(error.domain.utf8()) == net::kErrorDomain &&
47 net_error == net::ERR_NAME_RESOLUTION_FAILED; 55 (error.reason == net::ERR_NAME_NOT_RESOLVED ||
56 error.reason == net::ERR_NAME_RESOLUTION_FAILED);
48 } 57 }
49 58
50 NetErrorTracker::FrameType GetFrameType(WebKit::WebFrame* frame) { 59 NetErrorTracker::FrameType GetFrameType(WebKit::WebFrame* frame) {
51 return frame->parent() ? NetErrorTracker::FRAME_SUB 60 return frame->parent() ? NetErrorTracker::FRAME_SUB
52 : NetErrorTracker::FRAME_MAIN; 61 : NetErrorTracker::FRAME_MAIN;
53 } 62 }
54 63
55 NetErrorTracker::PageType GetPageType(WebKit::WebFrame* frame) { 64 NetErrorTracker::PageType GetPageType(WebKit::WebFrame* frame) {
56 bool error_page = IsErrorPage(GetProvisionallyLoadingURLFromWebFrame(frame)); 65 bool error_page = IsErrorPage(GetProvisionallyLoadingURLFromWebFrame(frame));
57 return error_page ? NetErrorTracker::PAGE_ERROR 66 return error_page ? NetErrorTracker::PAGE_ERROR
58 : NetErrorTracker::PAGE_NORMAL; 67 : NetErrorTracker::PAGE_NORMAL;
59 } 68 }
60 69
61 NetErrorTracker::ErrorType GetErrorType(const WebKit::WebURLError& error) { 70 NetErrorTracker::ErrorType GetErrorType(const WebKit::WebURLError& error) {
62 return IsDnsError(error.reason) ? NetErrorTracker::ERROR_DNS 71 return IsDnsError(error) ? NetErrorTracker::ERROR_DNS
63 : NetErrorTracker::ERROR_OTHER; 72 : NetErrorTracker::ERROR_OTHER;
64 }
65
66 // Converts a DNS probe result into a net error. Returns OK if the error page
67 // should not be changed from the original DNS error.
68 int DnsProbeResultToNetError(DnsProbeResult result) {
69 switch (result) {
70 case chrome_common_net::DNS_PROBE_UNKNOWN:
71 return net::OK;
72 case chrome_common_net::DNS_PROBE_NO_INTERNET:
73 // TODO(ttuttle): This is not the same error as when NCN returns this;
74 // ideally we should have two separate error codes for "no network" and
75 // "network with no internet".
76 return net::ERR_INTERNET_DISCONNECTED;
77 case chrome_common_net::DNS_PROBE_BAD_CONFIG:
78 // This is unspecific enough that we should still show the full DNS error
79 // page.
80 return net::OK;
81 case chrome_common_net::DNS_PROBE_NXDOMAIN:
82 return net::ERR_NAME_NOT_RESOLVED;
83 default:
84 NOTREACHED();
85 return net::OK;
86 }
87 }
88
89 WebKit::WebURLError NetErrorToWebURLError(int net_error) {
90 WebKit::WebURLError error;
91 error.domain = WebKit::WebString::fromUTF8(net::kErrorDomain);
92 error.reason = net_error;
93 return error;
94 } 73 }
95 74
96 } // namespace 75 } // namespace
97 76
98 NetErrorHelper::NetErrorHelper(RenderView* render_view) 77 NetErrorHelper::NetErrorHelper(RenderView* render_view)
99 : RenderViewObserver(render_view), 78 : RenderViewObserver(render_view),
100 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(base::Bind( 79 state_(IDLE),
101 &NetErrorHelper::TrackerCallback, 80 ALLOW_THIS_IN_INITIALIZER_LIST(tracker_(
102 base::Unretained(this)))), 81 base::Bind(&NetErrorHelper::TrackerCallback,
103 dns_error_page_state_(NetErrorTracker::DNS_ERROR_PAGE_NONE), 82 base::Unretained(this)))) {
104 updated_error_page_(false) {
105 } 83 }
106 84
107 NetErrorHelper::~NetErrorHelper() { 85 NetErrorHelper::~NetErrorHelper() {
108 } 86 }
109 87
110 void NetErrorHelper::DidStartProvisionalLoad(WebKit::WebFrame* frame) { 88 void NetErrorHelper::DidStartProvisionalLoad(WebKit::WebFrame* frame) {
111 tracker_.OnStartProvisionalLoad(GetFrameType(frame), GetPageType(frame)); 89 tracker_.OnStartProvisionalLoad(GetFrameType(frame), GetPageType(frame));
112 } 90 }
113 91
114 void NetErrorHelper::DidFailProvisionalLoad(WebKit::WebFrame* frame, 92 void NetErrorHelper::DidFailProvisionalLoad(WebKit::WebFrame* frame,
115 const WebKit::WebURLError& error) { 93 const WebKit::WebURLError& error) {
116 tracker_.OnFailProvisionalLoad(GetFrameType(frame), GetErrorType(error)); 94 tracker_.OnFailProvisionalLoad(GetFrameType(frame), GetErrorType(error));
95 last_error_ = error;
117 } 96 }
118 97
119 void NetErrorHelper::DidCommitProvisionalLoad(WebKit::WebFrame* frame, 98 void NetErrorHelper::DidCommitProvisionalLoad(WebKit::WebFrame* frame,
120 bool is_new_navigation) { 99 bool is_new_navigation) {
121 tracker_.OnCommitProvisionalLoad(GetFrameType(frame)); 100 tracker_.OnCommitProvisionalLoad(GetFrameType(frame));
122 } 101 }
123 102
124 void NetErrorHelper::DidFinishLoad(WebKit::WebFrame* frame) { 103 void NetErrorHelper::DidFinishLoad(WebKit::WebFrame* frame) {
125 tracker_.OnFinishLoad(GetFrameType(frame)); 104 tracker_.OnFinishLoad(GetFrameType(frame));
126 } 105 }
127 106
107 void NetErrorHelper::TrackerCallback(
108 NetErrorTracker::DnsErrorPageState tracker_state) {
109 if (tracker_state == NetErrorTracker::DNS_ERROR_PAGE_LOADED)
110 state_ = AWAITING_INITIAL_IPC;
111 else
112 state_ = IDLE;
113
114 DVLOG(1) << "Renderer in tracker state " << tracker_state
115 << ", new state " << state_ << ".";
116 }
117
128 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) { 118 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
129 bool handled = true; 119 bool handled = true;
130 120
131 IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message) 121 IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
132 IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo) 122 IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
133 IPC_MESSAGE_UNHANDLED(handled = false) 123 IPC_MESSAGE_UNHANDLED(handled = false)
134 IPC_END_MESSAGE_MAP() 124 IPC_END_MESSAGE_MAP()
135 125
136 return handled; 126 return handled;
137 } 127 }
138 128
139 void NetErrorHelper::OnNetErrorInfo(int dns_probe_result) { 129 bool NetErrorHelper::GetErrorStringsForDnsProbe(
140 DVLOG(1) << "Received DNS probe result " << dns_probe_result; 130 const WebKit::WebURLError& error,
131 base::DictionaryValue* strings,
132 const std::string& locale) {
133 if (!IsDnsError(error))
134 return false;
141 135
142 if (dns_probe_result < 0 || 136 if (!DnsProbesEnabledByFieldTrial()) {
143 dns_probe_result >= chrome_common_net::DNS_PROBE_MAX) { 137 DVLOG(1) << "Ignoring DNS error; probes disabled by field trial.";
144 DLOG(WARNING) << "Ignoring DNS probe result: invalid result " 138 return false;
145 << dns_probe_result; 139 }
140
141 // Get the strings for a fake "DNS probe possible" error
142 WebKit::WebURLError fake_error;
143 fake_error.domain = WebKit::WebString::fromUTF8(
144 chrome_common_net::kDnsProbeErrorDomain);
145 fake_error.reason = chrome_common_net::DNS_PROBE_POSSIBLE;
146 fake_error.unreachableURL = error.unreachableURL;
147 LocalizedError::GetStrings(fake_error, strings, locale);
148 return true;
149 }
150
151 void NetErrorHelper::OnNetErrorInfo(int status_num) {
152 if (status_num < 0 ||
153 status_num >= chrome_common_net::DNS_PROBE_MAX) {
154 LOG(WARNING) << "Ignoring NetErrorInfo: invalid status " << status_num;
146 NOTREACHED(); 155 NOTREACHED();
147 return; 156 return;
148 } 157 }
149 158
150 if (dns_error_page_state_ != NetErrorTracker::DNS_ERROR_PAGE_LOADED) { 159 DVLOG(1) << "Renderer received status "
151 DVLOG(1) << "Ignoring DNS probe result: not on DNS error page."; 160 << DnsProbeStatusToString(status_num);
161
162 DnsProbeStatus status = static_cast<DnsProbeStatus>(status_num);
163 bool is_finished = status >= chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN;
164
165 if (status == chrome_common_net::DNS_PROBE_POSSIBLE) {
166 DLOG(WARNING) << "Ignoring NetErrorInfo: DNS_PROBE_POSSIBLE from browser.";
167 NOTREACHED();
152 return; 168 return;
153 } 169 }
154 170
155 if (updated_error_page_) { 171 if (state_ == IDLE) {
156 DVLOG(1) << "Ignoring DNS probe result: already updated error page."; 172 // Unexpected IPC in idle; the browser sent the status after the renderer
173 // started loading a new page but before the browser became aware of it.
174 DVLOG(1) << "Ignoring NetErrorInfo: in state IDLE";
157 return; 175 return;
158 } 176 }
159 177
160 UpdateErrorPage(static_cast<DnsProbeResult>(dns_probe_result)); 178 if (state_ == AWAITING_PROBE_RESULT && !is_finished) {
161 updated_error_page_ = true; 179 DLOG(WARNING) << "Ignoring NetErrorInfo: "
180 << "non-FINISHED status in state AWAITING_PROBE_RESULT.";
181 NOTREACHED();
182 return;
183 }
184
185 if (status == chrome_common_net::DNS_PROBE_STARTED) {
186 DCHECK_EQ(AWAITING_INITIAL_IPC, state_);
187 state_ = AWAITING_PROBE_RESULT;
188 } else {
189 state_ = IDLE;
190 }
191
192 DVLOG(1) << "Renderer in new state " << state_ << ".";
193
194 last_status_ = status;
mmenke 2013/04/10 16:56:58 Don't think last_status_ serves any purpose - can
Deprecated (see juliatuttle) 2013/04/10 23:42:32 Done.
195
196 UpdateErrorPage();
162 } 197 }
163 198
164 void NetErrorHelper::TrackerCallback( 199 WebKit::WebURLError NetErrorHelper::MakeUpdatedError() {
mmenke 2013/04/10 16:56:58 Doesn't always make a WebKitError. Suggest GetFin
mmenke 2013/04/10 16:56:58 This can be const.
Deprecated (see juliatuttle) 2013/04/10 23:42:32 GetUpdatedError(), since it's not necessarily the
Deprecated (see juliatuttle) 2013/04/10 23:42:32 Done.
165 NetErrorTracker::DnsErrorPageState state) { 200 // If a probe didn't run or wasn't conclusive, restore the original error.
166 dns_error_page_state_ = state; 201 if (last_status_ == chrome_common_net::DNS_PROBE_NOT_RUN
202 || last_status_ == chrome_common_net::DNS_PROBE_FINISHED_UNKNOWN)
mmenke 2013/04/10 16:56:58 nit: Put "||" on previous line.
mmenke 2013/04/10 16:56:58 nit: Use braces in if's where the condition uses
Deprecated (see juliatuttle) 2013/04/10 23:42:32 Done.
Deprecated (see juliatuttle) 2013/04/10 23:42:32 Done.
203 return last_error_;
167 204
168 if (state == NetErrorTracker::DNS_ERROR_PAGE_LOADED) 205 WebKit::WebURLError error;
169 updated_error_page_ = false; 206 error.domain = WebKit::WebString::fromUTF8(
207 chrome_common_net::kDnsProbeErrorDomain);
208 error.reason = last_status_;
209 error.unreachableURL = last_error_.unreachableURL;
210
211 return error;
170 } 212 }
171 213
172 void NetErrorHelper::UpdateErrorPage(DnsProbeResult dns_probe_result) { 214 void NetErrorHelper::UpdateErrorPage() {
173 DVLOG(1) << "Updating error page with result " << dns_probe_result;
174
175 int net_error = DnsProbeResultToNetError(dns_probe_result);
176 if (net_error == net::OK)
177 return;
178
179 DVLOG(1) << "net error code is " << net_error;
180
181 DictionaryValue error_strings; 215 DictionaryValue error_strings;
182 LocalizedError::GetStrings(NetErrorToWebURLError(net_error), 216 LocalizedError::GetStrings(MakeUpdatedError(),
183 &error_strings, 217 &error_strings,
184 RenderThread::Get()->GetLocale()); 218 RenderThread::Get()->GetLocale());
185 219
186 // TODO(ttuttle): Update error page with error_strings. 220 std::string json;
221 JSONWriter::Write(&error_strings, &json);
222
223 std::string js = "updateForDnsProbe(" + json + ");";
224 string16 js16;
225 if (!UTF8ToUTF16(js.c_str(), js.length(), &js16)) {
226 NOTREACHED();
227 return;
228 }
229
230 DVLOG(1) << "Renderer updating error page.";
231 DVLOG(2) << "New strings: " << js;
232
233 string16 frame_xpath;
234 render_view()->EvaluateScript(frame_xpath, js16, 0, false);
187 } 235 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698