b1edcfdea5dea49320a7da258fe3d152d0f4917b
[platform/framework/web/crosswalk.git] / src / android_webview / browser / aw_content_browser_client.cc
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.
4
5 #include "android_webview/browser/aw_content_browser_client.h"
6
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_contents_client_bridge_base.h"
10 #include "android_webview/browser/aw_contents_io_thread_client.h"
11 #include "android_webview/browser/aw_cookie_access_policy.h"
12 #include "android_webview/browser/aw_quota_permission_context.h"
13 #include "android_webview/browser/aw_web_preferences_populater.h"
14 #include "android_webview/browser/jni_dependency_factory.h"
15 #include "android_webview/browser/net_disk_cache_remover.h"
16 #include "android_webview/browser/renderer_host/aw_resource_dispatcher_host_delegate.h"
17 #include "android_webview/common/render_view_messages.h"
18 #include "android_webview/common/url_constants.h"
19 #include "base/base_paths_android.h"
20 #include "base/path_service.h"
21 #include "content/public/browser/access_token_store.h"
22 #include "content/public/browser/browser_message_filter.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/child_process_security_policy.h"
25 #include "content/public/browser/render_process_host.h"
26 #include "content/public/browser/render_view_host.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/common/url_constants.h"
29 #include "grit/ui_resources.h"
30 #include "net/android/network_library.h"
31 #include "net/ssl/ssl_cert_request_info.h"
32 #include "net/ssl/ssl_info.h"
33 #include "ui/base/l10n/l10n_util_android.h"
34 #include "ui/base/resource/resource_bundle.h"
35 #include "webkit/common/webpreferences.h"
36
37 using content::BrowserThread;
38
39 namespace android_webview {
40 namespace {
41
42 // TODO(sgurun) move this to its own file.
43 // This class filters out incoming aw_contents related IPC messages for the
44 // renderer process on the IPC thread.
45 class AwContentsMessageFilter : public content::BrowserMessageFilter {
46 public:
47   explicit AwContentsMessageFilter(int process_id);
48
49   // BrowserMessageFilter methods.
50   virtual void OverrideThreadForMessage(
51       const IPC::Message& message,
52       BrowserThread::ID* thread) OVERRIDE;
53   virtual bool OnMessageReceived(
54       const IPC::Message& message,
55       bool* message_was_ok) OVERRIDE;
56
57   void OnShouldOverrideUrlLoading(int routing_id,
58                                   const base::string16& url,
59                                   bool* ignore_navigation);
60   void OnSubFrameCreated(int parent_render_frame_id, int child_render_frame_id);
61
62 private:
63   virtual ~AwContentsMessageFilter();
64
65   int process_id_;
66
67   DISALLOW_COPY_AND_ASSIGN(AwContentsMessageFilter);
68 };
69
70 AwContentsMessageFilter::AwContentsMessageFilter(int process_id)
71     : BrowserMessageFilter(AndroidWebViewMsgStart),
72       process_id_(process_id) {
73 }
74
75 AwContentsMessageFilter::~AwContentsMessageFilter() {
76 }
77
78 void AwContentsMessageFilter::OverrideThreadForMessage(
79     const IPC::Message& message, BrowserThread::ID* thread) {
80   if (message.type() == AwViewHostMsg_ShouldOverrideUrlLoading::ID) {
81     *thread = BrowserThread::UI;
82   }
83 }
84
85 bool AwContentsMessageFilter::OnMessageReceived(const IPC::Message& message,
86                                                 bool* message_was_ok) {
87   bool handled = true;
88   IPC_BEGIN_MESSAGE_MAP_EX(AwContentsMessageFilter, message, *message_was_ok)
89       IPC_MESSAGE_HANDLER(AwViewHostMsg_ShouldOverrideUrlLoading,
90                           OnShouldOverrideUrlLoading)
91       IPC_MESSAGE_HANDLER(AwViewHostMsg_SubFrameCreated, OnSubFrameCreated)
92       IPC_MESSAGE_UNHANDLED(handled = false)
93   IPC_END_MESSAGE_MAP()
94   return handled;
95 }
96
97 void AwContentsMessageFilter::OnShouldOverrideUrlLoading(
98     int render_frame_id,
99     const base::string16& url,
100     bool* ignore_navigation) {
101   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
102   *ignore_navigation = false;
103   AwContentsClientBridgeBase* client =
104       AwContentsClientBridgeBase::FromID(process_id_, render_frame_id);
105   if (client) {
106     *ignore_navigation = client->ShouldOverrideUrlLoading(url);
107   } else {
108     LOG(WARNING) << "Failed to find the associated render view host for url: "
109                  << url;
110   }
111 }
112
113 void AwContentsMessageFilter::OnSubFrameCreated(int parent_render_frame_id,
114                                                 int child_render_frame_id) {
115   AwContentsIoThreadClient::SubFrameCreated(
116       process_id_, parent_render_frame_id, child_render_frame_id);
117 }
118
119 class AwAccessTokenStore : public content::AccessTokenStore {
120  public:
121   AwAccessTokenStore() { }
122
123   // content::AccessTokenStore implementation
124   virtual void LoadAccessTokens(
125       const LoadAccessTokensCallbackType& request) OVERRIDE {
126     AccessTokenStore::AccessTokenSet access_token_set;
127     // AccessTokenSet and net::URLRequestContextGetter not used on Android,
128     // but Run needs to be called to finish the geolocation setup.
129     request.Run(access_token_set, NULL);
130   }
131   virtual void SaveAccessToken(const GURL& server_url,
132                                const base::string16& access_token) OVERRIDE { }
133
134  private:
135   virtual ~AwAccessTokenStore() { }
136
137   DISALLOW_COPY_AND_ASSIGN(AwAccessTokenStore);
138 };
139
140 }
141
142 std::string AwContentBrowserClient::GetAcceptLangsImpl() {
143   // Start with the currnet locale.
144   std::string langs = l10n_util::GetDefaultLocale();
145
146   // If we're not en-US, add in en-US which will be
147   // used with a lower q-value.
148   if (StringToLowerASCII(langs) != "en-us") {
149     langs += ",en-US";
150   }
151   return langs;
152 }
153
154 AwBrowserContext* AwContentBrowserClient::GetAwBrowserContext() {
155   return AwBrowserContext::GetDefault();
156 }
157
158 AwContentBrowserClient::AwContentBrowserClient(
159     JniDependencyFactory* native_factory)
160     : native_factory_(native_factory) {
161   base::FilePath user_data_dir;
162   if (!PathService::Get(base::DIR_ANDROID_APP_DATA, &user_data_dir)) {
163     NOTREACHED() << "Failed to get app data directory for Android WebView";
164   }
165   browser_context_.reset(
166       new AwBrowserContext(user_data_dir, native_factory_));
167 }
168
169 AwContentBrowserClient::~AwContentBrowserClient() {
170 }
171
172 void AwContentBrowserClient::AddCertificate(net::URLRequest* request,
173                                             net::CertificateMimeType cert_type,
174                                             const void* cert_data,
175                                             size_t cert_size,
176                                             int render_process_id,
177                                             int render_view_id) {
178   if (cert_size > 0)
179     net::android::StoreCertificate(cert_type, cert_data, cert_size);
180 }
181
182 content::BrowserMainParts* AwContentBrowserClient::CreateBrowserMainParts(
183     const content::MainFunctionParams& parameters) {
184   return new AwBrowserMainParts(browser_context_.get());
185 }
186
187 content::WebContentsViewDelegate*
188 AwContentBrowserClient::GetWebContentsViewDelegate(
189     content::WebContents* web_contents) {
190   return native_factory_->CreateViewDelegate(web_contents);
191 }
192
193 void AwContentBrowserClient::RenderProcessWillLaunch(
194     content::RenderProcessHost* host) {
195   // If WebView becomes multi-process capable, this may be insecure.
196   // More benefit can be derived from the ChildProcessSecurotyPolicy by
197   // deferring the GrantScheme calls until we know that a given child process
198   // really does need that priviledge. Check here to ensure we rethink this
199   // when the time comes. See crbug.com/156062.
200   CHECK(content::RenderProcessHost::run_renderer_in_process());
201
202   // Grant content: and file: scheme to the whole process, since we impose
203   // per-view access checks.
204   content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
205       host->GetID(), android_webview::kContentScheme);
206   content::ChildProcessSecurityPolicy::GetInstance()->GrantScheme(
207       host->GetID(), content::kFileScheme);
208
209   host->AddFilter(new AwContentsMessageFilter(host->GetID()));
210 }
211
212 net::URLRequestContextGetter* AwContentBrowserClient::CreateRequestContext(
213     content::BrowserContext* browser_context,
214     content::ProtocolHandlerMap* protocol_handlers,
215     content::ProtocolHandlerScopedVector protocol_interceptors) {
216   DCHECK(browser_context_.get() == browser_context);
217   // TODO(mkosiba,kinuko): protocol_interceptors should be hooked up in the
218   // downstream. (crbug.com/350286)
219   return browser_context_->CreateRequestContext(protocol_handlers);
220 }
221
222 net::URLRequestContextGetter*
223 AwContentBrowserClient::CreateRequestContextForStoragePartition(
224     content::BrowserContext* browser_context,
225     const base::FilePath& partition_path,
226     bool in_memory,
227     content::ProtocolHandlerMap* protocol_handlers,
228     content::ProtocolHandlerScopedVector protocol_interceptors) {
229   DCHECK(browser_context_.get() == browser_context);
230   return browser_context_->CreateRequestContextForStoragePartition(
231       partition_path, in_memory, protocol_handlers);
232 }
233
234 std::string AwContentBrowserClient::GetCanonicalEncodingNameByAliasName(
235     const std::string& alias_name) {
236   return alias_name;
237 }
238
239 void AwContentBrowserClient::AppendExtraCommandLineSwitches(
240     base::CommandLine* command_line,
241     int child_process_id) {
242   NOTREACHED() << "Android WebView does not support multi-process yet";
243 }
244
245 std::string AwContentBrowserClient::GetApplicationLocale() {
246   return l10n_util::GetDefaultLocale();
247 }
248
249 std::string AwContentBrowserClient::GetAcceptLangs(
250     content::BrowserContext* context) {
251   return GetAcceptLangsImpl();
252 }
253
254 gfx::ImageSkia* AwContentBrowserClient::GetDefaultFavicon() {
255   ResourceBundle& rb = ResourceBundle::GetSharedInstance();
256   // TODO(boliu): Bundle our own default favicon?
257   return rb.GetImageSkiaNamed(IDR_DEFAULT_FAVICON);
258 }
259
260 bool AwContentBrowserClient::AllowAppCache(const GURL& manifest_url,
261                            const GURL& first_party,
262                            content::ResourceContext* context) {
263   // WebView doesn't have a per-site policy for locally stored data,
264   // instead AppCache can be disabled for individual WebViews.
265   return true;
266 }
267
268
269 bool AwContentBrowserClient::AllowGetCookie(const GURL& url,
270                                             const GURL& first_party,
271                                             const net::CookieList& cookie_list,
272                                             content::ResourceContext* context,
273                                             int render_process_id,
274                                             int render_frame_id) {
275   return AwCookieAccessPolicy::GetInstance()->AllowGetCookie(url,
276                                                              first_party,
277                                                              cookie_list,
278                                                              context,
279                                                              render_process_id,
280                                                              render_frame_id);
281 }
282
283 bool AwContentBrowserClient::AllowSetCookie(const GURL& url,
284                                             const GURL& first_party,
285                                             const std::string& cookie_line,
286                                             content::ResourceContext* context,
287                                             int render_process_id,
288                                             int render_frame_id,
289                                             net::CookieOptions* options) {
290   return AwCookieAccessPolicy::GetInstance()->AllowSetCookie(url,
291                                                              first_party,
292                                                              cookie_line,
293                                                              context,
294                                                              render_process_id,
295                                                              render_frame_id,
296                                                              options);
297 }
298
299 bool AwContentBrowserClient::AllowWorkerDatabase(
300     const GURL& url,
301     const base::string16& name,
302     const base::string16& display_name,
303     unsigned long estimated_size,
304     content::ResourceContext* context,
305     const std::vector<std::pair<int, int> >& render_frames) {
306   // Android WebView does not yet support web workers.
307   return false;
308 }
309
310 bool AwContentBrowserClient::AllowWorkerFileSystem(
311     const GURL& url,
312     content::ResourceContext* context,
313     const std::vector<std::pair<int, int> >& render_frames) {
314   // Android WebView does not yet support web workers.
315   return false;
316 }
317
318 bool AwContentBrowserClient::AllowWorkerIndexedDB(
319     const GURL& url,
320     const base::string16& name,
321     content::ResourceContext* context,
322     const std::vector<std::pair<int, int> >& render_frames) {
323   // Android WebView does not yet support web workers.
324   return false;
325 }
326
327 content::QuotaPermissionContext*
328 AwContentBrowserClient::CreateQuotaPermissionContext() {
329   return new AwQuotaPermissionContext;
330 }
331
332 void AwContentBrowserClient::AllowCertificateError(
333     int render_process_id,
334     int render_frame_id,
335     int cert_error,
336     const net::SSLInfo& ssl_info,
337     const GURL& request_url,
338     ResourceType::Type resource_type,
339     bool overridable,
340     bool strict_enforcement,
341     const base::Callback<void(bool)>& callback,
342     content::CertificateRequestResultType* result) {
343   AwContentsClientBridgeBase* client =
344       AwContentsClientBridgeBase::FromID(render_process_id, render_frame_id);
345   bool cancel_request = true;
346   if (client)
347     client->AllowCertificateError(cert_error,
348                                   ssl_info.cert.get(),
349                                   request_url,
350                                   callback,
351                                   &cancel_request);
352   if (cancel_request)
353     *result = content::CERTIFICATE_REQUEST_RESULT_TYPE_DENY;
354 }
355
356 void AwContentBrowserClient::SelectClientCertificate(
357       int render_process_id,
358       int render_frame_id,
359       const net::HttpNetworkSession* network_session,
360       net::SSLCertRequestInfo* cert_request_info,
361       const base::Callback<void(net::X509Certificate*)>& callback) {
362   LOG(WARNING) << "Client certificate request from "
363         << cert_request_info->host_and_port.ToString()
364         << " rejected. (Client certificates not supported in WebView)";
365   callback.Run(NULL);
366 }
367
368 blink::WebNotificationPresenter::Permission
369     AwContentBrowserClient::CheckDesktopNotificationPermission(
370         const GURL& source_url,
371         content::ResourceContext* context,
372         int render_process_id) {
373   // Android WebView does not support notifications, so return Denied here.
374   return blink::WebNotificationPresenter::PermissionDenied;
375 }
376
377 void AwContentBrowserClient::ShowDesktopNotification(
378     const content::ShowDesktopNotificationHostMsgParams& params,
379     int render_process_id,
380     int render_view_id,
381     bool worker) {
382   NOTREACHED() << "Android WebView does not support desktop notifications.";
383 }
384
385 void AwContentBrowserClient::CancelDesktopNotification(
386     int render_process_id,
387     int render_view_id,
388     int notification_id) {
389   NOTREACHED() << "Android WebView does not support desktop notifications.";
390 }
391
392 bool AwContentBrowserClient::CanCreateWindow(
393     const GURL& opener_url,
394     const GURL& opener_top_level_frame_url,
395     const GURL& source_origin,
396     WindowContainerType container_type,
397     const GURL& target_url,
398     const content::Referrer& referrer,
399     WindowOpenDisposition disposition,
400     const blink::WebWindowFeatures& features,
401     bool user_gesture,
402     bool opener_suppressed,
403     content::ResourceContext* context,
404     int render_process_id,
405     bool is_guest,
406     int opener_id,
407     bool* no_javascript_access) {
408   // We unconditionally allow popup windows at this stage and will give
409   // the embedder the opporunity to handle displaying of the popup in
410   // WebContentsDelegate::AddContents (via the
411   // AwContentsClient.onCreateWindow callback).
412   // Note that if the embedder has blocked support for creating popup
413   // windows through AwSettings, then we won't get to this point as
414   // the popup creation will have been blocked at the WebKit level.
415   if (no_javascript_access) {
416     *no_javascript_access = false;
417   }
418   return true;
419 }
420
421 std::string AwContentBrowserClient::GetWorkerProcessTitle(const GURL& url,
422                                           content::ResourceContext* context) {
423   NOTREACHED() << "Android WebView does not yet support web workers.";
424   return std::string();
425 }
426
427
428 void AwContentBrowserClient::ResourceDispatcherHostCreated() {
429   AwResourceDispatcherHostDelegate::ResourceDispatcherHostCreated();
430 }
431
432 net::NetLog* AwContentBrowserClient::GetNetLog() {
433   // TODO(boliu): Implement AwNetLog.
434   return NULL;
435 }
436
437 content::AccessTokenStore* AwContentBrowserClient::CreateAccessTokenStore() {
438   return new AwAccessTokenStore();
439 }
440
441 bool AwContentBrowserClient::IsFastShutdownPossible() {
442   NOTREACHED() << "Android WebView is single process, so IsFastShutdownPossible"
443                << " should never be called";
444   return false;
445 }
446
447 void AwContentBrowserClient::UpdateInspectorSetting(
448     content::RenderViewHost* rvh,
449     const std::string& key,
450     const std::string& value) {
451   // TODO(boliu): Implement persisting inspector settings.
452   NOTIMPLEMENTED();
453 }
454
455 void AwContentBrowserClient::ClearCache(content::RenderViewHost* rvh) {
456   RemoveHttpDiskCache(rvh->GetProcess()->GetBrowserContext(),
457                       rvh->GetProcess()->GetID());
458 }
459
460 void AwContentBrowserClient::ClearCookies(content::RenderViewHost* rvh) {
461   // TODO(boliu): Implement.
462   NOTIMPLEMENTED();
463 }
464
465 base::FilePath AwContentBrowserClient::GetDefaultDownloadDirectory() {
466   // Android WebView does not currently use the Chromium downloads system.
467   // Download requests are cancelled immedately when recognized; see
468   // AwResourceDispatcherHost::CreateResourceHandlerForDownload. However the
469   // download system still tries to start up and calls this before recognizing
470   // the request has been cancelled.
471   return base::FilePath();
472 }
473
474 std::string AwContentBrowserClient::GetDefaultDownloadName() {
475   NOTREACHED() << "Android WebView does not use chromium downloads";
476   return std::string();
477 }
478
479 void AwContentBrowserClient::DidCreatePpapiPlugin(
480     content::BrowserPpapiHost* browser_host) {
481   NOTREACHED() << "Android WebView does not support plugins";
482 }
483
484 bool AwContentBrowserClient::AllowPepperSocketAPI(
485     content::BrowserContext* browser_context,
486     const GURL& url,
487     bool private_api,
488     const content::SocketPermissionRequest* params) {
489   NOTREACHED() << "Android WebView does not support plugins";
490   return false;
491 }
492
493 void AwContentBrowserClient::OverrideWebkitPrefs(content::RenderViewHost* rvh,
494                                                  const GURL& url,
495                                                  WebPreferences* web_prefs) {
496   if (!preferences_populater_.get()) {
497     preferences_populater_ = make_scoped_ptr(native_factory_->
498         CreateWebPreferencesPopulater());
499   }
500   preferences_populater_->PopulateFor(
501       content::WebContents::FromRenderViewHost(rvh), web_prefs);
502 }
503
504 }  // namespace android_webview