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