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.
5 #include "xwalk/runtime/browser/xwalk_content_browser_client.h"
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/render_widget_host.h"
20 #include "content/public/browser/render_widget_host_iterator.h"
21 #include "content/public/browser/resource_context.h"
22 #include "content/public/browser/resource_dispatcher_host.h"
23 #include "content/public/browser/storage_partition.h"
24 #include "content/public/browser/web_contents.h"
25 #include "content/public/common/main_function_params.h"
26 #include "content/public/common/show_desktop_notification_params.h"
27 #include "net/ssl/ssl_info.h"
28 #include "net/url_request/url_request_context_getter.h"
29 #include "ppapi/host/ppapi_host.h"
30 #include "xwalk/extensions/common/xwalk_extension_switches.h"
31 #include "xwalk/application/common/constants.h"
32 #include "xwalk/runtime/browser/devtools/xwalk_devtools_delegate.h"
33 #include "xwalk/runtime/browser/geolocation/xwalk_access_token_store.h"
34 #include "xwalk/runtime/browser/media/media_capture_devices_dispatcher.h"
35 #include "xwalk/runtime/browser/renderer_host/pepper/xwalk_browser_pepper_host_factory.h"
36 #include "xwalk/runtime/browser/runtime_quota_permission_context.h"
37 #include "xwalk/runtime/browser/speech/speech_recognition_manager_delegate.h"
38 #include "xwalk/runtime/browser/xwalk_browser_context.h"
39 #include "xwalk/runtime/browser/xwalk_browser_main_parts.h"
40 #include "xwalk/runtime/browser/xwalk_render_message_filter.h"
41 #include "xwalk/runtime/browser/xwalk_runner.h"
42 #include "xwalk/runtime/common/xwalk_paths.h"
44 #if !defined(DISABLE_NACL)
45 #include "components/nacl/browser/nacl_browser.h"
46 #include "components/nacl/browser/nacl_host_message_filter.h"
47 #include "components/nacl/browser/nacl_process_host.h"
48 #include "components/nacl/common/nacl_process_type.h"
51 #if defined(OS_ANDROID)
52 #include "base/android/path_utils.h"
53 #include "base/base_paths_android.h"
54 #include "xwalk/runtime/browser/android/xwalk_cookie_access_policy.h"
55 #include "xwalk/runtime/browser/android/xwalk_contents_client_bridge.h"
56 #include "xwalk/runtime/browser/android/xwalk_web_contents_view_delegate.h"
57 #include "xwalk/runtime/browser/xwalk_browser_main_parts_android.h"
58 #include "xwalk/runtime/common/android/xwalk_globals_android.h"
60 #include "xwalk/application/browser/application_system.h"
61 #include "xwalk/application/browser/application_service.h"
62 #include "xwalk/application/browser/application.h"
65 #if defined(OS_MACOSX)
66 #include "xwalk/runtime/browser/xwalk_browser_main_parts_mac.h"
70 #include "xwalk/application/common/application_manifest_constants.h"
71 #include "xwalk/runtime/browser/geolocation/tizen/location_provider_tizen.h"
72 #include "xwalk/runtime/browser/runtime_platform_util.h"
73 #include "xwalk/runtime/browser/tizen/xwalk_web_contents_view_delegate.h"
74 #include "xwalk/runtime/browser/xwalk_browser_main_parts_tizen.h"
81 // The application-wide singleton of ContentBrowserClient impl.
82 XWalkContentBrowserClient* g_browser_client = nullptr;
87 XWalkContentBrowserClient* XWalkContentBrowserClient::Get() {
88 return g_browser_client;
92 XWalkContentBrowserClient::XWalkContentBrowserClient(XWalkRunner* xwalk_runner)
93 : xwalk_runner_(xwalk_runner),
94 url_request_context_getter_(nullptr),
96 browser_context_(xwalk_runner->browser_context()) {
97 DCHECK(!g_browser_client);
98 g_browser_client = this;
101 XWalkContentBrowserClient::~XWalkContentBrowserClient() {
102 DCHECK(g_browser_client);
103 g_browser_client = nullptr;
106 content::BrowserMainParts* XWalkContentBrowserClient::CreateBrowserMainParts(
107 const content::MainFunctionParams& parameters) {
108 #if defined(OS_MACOSX)
109 main_parts_ = new XWalkBrowserMainPartsMac(parameters);
110 #elif defined(OS_ANDROID)
111 main_parts_ = new XWalkBrowserMainPartsAndroid(parameters);
112 #elif defined(OS_TIZEN)
113 main_parts_ = new XWalkBrowserMainPartsTizen(parameters);
115 main_parts_ = new XWalkBrowserMainParts(parameters);
121 net::URLRequestContextGetter* XWalkContentBrowserClient::CreateRequestContext(
122 content::BrowserContext* browser_context,
123 content::ProtocolHandlerMap* protocol_handlers,
124 content::URLRequestInterceptorScopedVector request_interceptors) {
125 return static_cast<XWalkBrowserContext*>(browser_context)->
126 CreateRequestContext(protocol_handlers, request_interceptors.Pass());
129 net::URLRequestContextGetter*
130 XWalkContentBrowserClient::CreateRequestContextForStoragePartition(
131 content::BrowserContext* browser_context,
132 const base::FilePath& partition_path,
134 content::ProtocolHandlerMap* protocol_handlers,
135 content::URLRequestInterceptorScopedVector request_interceptors) {
136 return static_cast<XWalkBrowserContext*>(browser_context)->
137 CreateRequestContextForStoragePartition(
138 partition_path, in_memory, protocol_handlers,
139 request_interceptors.Pass());
142 // This allow us to append extra command line switches to the child
143 // process we launch.
144 void XWalkContentBrowserClient::AppendExtraCommandLineSwitches(
145 CommandLine* command_line, int child_process_id) {
146 CommandLine* browser_process_cmd_line = CommandLine::ForCurrentProcess();
147 const int extra_switches_count = 1;
148 const char* extra_switches[extra_switches_count] = {
149 switches::kXWalkDisableExtensionProcess
152 for (int i = 0; i < extra_switches_count; i++) {
153 if (browser_process_cmd_line->HasSwitch(extra_switches[i]))
154 command_line->AppendSwitch(extra_switches[i]);
158 content::QuotaPermissionContext*
159 XWalkContentBrowserClient::CreateQuotaPermissionContext() {
160 return new RuntimeQuotaPermissionContext();
163 content::AccessTokenStore* XWalkContentBrowserClient::CreateAccessTokenStore() {
164 return new XWalkAccessTokenStore(url_request_context_getter_);
167 content::WebContentsViewDelegate*
168 XWalkContentBrowserClient::GetWebContentsViewDelegate(
169 content::WebContents* web_contents) {
170 #if defined(OS_ANDROID)
171 return new XWalkWebContentsViewDelegate(web_contents);
172 #elif defined(OS_TIZEN)
173 return new XWalkWebContentsViewDelegate(
174 web_contents, xwalk_runner_->app_system()->application_service());
180 void XWalkContentBrowserClient::RenderProcessWillLaunch(
181 content::RenderProcessHost* host) {
182 #if !defined(DISABLE_NACL)
183 int id = host->GetID();
184 net::URLRequestContextGetter* context =
185 host->GetStoragePartition()->GetURLRequestContext();
187 host->AddFilter(new nacl::NaClHostMessageFilter(
189 // TODO(Halton): IsOffTheRecord?
191 host->GetBrowserContext()->GetPath(),
194 xwalk_runner_->OnRenderProcessWillLaunch(host);
195 host->AddFilter(new XWalkRenderMessageFilter);
198 content::MediaObserver* XWalkContentBrowserClient::GetMediaObserver() {
199 return XWalkMediaCaptureDevicesDispatcher::GetInstance();
202 bool XWalkContentBrowserClient::AllowGetCookie(
204 const GURL& first_party,
205 const net::CookieList& cookie_list,
206 content::ResourceContext* context,
207 int render_process_id,
208 int render_frame_id) {
209 #if defined(OS_ANDROID)
210 return XWalkCookieAccessPolicy::GetInstance()->AllowGetCookie(
222 bool XWalkContentBrowserClient::AllowSetCookie(
224 const GURL& first_party,
225 const std::string& cookie_line,
226 content::ResourceContext* context,
227 int render_process_id,
229 net::CookieOptions* options) {
230 #if defined(OS_ANDROID)
231 return XWalkCookieAccessPolicy::GetInstance()->AllowSetCookie(
244 void XWalkContentBrowserClient::AllowCertificateError(
245 int render_process_id,
248 const net::SSLInfo& ssl_info,
249 const GURL& request_url,
250 content::ResourceType resource_type,
252 bool strict_enforcement,
253 bool expired_previous_decision,
254 const base::Callback<void(bool)>& callback, // NOLINT
255 content::CertificateRequestResultType* result) {
256 // Currently only Android handles it.
257 // TODO(yongsheng): applies it for other platforms?
258 #if defined(OS_ANDROID)
259 XWalkContentsClientBridgeBase* client =
260 XWalkContentsClientBridgeBase::FromRenderFrameID(render_process_id,
262 bool cancel_request = true;
264 client->AllowCertificateError(cert_error,
270 *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
274 blink::WebNotificationPermission
275 XWalkContentBrowserClient::CheckDesktopNotificationPermission(
276 const GURL& source_url,
277 content::ResourceContext* context,
278 int render_process_id) {
279 #if defined(OS_ANDROID)
280 return blink::WebNotificationPermissionAllowed;
282 return blink::WebNotificationPermissionDenied;
286 void XWalkContentBrowserClient::ShowDesktopNotification(
287 const content::ShowDesktopNotificationHostMsgParams& params,
288 content::BrowserContext* browser_context,
289 int render_process_id,
290 scoped_ptr<content::DesktopNotificationDelegate> delegate,
291 base::Closure* cancel_callback) {
292 #if defined(OS_ANDROID)
293 scoped_ptr<content::RenderWidgetHostIterator> widgets(
294 content::RenderWidgetHost::GetRenderWidgetHosts());
295 while (content::RenderWidgetHost* rwh = widgets->GetNextHost()) {
296 if (!rwh->GetProcess() || rwh->GetProcess()->GetID() != render_process_id)
298 content::RenderViewHost* rvh = content::RenderViewHost::From(rwh);
301 content::WebContents* web_contents =
302 content::WebContents::FromRenderViewHost(rvh);
305 XWalkContentsClientBridgeBase* bridge =
306 XWalkContentsClientBridgeBase::FromWebContents(web_contents);
307 bridge->ShowNotification(params, delegate.Pass(), cancel_callback);
313 void XWalkContentBrowserClient::RequestPermission(
314 content::PermissionType permission,
315 content::WebContents* web_contents,
317 const GURL& requesting_frame,
319 const base::Callback<void(bool)>& result_callback) {
320 switch (permission) {
321 case content::PERMISSION_GEOLOCATION:
322 #if defined(OS_ANDROID) || defined(OS_TIZEN)
323 if (!geolocation_permission_context_.get()) {
324 geolocation_permission_context_ =
325 new RuntimeGeolocationPermissionContext();
327 geolocation_permission_context_->RequestGeolocationPermission(
328 web_contents, requesting_frame, result_callback);
330 result_callback.Run(false);
333 case content::PERMISSION_NOTIFICATIONS:
339 void XWalkContentBrowserClient::CancelPermissionRequest(
340 content::PermissionType permission,
341 content::WebContents* web_contents,
343 const GURL& requesting_frame) {
344 switch (permission) {
345 case content::PERMISSION_GEOLOCATION:
346 #if defined(OS_ANDROID) || defined(OS_TIZEN)
347 geolocation_permission_context_->CancelGeolocationPermissionRequest(
348 web_contents, requesting_frame);
351 case content::PERMISSION_NOTIFICATIONS:
357 void XWalkContentBrowserClient::DidCreatePpapiPlugin(
358 content::BrowserPpapiHost* browser_host) {
359 #if defined(ENABLE_PLUGINS)
360 browser_host->GetPpapiHost()->AddHostFactoryFilter(
361 scoped_ptr<ppapi::host::HostFactory>(
362 new XWalkBrowserPepperHostFactory(browser_host)));
366 content::BrowserPpapiHost*
367 XWalkContentBrowserClient::GetExternalBrowserPpapiHost(
368 int plugin_process_id) {
369 #if !defined(DISABLE_NACL)
370 content::BrowserChildProcessHostIterator iter(PROCESS_TYPE_NACL_LOADER);
371 while (!iter.Done()) {
372 nacl::NaClProcessHost* host = static_cast<nacl::NaClProcessHost*>(
374 if (host->process() &&
375 host->process()->GetData().id == plugin_process_id) {
377 return host->browser_ppapi_host();
385 #if defined(OS_ANDROID) || defined(OS_TIZEN) || defined(OS_LINUX)
386 void XWalkContentBrowserClient::ResourceDispatcherHostCreated() {
387 resource_dispatcher_host_delegate_ =
388 (RuntimeResourceDispatcherHostDelegate::Create()).Pass();
389 content::ResourceDispatcherHost::Get()->SetDelegate(
390 resource_dispatcher_host_delegate_.get());
394 content::SpeechRecognitionManagerDelegate*
395 XWalkContentBrowserClient::GetSpeechRecognitionManagerDelegate() {
396 return new xwalk::XWalkSpeechRecognitionManagerDelegate();
399 #if !defined(OS_ANDROID)
400 bool XWalkContentBrowserClient::CanCreateWindow(const GURL& opener_url,
401 const GURL& opener_top_level_frame_url,
402 const GURL& source_origin,
403 WindowContainerType container_type,
404 const GURL& target_url,
405 const content::Referrer& referrer,
406 WindowOpenDisposition disposition,
407 const blink::WebWindowFeatures& features,
409 bool opener_suppressed,
410 content::ResourceContext* context,
411 int render_process_id,
413 bool* no_javascript_access) {
414 *no_javascript_access = false;
415 application::Application* app = xwalk_runner_->app_system()->
416 application_service()->GetApplicationByRenderHostID(render_process_id);
418 // If it's not a request from an application, always enable this action.
421 if (app->CanRequestURL(target_url)) {
422 LOG(INFO) << "[ALLOW] CreateWindow: " << target_url.spec();
426 LOG(INFO) << "[BlOCK] CreateWindow: " << target_url.spec();
427 #if defined(OS_TIZEN)
428 platform_util::OpenExternal(target_url);
434 content::LocationProvider*
435 XWalkContentBrowserClient::OverrideSystemLocationProvider() {
436 #if defined(OS_TIZEN)
437 return new LocationProviderTizen();
443 void XWalkContentBrowserClient::GetStoragePartitionConfigForSite(
444 content::BrowserContext* browser_context,
447 std::string* partition_domain,
448 std::string* partition_name,
451 partition_domain->clear();
452 partition_name->clear();
454 #if !defined(OS_ANDROID)
455 if (site.SchemeIs(application::kApplicationScheme))
456 *partition_domain = site.host();
460 content::DevToolsManagerDelegate*
461 XWalkContentBrowserClient::GetDevToolsManagerDelegate() {
462 return new XWalkDevToolsDelegate(browser_context_);