Upstream version 9.38.198.0
[platform/framework/web/crosswalk.git] / src / xwalk / runtime / browser / xwalk_content_browser_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/browser/xwalk_content_browser_client.h"
6
7 #include <string>
8 #include <vector>
9
10 #include "base/command_line.h"
11 #include "base/path_service.h"
12 #include "base/files/file.h"
13 #include "content/public/browser/browser_child_process_host.h"
14 #include "content/public/browser/browser_main_parts.h"
15 #include "content/public/browser/browser_ppapi_host.h"
16 #include "content/public/browser/child_process_data.h"
17 #include "content/public/browser/render_frame_host.h"
18 #include "content/public/browser/render_process_host.h"
19 #include "content/public/browser/resource_context.h"
20 #include "content/public/browser/storage_partition.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/common/main_function_params.h"
23 #include "content/public/common/show_desktop_notification_params.h"
24 #include "net/ssl/ssl_info.h"
25 #include "net/url_request/url_request_context_getter.h"
26 #include "ppapi/host/ppapi_host.h"
27 #include "xwalk/extensions/common/xwalk_extension_switches.h"
28 #include "xwalk/application/common/constants.h"
29 #include "xwalk/runtime/browser/xwalk_browser_main_parts.h"
30 #include "xwalk/runtime/browser/geolocation/xwalk_access_token_store.h"
31 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
32 #include "xwalk/runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h"
33 #include "xwalk/runtime/browser/runtime_context.h"
34 #include "xwalk/runtime/browser/runtime_quota_permission_context.h"
35 #include "xwalk/runtime/browser/speech/speech_recognition_manager_delegate.h"
36 #include "xwalk/runtime/browser/xwalk_render_message_filter.h"
37 #include "xwalk/runtime/browser/xwalk_runner.h"
38 #include "xwalk/runtime/common/xwalk_paths.h"
39
40 #if !defined(DISABLE_NACL)
41 #include "components/nacl/browser/nacl_browser.h"
42 #include "components/nacl/browser/nacl_host_message_filter.h"
43 #include "components/nacl/browser/nacl_process_host.h"
44 #include "components/nacl/common/nacl_process_type.h"
45 #endif
46
47 #if defined(OS_ANDROID)
48 #include "base/android/path_utils.h"
49 #include "base/base_paths_android.h"
50 #include "xwalk/runtime/browser/android/xwalk_cookie_access_policy.h"
51 #include "xwalk/runtime/browser/android/xwalk_contents_client_bridge.h"
52 #include "xwalk/runtime/browser/android/xwalk_web_contents_view_delegate.h"
53 #include "xwalk/runtime/browser/runtime_resource_dispatcher_host_delegate_android.h"
54 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
55 #include "xwalk/runtime/common/android/xwalk_globals_android.h"
56 #else
57 #include "xwalk/application/browser/application_system.h"
58 #include "xwalk/application/browser/application_service.h"
59 #include "xwalk/application/browser/application.h"
60 #endif
61
62 #if defined(OS_MACOSX)
63 #include "xwalk/runtime/browser/xwalk_browser_main_parts_mac.h"
64 #endif
65
66 #if defined(OS_TIZEN)
67 #include "xwalk/application/common/application_manifest_constants.h"
68 #include "xwalk/application/common/manifest_handlers/navigation_handler.h"
69 #include "xwalk/runtime/browser/runtime_platform_util.h"
70 #include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
71 #endif
72
73 namespace xwalk {
74
75 namespace {
76
77 // The application-wide singleton of ContentBrowserClient impl.
78 XWalkContentBrowserClient* g_browser_client = NULL;
79
80 }  // namespace
81
82 // static
83 XWalkContentBrowserClient* XWalkContentBrowserClient::Get() {
84   return g_browser_client;
85 }
86
87
88 XWalkContentBrowserClient::XWalkContentBrowserClient(XWalkRunner* xwalk_runner)
89     : xwalk_runner_(xwalk_runner),
90       url_request_context_getter_(NULL),
91       main_parts_(NULL) {
92   DCHECK(!g_browser_client);
93   g_browser_client = this;
94 }
95
96 XWalkContentBrowserClient::~XWalkContentBrowserClient() {
97   DCHECK(g_browser_client);
98   g_browser_client = NULL;
99 }
100
101 content::BrowserMainParts* XWalkContentBrowserClient::CreateBrowserMainParts(
102     const content::MainFunctionParams& parameters) {
103 #if defined(OS_MACOSX)
104   main_parts_ = new XWalkBrowserMainPartsMac(parameters);
105 #elif defined(OS_ANDROID)
106   main_parts_ = new XWalkBrowserMainPartsAndroid(parameters);
107 #elif defined(OS_TIZEN)
108   main_parts_ = new XWalkBrowserMainPartsTizen(parameters);
109 #else
110   main_parts_ = new XWalkBrowserMainParts(parameters);
111 #endif
112
113   return main_parts_;
114 }
115
116 net::URLRequestContextGetter* XWalkContentBrowserClient::CreateRequestContext(
117     content::BrowserContext* browser_context,
118     content::ProtocolHandlerMap* protocol_handlers,
119     content::URLRequestInterceptorScopedVector request_interceptors) {
120   url_request_context_getter_ = static_cast<RuntimeContext*>(browser_context)->
121       CreateRequestContext(protocol_handlers, request_interceptors.Pass());
122   return url_request_context_getter_;
123 }
124
125 net::URLRequestContextGetter*
126 XWalkContentBrowserClient::CreateRequestContextForStoragePartition(
127     content::BrowserContext* browser_context,
128     const base::FilePath& partition_path,
129     bool in_memory,
130     content::ProtocolHandlerMap* protocol_handlers,
131     content::URLRequestInterceptorScopedVector request_interceptors) {
132   return static_cast<RuntimeContext*>(browser_context)->
133       CreateRequestContextForStoragePartition(
134           partition_path, in_memory, protocol_handlers,
135           request_interceptors.Pass());
136 }
137
138 // This allow us to append extra command line switches to the child
139 // process we launch.
140 void XWalkContentBrowserClient::AppendExtraCommandLineSwitches(
141     CommandLine* command_line, int child_process_id) {
142   CommandLine* browser_process_cmd_line = CommandLine::ForCurrentProcess();
143   const int extra_switches_count = 1;
144   const char* extra_switches[extra_switches_count] = {
145     switches::kXWalkDisableExtensionProcess
146   };
147
148   for (int i = 0; i < extra_switches_count; i++) {
149     if (browser_process_cmd_line->HasSwitch(extra_switches[i]))
150       command_line->AppendSwitch(extra_switches[i]);
151   }
152 }
153
154 content::QuotaPermissionContext*
155 XWalkContentBrowserClient::CreateQuotaPermissionContext() {
156   return new RuntimeQuotaPermissionContext();
157 }
158
159 content::AccessTokenStore* XWalkContentBrowserClient::CreateAccessTokenStore() {
160   return new XWalkAccessTokenStore(url_request_context_getter_);
161 }
162
163 content::WebContentsViewDelegate*
164 XWalkContentBrowserClient::GetWebContentsViewDelegate(
165     content::WebContents* web_contents) {
166 #if defined(OS_ANDROID)
167   return new XWalkWebContentsViewDelegate(web_contents);
168 #else
169   return NULL;
170 #endif
171 }
172
173 void XWalkContentBrowserClient::RenderProcessWillLaunch(
174     content::RenderProcessHost* host) {
175 #if !defined(DISABLE_NACL)
176   int id = host->GetID();
177   net::URLRequestContextGetter* context =
178       host->GetStoragePartition()->GetURLRequestContext();
179
180   host->AddFilter(new nacl::NaClHostMessageFilter(
181       id,
182       // TODO(Halton): IsOffTheRecord?
183       false,
184       host->GetBrowserContext()->GetPath(),
185       context));
186 #endif
187   xwalk_runner_->OnRenderProcessWillLaunch(host);
188   host->AddFilter(new XWalkRenderMessageFilter);
189 }
190
191 content::MediaObserver* XWalkContentBrowserClient::GetMediaObserver() {
192   return XWalkMediaCaptureDevicesDispatcher::GetInstance();
193 }
194
195 bool XWalkContentBrowserClient::AllowGetCookie(
196     const GURL& url,
197     const GURL& first_party,
198     const net::CookieList& cookie_list,
199     content::ResourceContext* context,
200     int render_process_id,
201     int render_frame_id) {
202 #if defined(OS_ANDROID)
203   return XWalkCookieAccessPolicy::GetInstance()->AllowGetCookie(
204       url,
205       first_party,
206       cookie_list,
207       context,
208       render_process_id,
209       render_frame_id);
210 #else
211   return true;
212 #endif
213 }
214
215 bool XWalkContentBrowserClient::AllowSetCookie(
216     const GURL& url,
217     const GURL& first_party,
218     const std::string& cookie_line,
219     content::ResourceContext* context,
220     int render_process_id,
221     int render_frame_id,
222     net::CookieOptions* options) {
223 #if defined(OS_ANDROID)
224   return XWalkCookieAccessPolicy::GetInstance()->AllowSetCookie(
225       url,
226       first_party,
227       cookie_line,
228       context,
229       render_process_id,
230       render_frame_id,
231       options);
232 #else
233   return true;
234 #endif
235 }
236
237 void XWalkContentBrowserClient::AllowCertificateError(
238     int render_process_id,
239     int render_frame_id,
240     int cert_error,
241     const net::SSLInfo& ssl_info,
242     const GURL& request_url,
243     content::ResourceType resource_type,
244     bool overridable,
245     bool strict_enforcement,
246     bool expired_previous_decision,
247     const base::Callback<void(bool)>& callback, // NOLINT
248     content::CertificateRequestResultType* result) {
249   // Currently only Android handles it.
250   // TODO(yongsheng): applies it for other platforms?
251 #if defined(OS_ANDROID)
252   XWalkContentsClientBridgeBase* client =
253       XWalkContentsClientBridgeBase::FromRenderFrameID(render_process_id,
254           render_frame_id);
255   bool cancel_request = true;
256   if (client)
257     client->AllowCertificateError(cert_error,
258                                   ssl_info.cert.get(),
259                                   request_url,
260                                   callback,
261                                   &cancel_request);
262   if (cancel_request)
263     *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
264 #endif
265 }
266
267 void XWalkContentBrowserClient::RequestDesktopNotificationPermission(
268     const GURL& source_origin,
269     content::RenderFrameHost* render_frame_host,
270     const base::Callback<void(blink::WebNotificationPermission)>& callback) {
271 }
272
273 blink::WebNotificationPermission
274 XWalkContentBrowserClient::CheckDesktopNotificationPermission(
275     const GURL& source_url,
276     content::ResourceContext* context,
277     int render_process_id) {
278 #if defined(OS_ANDROID)
279   return blink::WebNotificationPermissionAllowed;
280 #else
281   return blink::WebNotificationPermissionDenied;
282 #endif
283 }
284
285 void XWalkContentBrowserClient::ShowDesktopNotification(
286     const content::ShowDesktopNotificationHostMsgParams& params,
287     content::RenderFrameHost* render_frame_host,
288     scoped_ptr<content::DesktopNotificationDelegate> delegate,
289     base::Closure* cancel_callback) {
290 #if defined(OS_ANDROID)
291   XWalkContentsClientBridgeBase* bridge =
292       XWalkContentsClientBridgeBase::FromRenderFrameHost(render_frame_host);
293   bridge->ShowNotification(params, render_frame_host,
294       delegate.Pass(), cancel_callback);
295 #endif
296 }
297
298 void XWalkContentBrowserClient::RequestGeolocationPermission(
299     content::WebContents* web_contents,
300     int bridge_id,
301     const GURL& requesting_frame,
302     bool user_gesture,
303     base::Callback<void(bool)> result_callback,
304     base::Closure* cancel_callback) {
305 #if defined(OS_ANDROID) || defined(OS_TIZEN)
306   if (!geolocation_permission_context_) {
307     geolocation_permission_context_ =
308       new RuntimeGeolocationPermissionContext();
309   }
310   geolocation_permission_context_->RequestGeolocationPermission(
311     web_contents,
312     requesting_frame,
313     result_callback,
314     cancel_callback);
315 #else
316   result_callback.Run(false);
317 #endif
318 }
319
320 void XWalkContentBrowserClient::DidCreatePpapiPlugin(
321     content::BrowserPpapiHost* browser_host) {
322 #if defined(ENABLE_PLUGINS)
323   browser_host->GetPpapiHost()->AddHostFactoryFilter(
324       scoped_ptr<ppapi::host::HostFactory>(
325           new XWalkBrowserPepperHostFactory(browser_host)));
326 #endif
327 }
328
329 content::BrowserPpapiHost*
330     XWalkContentBrowserClient::GetExternalBrowserPpapiHost(
331         int plugin_process_id) {
332 #if !defined(DISABLE_NACL)
333   content::BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_LOADER);
334   while (!iter.Done()) {
335     nacl::NaClProcessHost* host = static_cast<nacl::NaClProcessHost*>(
336         iter.GetDelegate());
337     if (host->process() &&
338         host->process()->GetData().id == plugin_process_id) {
339       // Found the plugin.
340       return host->browser_ppapi_host();
341     }
342     ++iter;
343   }
344 #endif
345   return NULL;
346 }
347
348 #if defined(OS_ANDROID)
349 void XWalkContentBrowserClient::ResourceDispatcherHostCreated() {
350   RuntimeResourceDispatcherHostDelegateAndroid::
351   ResourceDispatcherHostCreated();
352 }
353 #endif
354
355 content::SpeechRecognitionManagerDelegate*
356     XWalkContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
357   return new xwalk::XWalkSpeechRecognitionManagerDelegate();
358 }
359
360 #if !defined(OS_ANDROID)
361 bool XWalkContentBrowserClient::CanCreateWindow(const GURL& opener_url,
362                              const GURL& opener_top_level_frame_url,
363                              const GURL& source_origin,
364                              WindowContainerType container_type,
365                              const GURL& target_url,
366                              const content::Referrer& referrer,
367                              WindowOpenDisposition disposition,
368                              const blink::WebWindowFeatures& features,
369                              bool user_gesture,
370                              bool opener_suppressed,
371                              content::ResourceContext* context,
372                              int render_process_id,
373                              int opener_id,
374                              bool* no_javascript_access) {
375   *no_javascript_access = false;
376   application::Application* app = xwalk_runner_->app_system()->
377       application_service()->GetApplicationByRenderHostID(render_process_id);
378   if (!app)
379     // If it's not a request from an application, always enable this action.
380     return true;
381
382   if (app->CanRequestURL(target_url)) {
383     LOG(INFO) << "[ALLOW] CreateWindow: " << target_url.spec();
384     return true;
385   }
386
387   LOG(INFO) << "[BlOCK] CreateWindow: " << target_url.spec();
388 #if defined(OS_TIZEN)
389   platform_util::OpenExternal(target_url);
390 #endif
391   return false;
392 }
393 #endif
394
395
396 void XWalkContentBrowserClient::GetStoragePartitionConfigForSite(
397     content::BrowserContext* browser_context,
398     const GURL& site,
399     bool can_be_default,
400     std::string* partition_domain,
401     std::string* partition_name,
402     bool* in_memory) {
403   *in_memory = false;
404   partition_domain->clear();
405   partition_name->clear();
406
407 #if !defined(OS_ANDROID)
408   if (site.SchemeIs(application::kApplicationScheme))
409     *partition_domain = site.host();
410 #endif
411 }
412
413 }  // namespace xwalk