1d9529ad033a817fac667a8fde02be29a26fe5ac
[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/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/net/net_error_info.h"
18 #include "chrome/common/render_messages.h"
19 #include "chrome/renderer/net/error_cache_load.h"
20 #include "content/public/common/content_client.h"
21 #include "content/public/common/url_constants.h"
22 #include "content/public/renderer/content_renderer_client.h"
23 #include "content/public/renderer/render_frame.h"
24 #include "content/public/renderer/render_thread.h"
25 #include "content/public/renderer/render_view.h"
26 #include "content/public/renderer/resource_fetcher.h"
27 #include "grit/renderer_resources.h"
28 #include "ipc/ipc_message.h"
29 #include "ipc/ipc_message_macros.h"
30 #include "third_party/WebKit/public/platform/WebURL.h"
31 #include "third_party/WebKit/public/platform/WebURLError.h"
32 #include "third_party/WebKit/public/platform/WebURLRequest.h"
33 #include "third_party/WebKit/public/platform/WebURLResponse.h"
34 #include "third_party/WebKit/public/web/WebDataSource.h"
35 #include "third_party/WebKit/public/web/WebDocument.h"
36 #include "third_party/WebKit/public/web/WebFrame.h"
37 #include "third_party/WebKit/public/web/WebView.h"
38 #include "ui/base/resource/resource_bundle.h"
39 #include "ui/base/webui/jstemplate_builder.h"
40 #include "url/gurl.h"
41
42 using base::JSONWriter;
43 using chrome_common_net::DnsProbeStatus;
44 using chrome_common_net::DnsProbeStatusToString;
45 using content::RenderFrame;
46 using content::RenderFrameObserver;
47 using content::RenderThread;
48 using content::kUnreachableWebDataURL;
49
50 namespace {
51
52 // Number of seconds to wait for the navigation correction service to return
53 // suggestions.  If it takes too long, just use the local error page.
54 static const int kNavigationCorrectionFetchTimeoutSec = 3;
55
56 NetErrorHelperCore::PageType GetLoadingPageType(const blink::WebFrame* frame) {
57   GURL url = frame->provisionalDataSource()->request().url();
58   if (!url.is_valid() || url.spec() != kUnreachableWebDataURL)
59     return NetErrorHelperCore::NON_ERROR_PAGE;
60   return NetErrorHelperCore::ERROR_PAGE;
61 }
62
63 NetErrorHelperCore::FrameType GetFrameType(const blink::WebFrame* frame) {
64   if (!frame->parent())
65     return NetErrorHelperCore::MAIN_FRAME;
66   return NetErrorHelperCore::SUB_FRAME;
67 }
68
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
82
83 NetErrorHelper::NetErrorHelper(RenderFrame* render_view)
84     : RenderFrameObserver(render_view),
85       content::RenderFrameObserverTracker<NetErrorHelper>(render_view),
86       core_(this) {
87   RenderThread::Get()->AddObserver(this);
88   CommandLine* command_line = CommandLine::ForCurrentProcess();
89   bool auto_reload_enabled =
90       command_line->HasSwitch(switches::kEnableOfflineAutoReload);
91   core_.set_auto_reload_enabled(auto_reload_enabled);
92 }
93
94 NetErrorHelper::~NetErrorHelper() {
95   RenderThread::Get()->RemoveObserver(this);
96 }
97
98 void NetErrorHelper::DidStartProvisionalLoad() {
99   blink::WebFrame* frame = render_frame()->GetWebFrame();
100   core_.OnStartLoad(GetFrameType(frame), GetLoadingPageType(frame));
101 }
102
103 void NetErrorHelper::DidCommitProvisionalLoad(bool is_new_navigation) {
104   blink::WebFrame* frame = render_frame()->GetWebFrame();
105   core_.OnCommitLoad(GetFrameType(frame));
106 }
107
108 void NetErrorHelper::DidFinishLoad() {
109   blink::WebFrame* frame = render_frame()->GetWebFrame();
110   core_.OnFinishLoad(GetFrameType(frame));
111 }
112
113 void NetErrorHelper::OnStop() {
114   core_.OnStop();
115 }
116
117 bool NetErrorHelper::OnMessageReceived(const IPC::Message& message) {
118   bool handled = true;
119
120   IPC_BEGIN_MESSAGE_MAP(NetErrorHelper, message)
121     IPC_MESSAGE_HANDLER(ChromeViewMsg_NetErrorInfo, OnNetErrorInfo)
122     IPC_MESSAGE_HANDLER(ChromeViewMsg_SetNavigationCorrectionInfo,
123                         OnSetNavigationCorrectionInfo);
124     IPC_MESSAGE_UNHANDLED(handled = false)
125   IPC_END_MESSAGE_MAP()
126
127   return handled;
128 }
129
130 void NetErrorHelper::NetworkStateChanged(bool enabled) {
131   core_.NetworkStateChanged(enabled);
132 }
133
134 void NetErrorHelper::GetErrorHTML(
135     blink::WebFrame* frame,
136     const blink::WebURLError& error,
137     bool is_failed_post,
138     std::string* error_html) {
139   core_.GetErrorHTML(GetFrameType(frame), error, is_failed_post, error_html);
140 }
141
142 bool NetErrorHelper::ShouldSuppressErrorPage(blink::WebFrame* frame,
143                                              const GURL& url) {
144   return core_.ShouldSuppressErrorPage(GetFrameType(frame), url);
145 }
146
147 void NetErrorHelper::GenerateLocalizedErrorPage(
148     const blink::WebURLError& error,
149     bool is_failed_post,
150     scoped_ptr<LocalizedError::ErrorPageParams> params,
151     std::string* error_html) const {
152   error_html->clear();
153
154   int resource_id = IDR_NET_ERROR_HTML;
155   const base::StringPiece template_html(
156       ResourceBundle::GetSharedInstance().GetRawDataResource(resource_id));
157   if (template_html.empty()) {
158     NOTREACHED() << "unable to load template.";
159   } else {
160     base::DictionaryValue error_strings;
161     LocalizedError::GetStrings(error.reason, error.domain.utf8(),
162                                error.unreachableURL, is_failed_post,
163                                error.staleCopyInCache,
164                                RenderThread::Get()->GetLocale(),
165                                render_frame()->GetRenderView()->
166                                    GetAcceptLanguages(),
167                                params.Pass(), &error_strings);
168     // "t" is the id of the template's root node.
169     *error_html = webui::GetTemplatesHtml(template_html, &error_strings, "t");
170   }
171 }
172
173 void NetErrorHelper::LoadErrorPageInMainFrame(const std::string& html,
174                                               const GURL& failed_url) {
175   blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
176   if (!web_view)
177     return;
178   blink::WebFrame* frame = web_view->mainFrame();
179   frame->loadHTMLString(html, GURL(kUnreachableWebDataURL), failed_url, true);
180 }
181
182 void NetErrorHelper::EnableStaleLoadBindings(const GURL& page_url) {
183   ErrorCacheLoad::Install(render_frame(), page_url);
184 }
185
186 void NetErrorHelper::UpdateErrorPage(const blink::WebURLError& error,
187                                      bool is_failed_post) {
188   base::DictionaryValue error_strings;
189   LocalizedError::GetStrings(error.reason,
190                              error.domain.utf8(),
191                              error.unreachableURL,
192                              is_failed_post,
193                              error.staleCopyInCache,
194                              RenderThread::Get()->GetLocale(),
195                              render_frame()->GetRenderView()->
196                                  GetAcceptLanguages(),
197                              scoped_ptr<LocalizedError::ErrorPageParams>(),
198                              &error_strings);
199
200   std::string json;
201   JSONWriter::Write(&error_strings, &json);
202
203   std::string js = "if (window.updateForDnsProbe) "
204                    "updateForDnsProbe(" + json + ");";
205   base::string16 js16;
206   if (!base::UTF8ToUTF16(js.c_str(), js.length(), &js16)) {
207     NOTREACHED();
208     return;
209   }
210
211   render_frame()->ExecuteJavaScript(js16);
212 }
213
214 void NetErrorHelper::FetchNavigationCorrections(
215     const GURL& navigation_correction_url,
216     const std::string& navigation_correction_request_body) {
217   DCHECK(!correction_fetcher_.get());
218
219   blink::WebView* web_view = render_frame()->GetRenderView()->GetWebView();
220   if (!web_view)
221     return;
222   blink::WebFrame* frame = web_view->mainFrame();
223
224   correction_fetcher_.reset(
225       content::ResourceFetcher::Create(navigation_correction_url));
226   correction_fetcher_->SetMethod("POST");
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,
231       base::Bind(&NetErrorHelper::OnNavigationCorrectionsFetched,
232                      base::Unretained(this)));
233
234   correction_fetcher_->SetTimeout(
235       base::TimeDelta::FromSeconds(kNavigationCorrectionFetchTimeoutSec));
236 }
237
238 void NetErrorHelper::CancelFetchNavigationCorrections() {
239   correction_fetcher_.reset();
240 }
241
242 void NetErrorHelper::ReloadPage() {
243   render_frame()->GetWebFrame()->reload(false);
244 }
245
246 void NetErrorHelper::OnNetErrorInfo(int status_num) {
247   DCHECK(status_num >= 0 && status_num < chrome_common_net::DNS_PROBE_MAX);
248
249   DVLOG(1) << "Received status " << DnsProbeStatusToString(status_num);
250
251   core_.OnNetErrorInfo(static_cast<DnsProbeStatus>(status_num));
252 }
253
254 void NetErrorHelper::OnSetNavigationCorrectionInfo(
255     const GURL& navigation_correction_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 }
263
264 void NetErrorHelper::OnNavigationCorrectionsFetched(
265     const blink::WebURLResponse& response,
266     const std::string& data) {
267   // 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.
269   scoped_ptr<content::ResourceFetcher> fetcher(
270       correction_fetcher_.release());
271   if (!response.isNull() && response.httpStatusCode() == 200) {
272     core_.OnNavigationCorrectionsFetched(
273         data, render_frame()->GetRenderView()->GetAcceptLanguages(),
274         LocaleIsRTL());
275   } else {
276     core_.OnNavigationCorrectionsFetched(
277         "", render_frame()->GetRenderView()->GetAcceptLanguages(),
278         LocaleIsRTL());
279   }
280 }