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   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 
     68 AwContentsMessageFilter::AwContentsMessageFilter(int process_id)
     69     : process_id_(process_id) {
     70 }
     71 
     72 AwContentsMessageFilter::~AwContentsMessageFilter() {
     73 }
     74 
     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 
     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 
     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:
    111   AwAccessTokenStore() { }
    112 
    113   // content::AccessTokenStore implementation
    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   }
    121   virtual void SaveAccessToken(const GURL& server_url,
    122                                const string16& access_token) OVERRIDE { }
    123 
    124  private:
    125   virtual ~AwAccessTokenStore() { }
    126 
    127   DISALLOW_COPY_AND_ASSIGN(AwAccessTokenStore);
    128 };
    129 
    130 }
    131 
    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 
    144 AwBrowserContext* AwContentBrowserClient::GetAwBrowserContext() {
    145   return AwBrowserContext::GetDefault();
    146 }
    147 
    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 
    159 AwContentBrowserClient::~AwContentBrowserClient() {
    160 }
    161 
    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 
    172 content::BrowserMainParts* AwContentBrowserClient::CreateBrowserMainParts(
    173     const content::MainFunctionParams& parameters) {
    174   return new AwBrowserMainParts(browser_context_.get());
    175 }
    176 
    177 content::WebContentsViewDelegate*
    178 AwContentBrowserClient::GetWebContentsViewDelegate(
    179     content::WebContents* web_contents) {
    180   return native_factory_->CreateViewDelegate(web_contents);
    181 }
    182 
    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*
    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*
    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 
    221 std::string AwContentBrowserClient::GetCanonicalEncodingNameByAliasName(
    222     const std::string& alias_name) {
    223   return alias_name;
    224 }
    225 
    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 
    232 std::string AwContentBrowserClient::GetApplicationLocale() {
    233   return l10n_util::GetDefaultLocale();
    234 }
    235 
    236 std::string AwContentBrowserClient::GetAcceptLangs(
    237     content::BrowserContext* context) {
    238   return GetAcceptLangsImpl();
    239 }
    240 
    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 
    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 
    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 
    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 
    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 
    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 
    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*
    315 AwContentBrowserClient::CreateQuotaPermissionContext() {
    316   return new AwQuotaPermissionContext;
    317 }
    318 
    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 
    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
    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 
    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 
    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 
    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 
    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 
    416 void AwContentBrowserClient::ResourceDispatcherHostCreated() {
    417   AwResourceDispatcherHostDelegate::ResourceDispatcherHostCreated();
    418 }
    419 
    420 net::NetLog* AwContentBrowserClient::GetNetLog() {
    421   // TODO(boliu): Implement AwNetLog.
    422   return NULL;
    423 }
    424 
    425 content::AccessTokenStore* AwContentBrowserClient::CreateAccessTokenStore() {
    426   return new AwAccessTokenStore();
    427 }
    428 
    429 bool AwContentBrowserClient::IsFastShutdownPossible() {
    430   NOTREACHED() << "Android WebView is single process, so IsFastShutdownPossible"
    431                << " should never be called";
    432   return false;
    433 }
    434 
    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 
    443 void AwContentBrowserClient::ClearCache(content::RenderViewHost* rvh) {
    444   RemoveHttpDiskCache(rvh->GetProcess()->GetBrowserContext(),
    445                       rvh->GetProcess()->GetID());
    446 }
    447 
    448 void AwContentBrowserClient::ClearCookies(content::RenderViewHost* rvh) {
    449   // TODO(boliu): Implement.
    450   NOTIMPLEMENTED();
    451 }
    452 
    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 
    462 std::string AwContentBrowserClient::GetDefaultDownloadName() {
    463   NOTREACHED() << "Android WebView does not use chromium downloads";
    464   return std::string();
    465 }
    466 
    467 void AwContentBrowserClient::DidCreatePpapiPlugin(
    468     content::BrowserPpapiHost* browser_host) {
    469   NOTREACHED() << "Android WebView does not support plugins";
    470 }
    471 
    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 
    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