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