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