Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / renderer / net / net_error_helper.cc
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.
4
5 #include "chrome/renderer/net/net_error_helper.h"
6
7 #include <string>
8
9 #include "base/json/json_writer.h"
10 #include "base/metrics/histogram.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/values.h"
13 #include "chrome/common/localized_error.h"
14 #include "chrome/common/net/net_error_info.h"
15 #include "chrome/common/render_messages.h"
16 #include "content/public/common/content_client.h"
17 #include "content/public/common/url_constants.h"
18 #include "content/public/renderer/content_renderer_client.h"
19 #include "content/public/renderer/render_frame.h"
20 #include "content/public/renderer/render_thread.h"
21 #include "content/public/renderer/render_view.h"
22 #include "content/public/renderer/resource_fetcher.h"
23 #include "grit/renderer_resources.h"
24 #include "ipc/ipc_message.h"
25 #include "ipc/ipc_message_macros.h"
26 #include "third_party/WebKit/public/platform/WebURL.h"
27 #include "third_party/WebKit/public/platform/WebURLError.h"
28 #include "third_party/WebKit/public/platform/WebURLRequest.h"
29 #include "third_party/WebKit/public/platform/WebURLResponse.h"
30 #include "third_party/WebKit/public/web/WebDataSource.h"
31 #include "third_party/WebKit/public/web/WebDocument.h"
32 #include "third_party/WebKit/public/web/WebFrame.h"
33 #include "third_party/WebKit/public/web/WebView.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "ui/base/webui/jstemplate_builder.h"
36 #include "url/gurl.h"
37
38 using base::JSONWriter;
39 using chrome_common_net::DnsProbeStatus;
40 using chrome_common_net::DnsProbeStatusToString;
41 using content::RenderFrame;
42 using content::RenderFrameObserver;
43 using content::RenderThread;
44 using content::kUnreachableWebDataURL;
45
46 namespace {
47
48 // Number of seconds to wait for the alternate error page server.  If it takes
49 // too long, just use the local error page.
50 static const int kAlterErrorPageFetchTimeoutSec = 3000;
51
52 NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) {
53   GURL url = frame->provisionalDataSource()->request().url();
54   if (!url.is_valid() || url.spec() != kUnreachableWebDataURL)
55     return NetErrorHelperCore::NON_ERROR_PAGE;
56   return NetErrorHelperCore::ERROR_PAGE;
57 }
58
59 NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) {
60   if (!frame->parent())
61     return NetErrorHelperCore::MAIN_FRAME;
62   return NetErrorHelperCore::SUB_FRAME;
63 }
64
65 }  // namespace
66
67 NetErrorHelper::NetErrorHelper(RenderFrame* render_view)
68     : RenderFrameObserver(render_view),
69       content::RenderFrameObserverTracker<NetErrorHelper>(render_view),
70       core_(this) {
71 }
72
73 NetErrorHelper::~NetErrorHelper() {
74 }
75
76 void NetErrorHelper::DidStartProvisionalLoad() {
77   blink::WebFrame* frame = render_frame()->GetWebFrame();
78   core_.OnStartLoad(GetFrameType(frame), GetLoadingPageType(frame));
79 }
80
81 void NetErrorHelper::DidCommitProvisionalLoad(bool is_new_navigation) {
82   blink::WebFrame* frame = render_frame()->GetWebFrame();
83   core_.OnCommitLoad(GetFrameType(frame));
84 }
85
86 void NetErrorHelper::DidFinishLoad() {
87   blink::WebFrame* frame = render_frame()->GetWebFrame();
88   core_.OnFinishLoad(GetFrameType(frame));
89 }
90
91 void NetErrorHelper::OnStop() {
92   core_.OnStop();
93 }
94
95 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
96   bool handled = true;
97
98   IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
99     IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
100     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetAltErrorPageURL, OnSetAltErrorPageURL);
101     IPC_MESSAGE_UNHANDLED(handled = false)
102   IPC_END_MESSAGE_MAP()
103
104   return handled;
105 }
106
107 void NetErrorHelper::GetErrorHTML(
108     blink::WebFrame* frame,
109     const blink::WebURLError& error,
110     bool is_failed_post,
111     std::string* error_html) {
112   core_.GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html);
113 }
114
115 void NetErrorHelper::GenerateLocalizedErrorPage(const blink::WebURLError& error,
116                                                 bool is_failed_post,
117                                                 std::string* error_html) const {
118   error_html->clear();
119
120   int resource_id = IDR_NET_ERROR_HTML;
121   const base::StringPiece template_html(
122       ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
123   if (template_html.empty()) {
124     NOTREACHED() << "unable to load template.";
125   } else {
126     base::DictionaryValue error_strings;
127     LocalizedError::GetStrings(error.reason, error.domain.utf8(),
128                                error.unreachableURL, is_failed_post,
129                                error.staleCopyInCache,
130                                RenderThread::Get()->GetLocale(),
131                                render_frame()->GetRenderView()->
132                                    GetAcceptLanguages(),
133                                &error_strings);
134     // "t" is the id of the template's root node.
135     *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t");
136   }
137 }
138
139 void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html,
140                                               const GURL& failed_url) {
141   blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
142   if (!web_view)
143     return;
144   blink::WebFrame* frame = web_view->mainFrame();
145   frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true);
146 }
147
148 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error,
149                                      bool is_failed_post) {
150   base::DictionaryValue error_strings;
151   LocalizedError::GetStrings(error.reason,
152                              error.domain.utf8(),
153                              error.unreachableURL,
154                              is_failed_post,
155                              error.staleCopyInCache,
156                              RenderThread::Get()->GetLocale(),
157                              render_frame()->GetRenderView()->
158                                  GetAcceptLanguages(),
159                              &error_strings);
160
161   std::string json;
162   JSONWriter::Write(&error_strings, &json);
163
164   std::string js = "if (window.updateForDnsProbe) "
165                    "updateForDnsProbe(" + json + ");";
166   base::string16 js16;
167   if (!base::UTF8ToUTF16(js.c_str(), js.length(), &js16)) {
168     NOTREACHED();
169     return;
170   }
171
172   base::string16 frame_xpath;
173   render_frame()->GetRenderView()->EvaluateScript(frame_xpath, js16, 0, false);
174 }
175
176 void NetErrorHelper::FetchErrorPage(const GURL& url) {
177   DCHECK(!alt_error_page_fetcher_.get());
178
179   blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
180   if (!web_view)
181     return;
182   blink::WebFrame* frame = web_view->mainFrame();
183
184   alt_error_page_fetcher_.reset(content::ResourceFetcher::Create(url));
185
186   alt_error_page_fetcher_->Start(
187       frame, blink::WebURLRequest::TargetIsMainFrame,
188       base::Bind(&NetErrorHelper::OnAlternateErrorPageRetrieved,
189                      base::Unretained(this)));
190
191   alt_error_page_fetcher_->SetTimeout(
192       base::TimeDelta::FromSeconds(kAlterErrorPageFetchTimeoutSec));
193 }
194
195 void NetErrorHelper::CancelFetchErrorPage() {
196   alt_error_page_fetcher_.reset();
197 }
198
199 void NetErrorHelper::OnNetErrorInfo(int status_num) {
200   DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX);
201
202   DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num);
203
204   core_.OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num));
205 }
206
207 void NetErrorHelper::OnSetAltErrorPageURL(const GURL& alt_error_page_url) {
208   core_.set_alt_error_page_url(alt_error_page_url);
209 }
210
211 void NetErrorHelper::OnAlternateErrorPageRetrieved(
212     const blink::WebURLResponse& response,
213     const std::string& data) {
214   // The fetcher may only be deleted after |data| is passed to |core_|.  Move
215   // it to a temporary to prevent any potential re-entrancy issues.
216   scoped_ptr<content::ResourceFetcher> fetcher(
217       alt_error_page_fetcher_.release());
218   if (!response.isNull() && response.httpStatusCode() == 200) {
219     core_.OnAlternateErrorPageFetched(data);
220   } else {
221     core_.OnAlternateErrorPageFetched("");
222   }
223 }