OLD | NEW |
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> | 7 #include <string> |
8 | 8 |
9 #include "base/command_line.h" | 9 #include "base/command_line.h" |
10 #include "base/i18n/rtl.h" | |
11 #include "base/json/json_writer.h" | 10 #include "base/json/json_writer.h" |
12 #include "base/metrics/histogram.h" | 11 #include "base/metrics/histogram.h" |
13 #include "base/strings/utf_string_conversions.h" | 12 #include "base/strings/utf_string_conversions.h" |
14 #include "base/values.h" | 13 #include "base/values.h" |
15 #include "chrome/common/chrome_switches.h" | 14 #include "chrome/common/chrome_switches.h" |
16 #include "chrome/common/localized_error.h" | 15 #include "chrome/common/localized_error.h" |
17 #include "chrome/common/net/net_error_info.h" | 16 #include "chrome/common/net/net_error_info.h" |
18 #include "chrome/common/render_messages.h" | 17 #include "chrome/common/render_messages.h" |
19 #include "chrome/renderer/net/error_cache_load.h" | 18 #include "chrome/renderer/net/error_cache_load.h" |
20 #include "content/public/common/content_client.h" | 19 #include "content/public/common/content_client.h" |
(...skipping 21 matching lines...) Expand all Loading... |
42 using base::JSONWriter; | 41 using base::JSONWriter; |
43 using chrome_common_net::DnsProbeStatus; | 42 using chrome_common_net::DnsProbeStatus; |
44 using chrome_common_net::DnsProbeStatusToString; | 43 using chrome_common_net::DnsProbeStatusToString; |
45 using content::RenderFrame; | 44 using content::RenderFrame; |
46 using content::RenderFrameObserver; | 45 using content::RenderFrameObserver; |
47 using content::RenderThread; | 46 using content::RenderThread; |
48 using content::kUnreachableWebDataURL; | 47 using content::kUnreachableWebDataURL; |
49 | 48 |
50 namespace { | 49 namespace { |
51 | 50 |
52 // Number of seconds to wait for the navigation correction service to return | 51 // Number of seconds to wait for the alternate error page server. If it takes |
53 // suggestions. If it takes too long, just use the local error page. | 52 // too long, just use the local error page. |
54 static const int kNavigationCorrectionFetchTimeoutSec = 3; | 53 static const int kAlterErrorPageFetchTimeoutSec = 3000; |
55 | 54 |
56 NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) { | 55 NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) { |
57 GURL url = frame->provisionalDataSource()->request().url(); | 56 GURL url = frame->provisionalDataSource()->request().url(); |
58 if (!url.is_valid() || url.spec() != kUnreachableWebDataURL) | 57 if (!url.is_valid() || url.spec() != kUnreachableWebDataURL) |
59 return NetErrorHelperCore::NON_ERROR_PAGE; | 58 return NetErrorHelperCore::NON_ERROR_PAGE; |
60 return NetErrorHelperCore::ERROR_PAGE; | 59 return NetErrorHelperCore::ERROR_PAGE; |
61 } | 60 } |
62 | 61 |
63 NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) { | 62 NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) { |
64 if (!frame->parent()) | 63 if (!frame->parent()) |
65 return NetErrorHelperCore::MAIN_FRAME; | 64 return NetErrorHelperCore::MAIN_FRAME; |
66 return NetErrorHelperCore::SUB_FRAME; | 65 return NetErrorHelperCore::SUB_FRAME; |
67 } | 66 } |
68 | 67 |
69 // Copied from localized_error.cc. | |
70 // TODO(mmenke): Share code? | |
71 bool LocaleIsRTL() { | |
72 #if defined(TOOLKIT_GTK) | |
73 // base::i18n::IsRTL() uses the GTK text direction, which doesn't work within | |
74 // the renderer sandbox. | |
75 return base::i18n::ICUIsRTL(); | |
76 #else | |
77 return base::i18n::IsRTL(); | |
78 #endif | |
79 } | |
80 | |
81 } // namespace | 68 } // namespace |
82 | 69 |
83 NetErrorHelper::NetErrorHelper(RenderFrame* render_view) | 70 NetErrorHelper::NetErrorHelper(RenderFrame* render_view) |
84 : RenderFrameObserver(render_view), | 71 : RenderFrameObserver(render_view), |
85 content::RenderFrameObserverTracker<NetErrorHelper>(render_view), | 72 content::RenderFrameObserverTracker<NetErrorHelper>(render_view), |
86 core_(this) { | 73 core_(this) { |
87 RenderThread::Get()->AddObserver(this); | 74 RenderThread::Get()->AddObserver(this); |
88 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 75 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
89 bool auto_reload_enabled = | 76 bool auto_reload_enabled = |
90 command_line->HasSwitch(switches::kEnableOfflineAutoReload); | 77 command_line->HasSwitch(switches::kEnableOfflineAutoReload); |
(...skipping 21 matching lines...) Expand all Loading... |
112 | 99 |
113 void NetErrorHelper::OnStop() { | 100 void NetErrorHelper::OnStop() { |
114 core_.OnStop(); | 101 core_.OnStop(); |
115 } | 102 } |
116 | 103 |
117 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) { | 104 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) { |
118 bool handled = true; | 105 bool handled = true; |
119 | 106 |
120 IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message) | 107 IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message) |
121 IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo) | 108 IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo) |
122 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetNavigationCorrectionInfo, | 109 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL); |
123 OnSetNavigationCorrectionInfo); | |
124 IPC_MESSAGE_UNHANDLED(handled = false) | 110 IPC_MESSAGE_UNHANDLED(handled = false) |
125 IPC_END_MESSAGE_MAP() | 111 IPC_END_MESSAGE_MAP() |
126 | 112 |
127 return handled; | 113 return handled; |
128 } | 114 } |
129 | 115 |
130 void NetErrorHelper::NetworkStateChanged(bool enabled) { | 116 void NetErrorHelper::NetworkStateChanged(bool enabled) { |
131 core_.NetworkStateChanged(enabled); | 117 core_.NetworkStateChanged(enabled); |
132 } | 118 } |
133 | 119 |
134 void NetErrorHelper::GetErrorHTML( | 120 void NetErrorHelper::GetErrorHTML( |
135 blink::WebFrame* frame, | 121 blink::WebFrame* frame, |
136 const blink::WebURLError& error, | 122 const blink::WebURLError& error, |
137 bool is_failed_post, | 123 bool is_failed_post, |
138 std::string* error_html) { | 124 std::string* error_html) { |
139 core_.GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html); | 125 core_.GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html); |
140 } | 126 } |
141 | 127 |
142 bool NetErrorHelper::ShouldSuppressErrorPage(blink::WebFrame* frame, | 128 bool NetErrorHelper::ShouldSuppressErrorPage(blink::WebFrame* frame, |
143 const GURL& url) { | 129 const GURL& url) { |
144 return core_.ShouldSuppressErrorPage(GetFrameType(frame), url); | 130 return core_.ShouldSuppressErrorPage(GetFrameType(frame), url); |
145 } | 131 } |
146 | 132 |
147 void NetErrorHelper::GenerateLocalizedErrorPage( | 133 void NetErrorHelper::GenerateLocalizedErrorPage(const blink::WebURLError& error, |
148 const blink::WebURLError& error, | 134 bool is_failed_post, |
149 bool is_failed_post, | 135 std::string* error_html) const { |
150 scoped_ptr<LocalizedError::ErrorPageParams> params, | |
151 std::string* error_html) const { | |
152 error_html->clear(); | 136 error_html->clear(); |
153 | 137 |
154 int resource_id = IDR_NET_ERROR_HTML; | 138 int resource_id = IDR_NET_ERROR_HTML; |
155 const base::StringPiece template_html( | 139 const base::StringPiece template_html( |
156 ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id)); | 140 ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id)); |
157 if (template_html.empty()) { | 141 if (template_html.empty()) { |
158 NOTREACHED() << "unable to load template."; | 142 NOTREACHED() << "unable to load template."; |
159 } else { | 143 } else { |
160 base::DictionaryValue error_strings; | 144 base::DictionaryValue error_strings; |
161 LocalizedError::GetStrings(error.reason, error.domain.utf8(), | 145 LocalizedError::GetStrings(error.reason, error.domain.utf8(), |
162 error.unreachableURL, is_failed_post, | 146 error.unreachableURL, is_failed_post, |
163 error.staleCopyInCache, | 147 error.staleCopyInCache, |
164 RenderThread::Get()->GetLocale(), | 148 RenderThread::Get()->GetLocale(), |
165 render_frame()->GetRenderView()-> | 149 render_frame()->GetRenderView()-> |
166 GetAcceptLanguages(), | 150 GetAcceptLanguages(), |
167 params.Pass(), &error_strings); | 151 &error_strings); |
168 // "t" is the id of the template's root node. | 152 // "t" is the id of the template's root node. |
169 *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t"); | 153 *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t"); |
170 } | 154 } |
171 } | 155 } |
172 | 156 |
173 void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html, | 157 void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html, |
174 const GURL& failed_url) { | 158 const GURL& failed_url) { |
175 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView(); | 159 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView(); |
176 if (!web_view) | 160 if (!web_view) |
177 return; | 161 return; |
178 blink::WebFrame* frame = web_view->mainFrame(); | 162 blink::WebFrame* frame = web_view->mainFrame(); |
179 frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true); | 163 frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true); |
180 } | 164 } |
181 | 165 |
182 void NetErrorHelper::EnableStaleLoadBindings(const GURL& page_url) { | 166 void NetErrorHelper::EnableStaleLoadBindings(const GURL& page_url) { |
183 ErrorCacheLoad::Install(render_frame(), page_url); | 167 ErrorCacheLoad::Install(render_frame(), page_url); |
184 } | 168 } |
185 | 169 |
186 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error, | 170 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error, |
187 bool is_failed_post) { | 171 bool is_failed_post) { |
188 base::DictionaryValue error_strings; | 172 base::DictionaryValue error_strings; |
189 LocalizedError::GetStrings(error.reason, | 173 LocalizedError::GetStrings(error.reason, |
190 error.domain.utf8(), | 174 error.domain.utf8(), |
191 error.unreachableURL, | 175 error.unreachableURL, |
192 is_failed_post, | 176 is_failed_post, |
193 error.staleCopyInCache, | 177 error.staleCopyInCache, |
194 RenderThread::Get()->GetLocale(), | 178 RenderThread::Get()->GetLocale(), |
195 render_frame()->GetRenderView()-> | 179 render_frame()->GetRenderView()-> |
196 GetAcceptLanguages(), | 180 GetAcceptLanguages(), |
197 scoped_ptr<LocalizedError::ErrorPageParams>(), | |
198 &error_strings); | 181 &error_strings); |
199 | 182 |
200 std::string json; | 183 std::string json; |
201 JSONWriter::Write(&error_strings, &json); | 184 JSONWriter::Write(&error_strings, &json); |
202 | 185 |
203 std::string js = "if (window.updateForDnsProbe) " | 186 std::string js = "if (window.updateForDnsProbe) " |
204 "updateForDnsProbe(" + json + ");"; | 187 "updateForDnsProbe(" + json + ");"; |
205 base::string16 js16; | 188 base::string16 js16; |
206 if (!base::UTF8ToUTF16(js.c_str(), js.length(), &js16)) { | 189 if (!base::UTF8ToUTF16(js.c_str(), js.length(), &js16)) { |
207 NOTREACHED(); | 190 NOTREACHED(); |
208 return; | 191 return; |
209 } | 192 } |
210 | 193 |
211 render_frame()->ExecuteJavaScript(js16); | 194 render_frame()->ExecuteJavaScript(js16); |
212 } | 195 } |
213 | 196 |
214 void NetErrorHelper::FetchNavigationCorrections( | 197 void NetErrorHelper::FetchErrorPage(const GURL& url) { |
215 const GURL& navigation_correction_url, | 198 DCHECK(!alt_error_page_fetcher_.get()); |
216 const std::string& navigation_correction_request_body) { | |
217 DCHECK(!correction_fetcher_.get()); | |
218 | 199 |
219 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView(); | 200 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView(); |
220 if (!web_view) | 201 if (!web_view) |
221 return; | 202 return; |
222 blink::WebFrame* frame = web_view->mainFrame(); | 203 blink::WebFrame* frame = web_view->mainFrame(); |
223 | 204 |
224 correction_fetcher_.reset( | 205 alt_error_page_fetcher_.reset(content::ResourceFetcher::Create(url)); |
225 content::ResourceFetcher::Create(navigation_correction_url)); | 206 |
226 correction_fetcher_->SetMethod("POST"); | 207 alt_error_page_fetcher_->Start( |
227 correction_fetcher_->SetBody(navigation_correction_request_body); | |
228 correction_fetcher_->SetHeader("Content-Type", "application/json"); | |
229 correction_fetcher_->Start( | |
230 frame, blink::WebURLRequest::TargetIsMainFrame, | 208 frame, blink::WebURLRequest::TargetIsMainFrame, |
231 base::Bind(&NetErrorHelper::OnNavigationCorrectionsFetched, | 209 base::Bind(&NetErrorHelper::OnAlternateErrorPageRetrieved, |
232 base::Unretained(this))); | 210 base::Unretained(this))); |
233 | 211 |
234 correction_fetcher_->SetTimeout( | 212 alt_error_page_fetcher_->SetTimeout( |
235 base::TimeDelta::FromSeconds(kNavigationCorrectionFetchTimeoutSec)); | 213 base::TimeDelta::FromSeconds(kAlterErrorPageFetchTimeoutSec)); |
236 } | 214 } |
237 | 215 |
238 void NetErrorHelper::CancelFetchNavigationCorrections() { | 216 void NetErrorHelper::CancelFetchErrorPage() { |
239 correction_fetcher_.reset(); | 217 alt_error_page_fetcher_.reset(); |
240 } | 218 } |
241 | 219 |
242 void NetErrorHelper::ReloadPage() { | 220 void NetErrorHelper::ReloadPage() { |
243 render_frame()->GetWebFrame()->reload(false); | 221 render_frame()->GetWebFrame()->reload(false); |
244 } | 222 } |
245 | 223 |
246 void NetErrorHelper::OnNetErrorInfo(int status_num) { | 224 void NetErrorHelper::OnNetErrorInfo(int status_num) { |
247 DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX); | 225 DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX); |
248 | 226 |
249 DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num); | 227 DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num); |
250 | 228 |
251 core_.OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num)); | 229 core_.OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num)); |
252 } | 230 } |
253 | 231 |
254 void NetErrorHelper::OnSetNavigationCorrectionInfo( | 232 void NetErrorHelper::OnSetAltErrorPageURL(const GURL& alt_error_page_url) { |
255 const GURL& navigation_correction_url, | 233 core_.set_alt_error_page_url(alt_error_page_url); |
256 const std::string& language, | |
257 const std::string& country_code, | |
258 const std::string& api_key, | |
259 const GURL& search_url) { | |
260 core_.OnSetNavigationCorrectionInfo(navigation_correction_url, language, | |
261 country_code, api_key, search_url); | |
262 } | 234 } |
263 | 235 |
264 void NetErrorHelper::OnNavigationCorrectionsFetched( | 236 void NetErrorHelper::OnAlternateErrorPageRetrieved( |
265 const blink::WebURLResponse& response, | 237 const blink::WebURLResponse& response, |
266 const std::string& data) { | 238 const std::string& data) { |
267 // The fetcher may only be deleted after |data| is passed to |core_|. Move | 239 // The fetcher may only be deleted after |data| is passed to |core_|. Move |
268 // it to a temporary to prevent any potential re-entrancy issues. | 240 // it to a temporary to prevent any potential re-entrancy issues. |
269 scoped_ptr<content::ResourceFetcher> fetcher( | 241 scoped_ptr<content::ResourceFetcher> fetcher( |
270 correction_fetcher_.release()); | 242 alt_error_page_fetcher_.release()); |
271 if (!response.isNull() && response.httpStatusCode() == 200) { | 243 if (!response.isNull() && response.httpStatusCode() == 200) { |
272 core_.OnNavigationCorrectionsFetched( | 244 core_.OnAlternateErrorPageFetched(data); |
273 data, render_frame()->GetRenderView()->GetAcceptLanguages(), | |
274 LocaleIsRTL()); | |
275 } else { | 245 } else { |
276 core_.OnNavigationCorrectionsFetched( | 246 core_.OnAlternateErrorPageFetched(""); |
277 "", render_frame()->GetRenderView()->GetAcceptLanguages(), | |
278 LocaleIsRTL()); | |
279 } | 247 } |
280 } | 248 } |
OLD | NEW |