Explicitly add python-numpy dependency to install-build-deps.
[chromium-blink-merge.git] / chrome / renderer / net / net_error_helper.cc
blobbe5b4d1e84084eeff6d46e7b448a2d62b4f25242
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
3 // found in the LICENSE file.
5 #include "chrome/renderer/net/net_error_helper.h"
7 #include <string>
9 #include "base/command_line.h"
10 #include "base/i18n/rtl.h"
11 #include "base/json/json_writer.h"
12 #include "base/metrics/histogram.h"
13 #include "base/strings/utf_string_conversions.h"
14 #include "base/values.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/localized_error.h"
17 #include "chrome/common/render_messages.h"
18 #include "chrome/grit/renderer_resources.h"
19 #include "chrome/renderer/net/net_error_page_controller.h"
20 #include "components/error_page/common/error_page_params.h"
21 #include "components/error_page/common/net_error_info.h"
22 #include "content/public/common/content_client.h"
23 #include "content/public/common/url_constants.h"
24 #include "content/public/renderer/content_renderer_client.h"
25 #include "content/public/renderer/document_state.h"
26 #include "content/public/renderer/render_frame.h"
27 #include "content/public/renderer/render_thread.h"
28 #include "content/public/renderer/render_view.h"
29 #include "content/public/renderer/resource_fetcher.h"
30 #include "ipc/ipc_message.h"
31 #include "ipc/ipc_message_macros.h"
32 #include "third_party/WebKit/public/platform/WebURL.h"
33 #include "third_party/WebKit/public/platform/WebURLError.h"
34 #include "third_party/WebKit/public/platform/WebURLRequest.h"
35 #include "third_party/WebKit/public/platform/WebURLResponse.h"
36 #include "third_party/WebKit/public/web/WebDataSource.h"
37 #include "third_party/WebKit/public/web/WebDocument.h"
38 #include "third_party/WebKit/public/web/WebLocalFrame.h"
39 #include "third_party/WebKit/public/web/WebView.h"
40 #include "ui/base/resource/resource_bundle.h"
41 #include "ui/base/webui/jstemplate_builder.h"
42 #include "url/gurl.h"
44 using base::JSONWriter;
45 using chrome_common_net::DnsProbeStatus;
46 using chrome_common_net::DnsProbeStatusToString;
47 using content::DocumentState;
48 using content::RenderFrame;
49 using content::RenderFrameObserver;
50 using content::RenderThread;
51 using content::kUnreachableWebDataURL;
52 using error_page::ErrorPageParams;
53 using error_page::NetErrorHelperCore;
55 namespace {
57 // Number of seconds to wait for the navigation correction service to return
58 // suggestions. If it takes too long, just use the local error page.
59 static const int kNavigationCorrectionFetchTimeoutSec = 3;
61 NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) {
62 GURL url = frame->provisionalDataSource()->request().url();
63 if (!url.is_valid() || url.spec() != kUnreachableWebDataURL)
64 return NetErrorHelperCore::NON_ERROR_PAGE;
65 return NetErrorHelperCore::ERROR_PAGE;
68 NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) {
69 if (!frame->parent())
70 return NetErrorHelperCore::MAIN_FRAME;
71 return NetErrorHelperCore::SUB_FRAME;
74 } // namespace
76 NetErrorHelper::NetErrorHelper(RenderFrame* render_frame)
77 : RenderFrameObserver(render_frame),
78 content::RenderFrameObserverTracker<NetErrorHelper>(render_frame) {
79 RenderThread::Get()->AddObserver(this);
80 CommandLine* command_line = CommandLine::ForCurrentProcess();
81 bool auto_reload_enabled =
82 command_line->HasSwitch(switches::kEnableOfflineAutoReload);
83 bool auto_reload_visible_only =
84 command_line->HasSwitch(switches::kEnableOfflineAutoReloadVisibleOnly);
85 core_.reset(new NetErrorHelperCore(this,
86 auto_reload_enabled,
87 auto_reload_visible_only,
88 !render_frame->IsHidden()));
91 NetErrorHelper::~NetErrorHelper() {
92 RenderThread::Get()->RemoveObserver(this);
95 void NetErrorHelper::ReloadButtonPressed() {
96 core_->ExecuteButtonPress(NetErrorHelperCore::RELOAD_BUTTON);
99 void NetErrorHelper::LoadStaleButtonPressed() {
100 core_->ExecuteButtonPress(NetErrorHelperCore::LOAD_STALE_BUTTON);
103 void NetErrorHelper::MoreButtonPressed() {
104 core_->ExecuteButtonPress(NetErrorHelperCore::MORE_BUTTON);
107 void NetErrorHelper::DidStartProvisionalLoad() {
108 blink::WebFrame* frame = render_frame()->GetWebFrame();
109 core_->OnStartLoad(GetFrameType(frame), GetLoadingPageType(frame));
112 void NetErrorHelper::DidCommitProvisionalLoad(bool is_new_navigation) {
113 blink::WebFrame* frame = render_frame()->GetWebFrame();
114 core_->OnCommitLoad(GetFrameType(frame), frame->document().url());
117 void NetErrorHelper::DidFinishLoad() {
118 blink::WebFrame* frame = render_frame()->GetWebFrame();
119 core_->OnFinishLoad(GetFrameType(frame));
122 void NetErrorHelper::OnStop() {
123 core_->OnStop();
126 void NetErrorHelper::WasShown() {
127 core_->OnWasShown();
130 void NetErrorHelper::WasHidden() {
131 core_->OnWasHidden();
134 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
135 bool handled = true;
137 IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
138 IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
139 IPC_MESSAGE_HANDLER(ChromeViewMsg_SetNavigationCorrectionInfo,
140 OnSetNavigationCorrectionInfo);
141 IPC_MESSAGE_UNHANDLED(handled = false)
142 IPC_END_MESSAGE_MAP()
144 return handled;
147 void NetErrorHelper::NetworkStateChanged(bool enabled) {
148 core_->NetworkStateChanged(enabled);
151 void NetErrorHelper::GetErrorHTML(
152 blink::WebFrame* frame,
153 const blink::WebURLError& error,
154 bool is_failed_post,
155 std::string* error_html) {
156 core_->GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html);
159 bool NetErrorHelper::ShouldSuppressErrorPage(blink::WebFrame* frame,
160 const GURL& url) {
161 return core_->ShouldSuppressErrorPage(GetFrameType(frame), url);
164 void NetErrorHelper::TrackClick(int tracking_id) {
165 core_->TrackClick(tracking_id);
168 void NetErrorHelper::GenerateLocalizedErrorPage(
169 const blink::WebURLError& error,
170 bool is_failed_post,
171 scoped_ptr<ErrorPageParams> params,
172 bool* reload_button_shown,
173 bool* load_stale_button_shown,
174 std::string* error_html) const {
175 error_html->clear();
177 int resource_id = IDR_NET_ERROR_HTML;
178 const base::StringPiece template_html(
179 ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
180 if (template_html.empty()) {
181 NOTREACHED() << "unable to load template.";
182 } else {
183 CommandLine* command_line = CommandLine::ForCurrentProcess();
184 bool load_stale_cache_enabled =
185 command_line->HasSwitch(switches::kEnableOfflineLoadStaleCache);
187 base::DictionaryValue error_strings;
188 LocalizedError::GetStrings(error.reason, error.domain.utf8(),
189 error.unreachableURL, is_failed_post,
190 (load_stale_cache_enabled &&
191 error.staleCopyInCache && !is_failed_post),
192 RenderThread::Get()->GetLocale(),
193 render_frame()->GetRenderView()->
194 GetAcceptLanguages(),
195 params.Pass(), &error_strings);
196 *reload_button_shown = error_strings.Get("reloadButton", NULL);
197 *load_stale_button_shown = error_strings.Get("staleLoadButton", NULL);
199 // "t" is the id of the template's root node.
200 *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t");
204 void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html,
205 const GURL& failed_url) {
206 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
207 if (!web_view)
208 return;
209 blink::WebFrame* frame = web_view->mainFrame();
210 frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true);
213 void NetErrorHelper::EnablePageHelperFunctions() {
214 NetErrorPageController::Install(render_frame());
217 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error,
218 bool is_failed_post) {
219 CommandLine* command_line = CommandLine::ForCurrentProcess();
220 bool load_stale_cache_enabled =
221 command_line->HasSwitch(switches::kEnableOfflineLoadStaleCache);
223 base::DictionaryValue error_strings;
224 LocalizedError::GetStrings(error.reason,
225 error.domain.utf8(),
226 error.unreachableURL,
227 is_failed_post,
228 (load_stale_cache_enabled &&
229 error.staleCopyInCache && !is_failed_post),
230 RenderThread::Get()->GetLocale(),
231 render_frame()->GetRenderView()->
232 GetAcceptLanguages(),
233 scoped_ptr<ErrorPageParams>(),
234 &error_strings);
236 std::string json;
237 JSONWriter::Write(&error_strings, &json);
239 std::string js = "if (window.updateForDnsProbe) "
240 "updateForDnsProbe(" + json + ");";
241 base::string16 js16;
242 if (!base::UTF8ToUTF16(js.c_str(), js.length(), &js16)) {
243 NOTREACHED();
244 return;
247 render_frame()->ExecuteJavaScript(js16);
250 void NetErrorHelper::FetchNavigationCorrections(
251 const GURL& navigation_correction_url,
252 const std::string& navigation_correction_request_body) {
253 DCHECK(!correction_fetcher_.get());
255 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
256 if (!web_view)
257 return;
258 blink::WebFrame* frame = web_view->mainFrame();
260 correction_fetcher_.reset(
261 content::ResourceFetcher::Create(navigation_correction_url));
262 correction_fetcher_->SetMethod("POST");
263 correction_fetcher_->SetBody(navigation_correction_request_body);
264 correction_fetcher_->SetHeader("Content-Type", "application/json");
266 correction_fetcher_->Start(
267 frame,
268 blink::WebURLRequest::RequestContextInternal,
269 blink::WebURLRequest::FrameTypeTopLevel,
270 content::ResourceFetcher::PLATFORM_LOADER,
271 base::Bind(&NetErrorHelper::OnNavigationCorrectionsFetched,
272 base::Unretained(this)));
274 correction_fetcher_->SetTimeout(
275 base::TimeDelta::FromSeconds(kNavigationCorrectionFetchTimeoutSec));
278 void NetErrorHelper::CancelFetchNavigationCorrections() {
279 correction_fetcher_.reset();
282 void NetErrorHelper::SendTrackingRequest(
283 const GURL& tracking_url,
284 const std::string& tracking_request_body) {
285 blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
286 if (!web_view)
287 return;
288 blink::WebFrame* frame = web_view->mainFrame();
290 // If there's already a pending tracking request, this will cancel it.
291 tracking_fetcher_.reset(content::ResourceFetcher::Create(tracking_url));
292 tracking_fetcher_->SetMethod("POST");
293 tracking_fetcher_->SetBody(tracking_request_body);
294 tracking_fetcher_->SetHeader("Content-Type", "application/json");
296 tracking_fetcher_->Start(
297 frame,
298 blink::WebURLRequest::RequestContextInternal,
299 blink::WebURLRequest::FrameTypeTopLevel,
300 content::ResourceFetcher::PLATFORM_LOADER,
301 base::Bind(&NetErrorHelper::OnTrackingRequestComplete,
302 base::Unretained(this)));
305 void NetErrorHelper::ReloadPage() {
306 render_frame()->GetWebFrame()->reload(false);
309 void NetErrorHelper::LoadPageFromCache(const GURL& page_url) {
310 blink::WebFrame* web_frame = render_frame()->GetWebFrame();
311 DCHECK(!EqualsASCII(web_frame->dataSource()->request().httpMethod(), "POST"));
313 blink::WebURLRequest request(page_url);
314 request.setCachePolicy(blink::WebURLRequest::ReturnCacheDataDontLoad);
316 web_frame->loadRequest(request);
319 void NetErrorHelper::OnNetErrorInfo(int status_num) {
320 DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX);
322 DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num);
324 core_->OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num));
327 void NetErrorHelper::OnSetNavigationCorrectionInfo(
328 const GURL& navigation_correction_url,
329 const std::string& language,
330 const std::string& country_code,
331 const std::string& api_key,
332 const GURL& search_url) {
333 core_->OnSetNavigationCorrectionInfo(navigation_correction_url, language,
334 country_code, api_key, search_url);
337 void NetErrorHelper::OnNavigationCorrectionsFetched(
338 const blink::WebURLResponse& response,
339 const std::string& data) {
340 // The fetcher may only be deleted after |data| is passed to |core_|. Move
341 // it to a temporary to prevent any potential re-entrancy issues.
342 scoped_ptr<content::ResourceFetcher> fetcher(
343 correction_fetcher_.release());
344 bool success = (!response.isNull() && response.httpStatusCode() == 200);
345 core_->OnNavigationCorrectionsFetched(
346 success ? data : "",
347 render_frame()->GetRenderView()->GetAcceptLanguages(),
348 base::i18n::IsRTL());
351 void NetErrorHelper::OnTrackingRequestComplete(
352 const blink::WebURLResponse& response,
353 const std::string& data) {
354 tracking_fetcher_.reset();