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