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