1 // Copyright (c) 2012 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.
5 #include "android_webview/browser/aw_content_browser_client.h"
7 #include "android_webview/browser/aw_browser_context.h"
8 #include "android_webview/browser/aw_browser_main_parts.h"
9 #include "android_webview/browser/aw_browser_permission_request_delegate.h"
10 #include "android_webview/browser/aw_contents_client_bridge_base.h"
11 #include "android_webview/browser/aw_contents_io_thread_client.h"
12 #include "android_webview/browser/aw_cookie_access_policy.h"
13 #include "android_webview/browser/aw_quota_permission_context.h"
14 #include "android_webview/browser/aw_web_preferences_populater.h"
15 #include "android_webview/browser/jni_dependency_factory.h"
16 #include "android_webview/browser/net_disk_cache_remover.h"
17 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
18 #include "android_webview/common/render_view_messages.h"
19 #include "android_webview/common/url_constants.h"
20 #include "base/base_paths_android.h"
21 #include "base/path_service.h"
22 #include "components/cdm/browser/cdm_message_filter_android.h"
23 #include "content/public/browser/access_token_store.h"
24 #include "content/public/browser/browser_message_filter.h"
25 #include "content/public/browser/browser_thread.h"
26 #include "content/public/browser/child_process_security_policy.h"
27 #include "content/public/browser/render_process_host.h"
28 #include "content/public/browser/render_view_host.h"
29 #include "content/public/browser/web_contents.h"
30 #include "content/public/common/url_constants.h"
31 #include "content/public/common/web_preferences.h"
32 #include "grit/ui_resources.h"
33 #include "net/android/network_library.h"
34 #include "net/ssl/ssl_cert_request_info.h"
35 #include "net/ssl/ssl_info.h"
36 #include "ui/base/l10n/l10n_util_android.h"
37 #include "ui/base/resource/resource_bundle.h"
39 using content::BrowserThread
;
40 using content::ResourceType
;
42 namespace android_webview
{
45 // TODO(sgurun) move this to its own file.
46 // This class filters out incoming aw_contents related IPC messages for the
47 // renderer process on the IPC thread.
48 class AwContentsMessageFilter
: public content::BrowserMessageFilter
{
50 explicit AwContentsMessageFilter(int process_id
);
52 // BrowserMessageFilter methods.
53 virtual void OverrideThreadForMessage(
54 const IPC::Message
& message
,
55 BrowserThread::ID
* thread
) OVERRIDE
;
56 virtual bool OnMessageReceived(
57 const IPC::Message
& message
) OVERRIDE
;
59 void OnShouldOverrideUrlLoading(int routing_id
,
60 const base::string16
& url
,
61 bool* ignore_navigation
);
62 void OnSubFrameCreated(int parent_render_frame_id
, int child_render_frame_id
);
65 virtual ~AwContentsMessageFilter();
69 DISALLOW_COPY_AND_ASSIGN(AwContentsMessageFilter
);
72 AwContentsMessageFilter::AwContentsMessageFilter(int process_id
)
73 : BrowserMessageFilter(AndroidWebViewMsgStart
),
74 process_id_(process_id
) {
77 AwContentsMessageFilter::~AwContentsMessageFilter() {
80 void AwContentsMessageFilter::OverrideThreadForMessage(
81 const IPC::Message
& message
, BrowserThread::ID
* thread
) {
82 if (message
.type() == AwViewHostMsg_ShouldOverrideUrlLoading::ID
) {
83 *thread
= BrowserThread::UI
;
87 bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message
& message
) {
89 IPC_BEGIN_MESSAGE_MAP(AwContentsMessageFilter
, message
)
90 IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading
,
91 OnShouldOverrideUrlLoading
)
92 IPC_MESSAGE_HANDLER(AwViewHostMsg_SubFrameCreated
, OnSubFrameCreated
)
93 IPC_MESSAGE_UNHANDLED(handled
= false)
98 void AwContentsMessageFilter::OnShouldOverrideUrlLoading(
100 const base::string16
& url
,
101 bool* ignore_navigation
) {
102 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI
));
103 *ignore_navigation
= false;
104 AwContentsClientBridgeBase
* client
=
105 AwContentsClientBridgeBase::FromID(process_id_
, render_frame_id
);
107 *ignore_navigation
= client
->ShouldOverrideUrlLoading(url
);
109 LOG(WARNING
) << "Failed to find the associated render view host for url: "
114 void AwContentsMessageFilter::OnSubFrameCreated(int parent_render_frame_id
,
115 int child_render_frame_id
) {
116 AwContentsIoThreadClient::SubFrameCreated(
117 process_id_
, parent_render_frame_id
, child_render_frame_id
);
120 class AwAccessTokenStore
: public content::AccessTokenStore
{
122 AwAccessTokenStore() { }
124 // content::AccessTokenStore implementation
125 virtual void LoadAccessTokens(
126 const LoadAccessTokensCallbackType
& request
) OVERRIDE
{
127 AccessTokenStore::AccessTokenSet access_token_set
;
128 // AccessTokenSet and net::URLRequestContextGetter not used on Android,
129 // but Run needs to be called to finish the geolocation setup.
130 request
.Run(access_token_set
, NULL
);
132 virtual void SaveAccessToken(const GURL
& server_url
,
133 const base::string16
& access_token
) OVERRIDE
{ }
136 virtual ~AwAccessTokenStore() { }
138 DISALLOW_COPY_AND_ASSIGN(AwAccessTokenStore
);
141 void CancelProtectedMediaIdentifierPermissionRequests(
142 int render_process_id
,
144 const GURL
& origin
) {
145 AwBrowserPermissionRequestDelegate
* delegate
=
146 AwBrowserPermissionRequestDelegate::FromID(render_process_id
,
149 delegate
->CancelProtectedMediaIdentifierPermissionRequests(origin
);
152 void CancelGeolocationPermissionRequests(
153 int render_process_id
,
155 const GURL
& origin
) {
156 AwBrowserPermissionRequestDelegate
* delegate
=
157 AwBrowserPermissionRequestDelegate::FromID(render_process_id
,
160 delegate
->CancelGeolocationPermissionRequests(origin
);
165 std::string
AwContentBrowserClient::GetAcceptLangsImpl() {
166 // Start with the currnet locale.
167 std::string langs
= l10n_util::GetDefaultLocale();
169 // If we're not en-US, add in en-US which will be
170 // used with a lower q-value.
171 if (StringToLowerASCII(langs
) != "en-us") {
177 AwBrowserContext
* AwContentBrowserClient::GetAwBrowserContext() {
178 return AwBrowserContext::GetDefault();
181 AwContentBrowserClient::AwContentBrowserClient(
182 JniDependencyFactory
* native_factory
)
183 : native_factory_(native_factory
) {
184 base::FilePath user_data_dir
;
185 if (!PathService::Get(base::DIR_ANDROID_APP_DATA
, &user_data_dir
)) {
186 NOTREACHED() << "Failed to get app data directory for Android WebView";
188 browser_context_
.reset(
189 new AwBrowserContext(user_data_dir
, native_factory_
));
192 AwContentBrowserClient::~AwContentBrowserClient() {
195 void AwContentBrowserClient::AddCertificate(net::CertificateMimeType cert_type
,
196 const void* cert_data
,
198 int render_process_id
,
199 int render_frame_id
) {
201 net::android::StoreCertificate(cert_type
, cert_data
, cert_size
);
204 content::BrowserMainParts
* AwContentBrowserClient::CreateBrowserMainParts(
205 const content::MainFunctionParams
& parameters
) {
206 return new AwBrowserMainParts(browser_context_
.get());
209 content::WebContentsViewDelegate
*
210 AwContentBrowserClient::GetWebContentsViewDelegate(
211 content::WebContents
* web_contents
) {
212 return native_factory_
->CreateViewDelegate(web_contents
);
215 void AwContentBrowserClient::RenderProcessWillLaunch(
216 content::RenderProcessHost
* host
) {
217 // If WebView becomes multi-process capable, this may be insecure.
218 // More benefit can be derived from the ChildProcessSecurotyPolicy by
219 // deferring the GrantScheme calls until we know that a given child process
220 // really does need that priviledge. Check here to ensure we rethink this
221 // when the time comes. See crbug.com/156062.
222 CHECK(content::RenderProcessHost::run_renderer_in_process());
224 // Grant content: and file: scheme to the whole process, since we impose
225 // per-view access checks.
226 content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
227 host
->GetID(), android_webview::kContentScheme
);
228 content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
229 host
->GetID(), url::kFileScheme
);
231 host
->AddFilter(new AwContentsMessageFilter(host
->GetID()));
232 host
->AddFilter(new cdm::CdmMessageFilterAndroid());
235 net::URLRequestContextGetter
* AwContentBrowserClient::CreateRequestContext(
236 content::BrowserContext
* browser_context
,
237 content::ProtocolHandlerMap
* protocol_handlers
,
238 content::URLRequestInterceptorScopedVector request_interceptors
) {
239 DCHECK(browser_context_
.get() == browser_context
);
240 return browser_context_
->CreateRequestContext(protocol_handlers
,
241 request_interceptors
.Pass());
244 net::URLRequestContextGetter
*
245 AwContentBrowserClient::CreateRequestContextForStoragePartition(
246 content::BrowserContext
* browser_context
,
247 const base::FilePath
& partition_path
,
249 content::ProtocolHandlerMap
* protocol_handlers
,
250 content::URLRequestInterceptorScopedVector request_interceptors
) {
251 DCHECK(browser_context_
.get() == browser_context
);
252 // TODO(mkosiba,kinuko): request_interceptors should be hooked up in the
253 // downstream. (crbug.com/350286)
254 return browser_context_
->CreateRequestContextForStoragePartition(
255 partition_path
, in_memory
, protocol_handlers
,
256 request_interceptors
.Pass());
259 std::string
AwContentBrowserClient::GetCanonicalEncodingNameByAliasName(
260 const std::string
& alias_name
) {
264 void AwContentBrowserClient::AppendExtraCommandLineSwitches(
265 base::CommandLine
* command_line
,
266 int child_process_id
) {
267 NOTREACHED() << "Android WebView does not support multi-process yet";
270 std::string
AwContentBrowserClient::GetApplicationLocale() {
271 return l10n_util::GetDefaultLocale();
274 std::string
AwContentBrowserClient::GetAcceptLangs(
275 content::BrowserContext
* context
) {
276 return GetAcceptLangsImpl();
279 const gfx::ImageSkia
* AwContentBrowserClient::GetDefaultFavicon() {
280 ResourceBundle
& rb
= ResourceBundle::GetSharedInstance();
281 // TODO(boliu): Bundle our own default favicon?
282 return rb
.GetImageSkiaNamed(IDR_DEFAULT_FAVICON
);
285 bool AwContentBrowserClient::AllowAppCache(const GURL
& manifest_url
,
286 const GURL
& first_party
,
287 content::ResourceContext
* context
) {
288 // WebView doesn't have a per-site policy for locally stored data,
289 // instead AppCache can be disabled for individual WebViews.
294 bool AwContentBrowserClient::AllowGetCookie(const GURL
& url
,
295 const GURL
& first_party
,
296 const net::CookieList
& cookie_list
,
297 content::ResourceContext
* context
,
298 int render_process_id
,
299 int render_frame_id
) {
300 return AwCookieAccessPolicy::GetInstance()->AllowGetCookie(url
,
308 bool AwContentBrowserClient::AllowSetCookie(const GURL
& url
,
309 const GURL
& first_party
,
310 const std::string
& cookie_line
,
311 content::ResourceContext
* context
,
312 int render_process_id
,
314 net::CookieOptions
* options
) {
315 return AwCookieAccessPolicy::GetInstance()->AllowSetCookie(url
,
324 bool AwContentBrowserClient::AllowWorkerDatabase(
326 const base::string16
& name
,
327 const base::string16
& display_name
,
328 unsigned long estimated_size
,
329 content::ResourceContext
* context
,
330 const std::vector
<std::pair
<int, int> >& render_frames
) {
331 // Android WebView does not yet support web workers.
335 void AwContentBrowserClient::AllowWorkerFileSystem(
337 content::ResourceContext
* context
,
338 const std::vector
<std::pair
<int, int> >& render_frames
,
339 base::Callback
<void(bool)> callback
) {
340 // Android WebView does not yet support web workers.
344 bool AwContentBrowserClient::AllowWorkerIndexedDB(
346 const base::string16
& name
,
347 content::ResourceContext
* context
,
348 const std::vector
<std::pair
<int, int> >& render_frames
) {
349 // Android WebView does not yet support web workers.
353 content::QuotaPermissionContext
*
354 AwContentBrowserClient::CreateQuotaPermissionContext() {
355 return new AwQuotaPermissionContext
;
358 void AwContentBrowserClient::AllowCertificateError(
359 int render_process_id
,
362 const net::SSLInfo
& ssl_info
,
363 const GURL
& request_url
,
364 ResourceType::Type resource_type
,
366 bool strict_enforcement
,
367 const base::Callback
<void(bool)>& callback
,
368 content::CertificateRequestResultType
* result
) {
369 AwContentsClientBridgeBase
* client
=
370 AwContentsClientBridgeBase::FromID(render_process_id
, render_frame_id
);
371 bool cancel_request
= true;
373 client
->AllowCertificateError(cert_error
,
379 *result
= content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY
;
382 void AwContentBrowserClient::SelectClientCertificate(
383 int render_process_id
,
385 const net::HttpNetworkSession
* network_session
,
386 net::SSLCertRequestInfo
* cert_request_info
,
387 const base::Callback
<void(net::X509Certificate
*)>& callback
) {
388 AwContentsClientBridgeBase
* client
=
389 AwContentsClientBridgeBase::FromID(render_process_id
, render_frame_id
);
391 client
->SelectClientCertificate(cert_request_info
, callback
);
397 blink::WebNotificationPresenter::Permission
398 AwContentBrowserClient::CheckDesktopNotificationPermission(
399 const GURL
& source_url
,
400 content::ResourceContext
* context
,
401 int render_process_id
) {
402 // Android WebView does not support notifications, so return Denied here.
403 return blink::WebNotificationPresenter::PermissionDenied
;
406 void AwContentBrowserClient::ShowDesktopNotification(
407 const content::ShowDesktopNotificationHostMsgParams
& params
,
408 content::RenderFrameHost
* render_frame_host
,
409 content::DesktopNotificationDelegate
* delegate
,
410 base::Closure
* cancel_callback
) {
411 NOTREACHED() << "Android WebView does not support desktop notifications.";
414 void AwContentBrowserClient::RequestGeolocationPermission(
415 content::WebContents
* web_contents
,
417 const GURL
& requesting_frame
,
419 base::Callback
<void(bool)> result_callback
,
420 base::Closure
* cancel_callback
) {
421 int render_process_id
= web_contents
->GetRenderProcessHost()->GetID();
422 int render_view_id
= web_contents
->GetRenderViewHost()->GetRoutingID();
423 AwBrowserPermissionRequestDelegate
* delegate
=
424 AwBrowserPermissionRequestDelegate::FromID(render_process_id
,
426 if (delegate
== NULL
) {
427 DVLOG(0) << "Dropping GeolocationPermission request";
428 result_callback
.Run(false);
432 GURL origin
= requesting_frame
.GetOrigin();
433 if (cancel_callback
) {
434 *cancel_callback
= base::Bind(
435 CancelGeolocationPermissionRequests
, render_process_id
, render_view_id
,
438 delegate
->RequestGeolocationPermission(origin
, result_callback
);
441 void AwContentBrowserClient::RequestMidiSysExPermission(
442 content::WebContents
* web_contents
,
444 const GURL
& requesting_frame
,
446 base::Callback
<void(bool)> result_callback
,
447 base::Closure
* cancel_callback
) {
448 // TODO(toyoshim): Android WebView is not supported yet.
449 // See http://crbug.com/339767.
450 result_callback
.Run(false);
453 void AwContentBrowserClient::RequestProtectedMediaIdentifierPermission(
454 content::WebContents
* web_contents
,
456 base::Callback
<void(bool)> result_callback
,
457 base::Closure
* cancel_callback
) {
458 int render_process_id
= web_contents
->GetRenderProcessHost()->GetID();
459 int render_view_id
= web_contents
->GetRenderViewHost()->GetRoutingID();
460 AwBrowserPermissionRequestDelegate
* delegate
=
461 AwBrowserPermissionRequestDelegate::FromID(render_process_id
,
463 if (delegate
== NULL
) {
464 DVLOG(0) << "Dropping ProtectedMediaIdentifierPermission request";
465 result_callback
.Run(false);
469 if (cancel_callback
) {
470 *cancel_callback
= base::Bind(
471 CancelProtectedMediaIdentifierPermissionRequests
,
472 render_process_id
, render_view_id
, origin
);
474 delegate
->RequestProtectedMediaIdentifierPermission(origin
, result_callback
);
477 bool AwContentBrowserClient::CanCreateWindow(
478 const GURL
& opener_url
,
479 const GURL
& opener_top_level_frame_url
,
480 const GURL
& source_origin
,
481 WindowContainerType container_type
,
482 const GURL
& target_url
,
483 const content::Referrer
& referrer
,
484 WindowOpenDisposition disposition
,
485 const blink::WebWindowFeatures
& features
,
487 bool opener_suppressed
,
488 content::ResourceContext
* context
,
489 int render_process_id
,
491 bool* no_javascript_access
) {
492 // We unconditionally allow popup windows at this stage and will give
493 // the embedder the opporunity to handle displaying of the popup in
494 // WebContentsDelegate::AddContents (via the
495 // AwContentsClient.onCreateWindow callback).
496 // Note that if the embedder has blocked support for creating popup
497 // windows through AwSettings, then we won't get to this point as
498 // the popup creation will have been blocked at the WebKit level.
499 if (no_javascript_access
) {
500 *no_javascript_access
= false;
505 std::string
AwContentBrowserClient::GetWorkerProcessTitle(const GURL
& url
,
506 content::ResourceContext
* context
) {
507 NOTREACHED() << "Android WebView does not yet support web workers.";
508 return std::string();
512 void AwContentBrowserClient::ResourceDispatcherHostCreated() {
513 AwResourceDispatcherHostDelegate::ResourceDispatcherHostCreated();
516 net::NetLog
* AwContentBrowserClient::GetNetLog() {
517 // TODO(boliu): Implement AwNetLog.
521 content::AccessTokenStore
* AwContentBrowserClient::CreateAccessTokenStore() {
522 return new AwAccessTokenStore();
525 bool AwContentBrowserClient::IsFastShutdownPossible() {
526 NOTREACHED() << "Android WebView is single process, so IsFastShutdownPossible"
527 << " should never be called";
531 void AwContentBrowserClient::UpdateInspectorSetting(
532 content::RenderViewHost
* rvh
,
533 const std::string
& key
,
534 const std::string
& value
) {
535 // TODO(boliu): Implement persisting inspector settings.
539 void AwContentBrowserClient::ClearCache(content::RenderViewHost
* rvh
) {
540 RemoveHttpDiskCache(rvh
->GetProcess()->GetBrowserContext(),
541 rvh
->GetProcess()->GetID());
544 void AwContentBrowserClient::ClearCookies(content::RenderViewHost
* rvh
) {
545 // TODO(boliu): Implement.
549 base::FilePath
AwContentBrowserClient::GetDefaultDownloadDirectory() {
550 // Android WebView does not currently use the Chromium downloads system.
551 // Download requests are cancelled immedately when recognized; see
552 // AwResourceDispatcherHost::CreateResourceHandlerForDownload. However the
553 // download system still tries to start up and calls this before recognizing
554 // the request has been cancelled.
555 return base::FilePath();
558 std::string
AwContentBrowserClient::GetDefaultDownloadName() {
559 NOTREACHED() << "Android WebView does not use chromium downloads";
560 return std::string();
563 void AwContentBrowserClient::DidCreatePpapiPlugin(
564 content::BrowserPpapiHost
* browser_host
) {
565 NOTREACHED() << "Android WebView does not support plugins";
568 bool AwContentBrowserClient::AllowPepperSocketAPI(
569 content::BrowserContext
* browser_context
,
572 const content::SocketPermissionRequest
* params
) {
573 NOTREACHED() << "Android WebView does not support plugins";
577 void AwContentBrowserClient::OverrideWebkitPrefs(
578 content::RenderViewHost
* rvh
,
580 content::WebPreferences
* web_prefs
) {
581 if (!preferences_populater_
.get()) {
582 preferences_populater_
= make_scoped_ptr(native_factory_
->
583 CreateWebPreferencesPopulater());
585 preferences_populater_
->PopulateFor(
586 content::WebContents::FromRenderViewHost(rvh
), web_prefs
);
589 #if defined(VIDEO_HOLE)
590 content::ExternalVideoSurfaceContainer
*
591 AwContentBrowserClient::OverrideCreateExternalVideoSurfaceContainer(
592 content::WebContents
* web_contents
) {
593 return native_factory_
->CreateExternalVideoSurfaceContainer(web_contents
);
597 } // namespace android_webview