d2b4d7981e3ed349213d21b4116c111a5ef9b269
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / renderer / xwalk_content_renderer_client.cc
1 // Copyright (c) 2013 Intel Corporation. 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 "xwalk/runtime/renderer/xwalk_content_renderer_client.h"
6
7 #include "base/command_line.h"
8 #include "base/strings/utf_string_conversions.h"
9 #include "components/nacl/renderer/ppb_nacl_private_impl.h"
10 #include "components/visitedlink/renderer/visitedlink_slave.h"
11 #include "content/public/renderer/render_frame.h"
12 #include "content/public/renderer/render_frame_observer.h"
13 #include "content/public/renderer/render_frame_observer_tracker.h"
14 #include "content/public/renderer/render_thread.h"
15 #include "grit/xwalk_application_resources.h"
16 #include "grit/xwalk_sysapps_resources.h"
17 #include "third_party/WebKit/public/platform/WebString.h"
18 #include "third_party/WebKit/public/platform/WebURLRequest.h"
19 #include "third_party/WebKit/public/web/WebDocument.h"
20 #include "third_party/WebKit/public/web/WebSecurityPolicy.h"
21 #include "xwalk/application/common/constants.h"
22 #include "xwalk/application/renderer/application_native_module.h"
23 #include "xwalk/extensions/common/xwalk_extension_switches.h"
24 #include "xwalk/extensions/renderer/xwalk_js_module.h"
25 #include "xwalk/runtime/common/xwalk_localized_error.h"
26 #include "xwalk/runtime/renderer/isolated_file_system.h"
27 #include "xwalk/runtime/renderer/pepper/pepper_helper.h"
28
29 #if defined(OS_ANDROID)
30 #include "xwalk/runtime/browser/android/net/url_constants.h"
31 #include "xwalk/runtime/renderer/android/xwalk_permission_client.h"
32 #include "xwalk/runtime/renderer/android/xwalk_render_process_observer.h"
33 #include "xwalk/runtime/renderer/android/xwalk_render_view_ext.h"
34 #else
35 #include "third_party/WebKit/public/web/WebFrame.h"
36 #endif
37
38 #if defined(OS_TIZEN)
39 #include "xwalk/runtime/common/xwalk_common_messages.h"
40 #endif
41
42 #if defined(OS_TIZEN_MOBILE)
43 #include "xwalk/runtime/renderer/tizen/xwalk_content_renderer_client_tizen.h"
44 #endif
45
46 #if defined(OS_TIZEN)
47 #include "xwalk/runtime/renderer/tizen/xwalk_render_view_ext_tizen.h"
48 #endif
49
50 namespace xwalk {
51
52 namespace {
53
54 xwalk::XWalkContentRendererClient* g_renderer_client;
55
56 class XWalkFrameHelper
57     : public content::RenderFrameObserver,
58       public content::RenderFrameObserverTracker<XWalkFrameHelper> {
59  public:
60   XWalkFrameHelper(
61       content::RenderFrame* render_frame,
62       extensions::XWalkExtensionRendererController* extension_controller)
63       : content::RenderFrameObserver(render_frame),
64         content::RenderFrameObserverTracker<XWalkFrameHelper>(render_frame),
65         extension_controller_(extension_controller) {}
66   virtual ~XWalkFrameHelper() {}
67
68   // RenderFrameObserver implementation.
69   virtual void WillReleaseScriptContext(v8::Handle<v8::Context> context,
70                                         int world_id) OVERRIDE {
71     if (extension_controller_)
72       extension_controller_->WillReleaseScriptContext(
73           render_frame()->GetWebFrame(), context);
74   }
75
76 #if defined(OS_TIZEN)
77   virtual void DidCommitProvisionalLoad(bool is_new_navigation) OVERRIDE {
78     blink::WebFrame* frame = render_frame()->GetWebFrame();
79     GURL url(frame->document().url());
80     if (url.SchemeIs(application::kApplicationScheme)) {
81       blink::WebSecurityOrigin origin = frame->document().securityOrigin();
82       origin.grantLoadLocalResources();
83     }
84   }
85 #endif
86
87  private:
88   extensions::XWalkExtensionRendererController* extension_controller_;
89
90   DISALLOW_COPY_AND_ASSIGN(XWalkFrameHelper);
91 };
92
93 }  // namespace
94
95 XWalkContentRendererClient* XWalkContentRendererClient::Get() {
96   return g_renderer_client;
97 }
98
99 XWalkContentRendererClient::XWalkContentRendererClient() {
100   DCHECK(!g_renderer_client);
101   g_renderer_client = this;
102 }
103
104 XWalkContentRendererClient::~XWalkContentRendererClient() {
105   g_renderer_client = NULL;
106 }
107
108 void XWalkContentRendererClient::RenderThreadStarted() {
109   CommandLine* cmd_line = CommandLine::ForCurrentProcess();
110   if (!cmd_line->HasSwitch(switches::kXWalkDisableExtensions))
111     extension_controller_.reset(
112         new extensions::XWalkExtensionRendererController(this));
113
114   blink::WebString application_scheme(
115       base::ASCIIToUTF16(application::kApplicationScheme));
116   blink::WebSecurityPolicy::registerURLSchemeAsSecure(application_scheme);
117   blink::WebSecurityPolicy::registerURLSchemeAsCORSEnabled(application_scheme);
118
119   content::RenderThread* thread = content::RenderThread::Get();
120   xwalk_render_process_observer_.reset(new XWalkRenderProcessObserver);
121   thread->AddObserver(xwalk_render_process_observer_.get());
122 #if defined(OS_ANDROID)
123   blink::WebString content_scheme(
124       base::ASCIIToUTF16(xwalk::kContentScheme));
125   blink::WebSecurityPolicy::registerURLSchemeAsLocal(content_scheme);
126
127   visited_link_slave_.reset(new visitedlink::VisitedLinkSlave);
128   thread->AddObserver(visited_link_slave_.get());
129 #endif
130 }
131
132 void XWalkContentRendererClient::RenderFrameCreated(
133     content::RenderFrame* render_frame) {
134   new XWalkFrameHelper(render_frame, extension_controller_.get());
135 #if defined(OS_ANDROID)
136   new XWalkPermissionClient(render_frame);
137 #endif
138
139 #if defined(ENABLE_PLUGINS)
140   new PepperHelper(render_frame);
141 #endif
142 }
143
144 void XWalkContentRendererClient::RenderViewCreated(
145     content::RenderView* render_view) {
146 #if defined(OS_ANDROID)
147   XWalkRenderViewExt::RenderViewCreated(render_view);
148 #elif defined(OS_TIZEN)
149   XWalkRenderViewExtTizen::RenderViewCreated(render_view);
150 #endif
151 }
152
153 void XWalkContentRendererClient::DidCreateScriptContext(
154     blink::WebFrame* frame, v8::Handle<v8::Context> context,
155     int extension_group, int world_id) {
156   if (extension_controller_)
157     extension_controller_->DidCreateScriptContext(frame, context);
158 #if !defined(OS_ANDROID)
159   xwalk_render_process_observer_->DidCreateScriptContext(
160       frame, context, extension_group, world_id);
161 #endif
162 }
163
164 void XWalkContentRendererClient::DidCreateModuleSystem(
165     extensions::XWalkModuleSystem* module_system) {
166   scoped_ptr<extensions::XWalkNativeModule> app_module(
167       new application::ApplicationNativeModule());
168   module_system->RegisterNativeModule("application", app_module.Pass());
169   scoped_ptr<extensions::XWalkNativeModule> isolated_file_system_module(
170       new extensions::IsolatedFileSystem());
171   module_system->RegisterNativeModule("isolated_file_system",
172       isolated_file_system_module.Pass());
173   module_system->RegisterNativeModule("sysapps_common",
174       extensions::CreateJSModuleFromResource(IDR_XWALK_SYSAPPS_COMMON_API));
175   module_system->RegisterNativeModule("sysapps_promise",
176       extensions::CreateJSModuleFromResource(
177           IDR_XWALK_SYSAPPS_COMMON_PROMISE_API));
178   module_system->RegisterNativeModule("widget_common",
179       extensions::CreateJSModuleFromResource(
180           IDR_XWALK_APPLICATION_WIDGET_COMMON_API));
181 }
182
183 const void* XWalkContentRendererClient::CreatePPAPIInterface(
184     const std::string& interface_name) {
185 #if defined(ENABLE_PLUGINS) && !defined(DISABLE_NACL)
186   if (interface_name == PPB_NACL_PRIVATE_INTERFACE)
187     return nacl::GetNaClPrivateInterface();
188 #endif
189   return NULL;
190 }
191
192 bool XWalkContentRendererClient::IsExternalPepperPlugin(
193     const std::string& module_name) {
194   // TODO(bbudge) remove this when the trusted NaCl plugin has been removed.
195   // We must defer certain plugin events for NaCl instances since we switch
196   // from the in-process to the out-of-process proxy after instantiating them.
197   return module_name == "Native Client";
198 }
199
200 #if defined(OS_ANDROID)
201 unsigned long long XWalkContentRendererClient::VisitedLinkHash( // NOLINT
202     const char* canonical_url, size_t length) {
203   return visited_link_slave_->ComputeURLFingerprint(canonical_url, length);
204 }
205
206 bool XWalkContentRendererClient::IsLinkVisited(unsigned long long link_hash) { // NOLINT
207   return visited_link_slave_->IsVisited(link_hash);
208 }
209 #endif
210
211 bool XWalkContentRendererClient::WillSendRequest(blink::WebFrame* frame,
212                      content::PageTransition transition_type,
213                      const GURL& url,
214                      const GURL& first_party_for_cookies,
215                      GURL* new_url) {
216 #if defined(OS_ANDROID)
217   return false;
218 #else
219   if (!xwalk_render_process_observer_->IsWarpMode()
220 #if defined(OS_TIZEN)
221       && !xwalk_render_process_observer_->IsCSPMode()
222 #endif
223       )
224     return false;
225
226   GURL origin_url(frame->document().url());
227   GURL app_url(xwalk_render_process_observer_->app_url());
228 #if defined(OS_TIZEN)
229   // if under CSP mode.
230   if (xwalk_render_process_observer_->IsCSPMode()) {
231     if (url.GetOrigin() != app_url.GetOrigin() &&
232         origin_url != first_party_for_cookies &&
233         !first_party_for_cookies.is_empty() &&
234         first_party_for_cookies.GetOrigin() != app_url.GetOrigin() &&
235         !blink::WebSecurityOrigin::create(app_url).canRequest(url)) {
236       LOG(INFO) << "[BLOCK] allow-navigation: " << url.spec();
237       content::RenderThread::Get()->Send(new ViewMsg_OpenLinkExternal(url));
238       *new_url = GURL();
239       return true;
240     }
241     return false;
242   }
243 #endif
244   // if under WARP mode.
245   if (url.GetOrigin() == app_url.GetOrigin() ||
246       frame->document().securityOrigin().canRequest(url)) {
247     LOG(INFO) << "[PASS] " << origin_url.spec() << " request " << url.spec();
248     return false;
249   }
250
251   LOG(INFO) << "[BLOCK] " << origin_url.spec() << " request " << url.spec();
252 #if defined(OS_TIZEN)
253   if (url.GetOrigin() != app_url.GetOrigin() &&
254       origin_url != first_party_for_cookies &&
255       first_party_for_cookies.GetOrigin() != app_url.GetOrigin())
256     content::RenderThread::Get()->Send(new ViewMsg_OpenLinkExternal(url));
257 #endif
258
259   *new_url = GURL();
260   return true;
261 #endif
262 }
263
264 void XWalkContentRendererClient::GetNavigationErrorStrings(
265     content::RenderView* render_view,
266     blink::WebFrame* frame,
267     const blink::WebURLRequest& failed_request,
268     const blink::WebURLError& error,
269     std::string* error_html,
270     base::string16* error_description) {
271   bool is_post = EqualsASCII(failed_request.httpMethod(), "POST");
272
273   // TODO(guangzhen): Check whether error_html is needed in xwalk runtime.
274
275   if (error_description) {
276     *error_description = LocalizedError::GetErrorDetails(error, is_post);
277   }
278 }
279
280 }  // namespace xwalk