Home | History | Annotate | Download | only in web_view
      1 // Copyright 2014 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 "chrome/browser/guest_view/web_view/chrome_web_view_permission_helper_delegate.h"
      6 
      7 #include "chrome/browser/content_settings/tab_specific_content_settings.h"
      8 #include "chrome/browser/geolocation/geolocation_permission_context.h"
      9 #include "chrome/browser/geolocation/geolocation_permission_context_factory.h"
     10 #include "chrome/browser/plugins/chrome_plugin_service_filter.h"
     11 #include "chrome/browser/profiles/profile.h"
     12 #include "chrome/common/render_messages.h"
     13 #include "content/public/browser/user_metrics.h"
     14 #include "extensions/browser/guest_view/web_view/web_view_constants.h"
     15 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
     16 
     17 ChromeWebViewPermissionHelperDelegate::ChromeWebViewPermissionHelperDelegate(
     18     extensions::WebViewPermissionHelper* web_view_permission_helper)
     19     : WebViewPermissionHelperDelegate(web_view_permission_helper),
     20       weak_factory_(this) {
     21 }
     22 
     23 ChromeWebViewPermissionHelperDelegate::~ChromeWebViewPermissionHelperDelegate()
     24 {}
     25 
     26 #if defined(ENABLE_PLUGINS)
     27 bool ChromeWebViewPermissionHelperDelegate::OnMessageReceived(
     28     const IPC::Message& message,
     29     content::RenderFrameHost* render_frame_host) {
     30   IPC_BEGIN_MESSAGE_MAP(ChromeWebViewPermissionHelperDelegate, message)
     31     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedOutdatedPlugin,
     32                         OnBlockedOutdatedPlugin)
     33     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_BlockedUnauthorizedPlugin,
     34                         OnBlockedUnauthorizedPlugin)
     35     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_NPAPINotSupported,
     36                         OnNPAPINotSupported)
     37 #if defined(ENABLE_PLUGIN_INSTALLATION)
     38     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_FindMissingPlugin,
     39                         OnFindMissingPlugin)
     40 #endif
     41     IPC_MESSAGE_UNHANDLED(return false)
     42   IPC_END_MESSAGE_MAP()
     43 
     44   return true;
     45 }
     46 
     47 bool ChromeWebViewPermissionHelperDelegate::OnMessageReceived(
     48     const IPC::Message& message) {
     49   IPC_BEGIN_MESSAGE_MAP(ChromeWebViewPermissionHelperDelegate, message)
     50     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_CouldNotLoadPlugin,
     51                         OnCouldNotLoadPlugin)
     52     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_OpenAboutPlugins,
     53                         OnOpenAboutPlugins)
     54 #if defined(ENABLE_PLUGIN_INSTALLATION)
     55     IPC_MESSAGE_HANDLER(ChromeViewHostMsg_RemovePluginPlaceholderHost,
     56                         OnRemovePluginPlaceholderHost)
     57 #endif
     58     IPC_MESSAGE_UNHANDLED(return false)
     59   IPC_END_MESSAGE_MAP()
     60 
     61   return true;
     62 }
     63 
     64 void ChromeWebViewPermissionHelperDelegate::OnBlockedUnauthorizedPlugin(
     65     const base::string16& name,
     66     const std::string& identifier) {
     67   const char kPluginName[] = "name";
     68   const char kPluginIdentifier[] = "identifier";
     69 
     70   base::DictionaryValue info;
     71   info.SetString(std::string(kPluginName), name);
     72   info.SetString(std::string(kPluginIdentifier), identifier);
     73   web_view_permission_helper()->RequestPermission(
     74       WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN,
     75       info,
     76       base::Bind(&ChromeWebViewPermissionHelperDelegate::OnPermissionResponse,
     77                  weak_factory_.GetWeakPtr(),
     78                  identifier),
     79       true /* allowed_by_default */);
     80   content::RecordAction(
     81       base::UserMetricsAction("WebView.Guest.PluginLoadRequest"));
     82 }
     83 
     84 void ChromeWebViewPermissionHelperDelegate::OnCouldNotLoadPlugin(
     85     const base::FilePath& plugin_path) {
     86 }
     87 
     88 void ChromeWebViewPermissionHelperDelegate::OnBlockedOutdatedPlugin(
     89     int placeholder_id,
     90     const std::string& identifier) {
     91 }
     92 
     93 void ChromeWebViewPermissionHelperDelegate::OnNPAPINotSupported(
     94     const std::string& id) {
     95 }
     96 
     97 void ChromeWebViewPermissionHelperDelegate::OnOpenAboutPlugins() {
     98 }
     99 
    100 #if defined(ENABLE_PLUGIN_INSTALLATION)
    101 void ChromeWebViewPermissionHelperDelegate::OnFindMissingPlugin(
    102     int placeholder_id,
    103     const std::string& mime_type) {
    104   Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id));
    105 }
    106 
    107 void ChromeWebViewPermissionHelperDelegate::OnRemovePluginPlaceholderHost(
    108     int placeholder_id) {
    109 }
    110 #endif  // defined(ENABLE_PLUGIN_INSTALLATION)
    111 
    112 void ChromeWebViewPermissionHelperDelegate::OnPermissionResponse(
    113     const std::string& identifier,
    114     bool allow,
    115     const std::string& input) {
    116   if (allow) {
    117     ChromePluginServiceFilter::GetInstance()->AuthorizeAllPlugins(
    118         web_contents(), true, identifier);
    119   }
    120 }
    121 
    122 #endif  // defined(ENABLE_PLUGINS)
    123 
    124 void ChromeWebViewPermissionHelperDelegate::CanDownload(
    125     content::RenderViewHost* render_view_host,
    126     const GURL& url,
    127     const std::string& request_method,
    128     const base::Callback<void(bool)>& callback) {
    129   base::DictionaryValue request_info;
    130   request_info.SetString(guestview::kUrl, url.spec());
    131   web_view_permission_helper()->RequestPermission(
    132       WEB_VIEW_PERMISSION_TYPE_DOWNLOAD,
    133       request_info,
    134       base::Bind(
    135           &ChromeWebViewPermissionHelperDelegate::OnDownloadPermissionResponse,
    136           base::Unretained(this),
    137           callback),
    138       false /* allowed_by_default */);
    139 }
    140 
    141 void ChromeWebViewPermissionHelperDelegate::OnDownloadPermissionResponse(
    142     const base::Callback<void(bool)>& callback,
    143     bool allow,
    144     const std::string& user_input) {
    145   callback.Run(allow && web_view_guest()->attached());
    146 }
    147 
    148 void ChromeWebViewPermissionHelperDelegate::RequestPointerLockPermission(
    149     bool user_gesture,
    150     bool last_unlocked_by_target,
    151     const base::Callback<void(bool)>& callback) {
    152   base::DictionaryValue request_info;
    153   request_info.SetBoolean(guestview::kUserGesture, user_gesture);
    154   request_info.SetBoolean(webview::kLastUnlockedBySelf,
    155                           last_unlocked_by_target);
    156   request_info.SetString(guestview::kUrl,
    157                          web_contents()->GetLastCommittedURL().spec());
    158 
    159   web_view_permission_helper()->RequestPermission(
    160       WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK,
    161       request_info,
    162       base::Bind(&ChromeWebViewPermissionHelperDelegate::
    163                      OnPointerLockPermissionResponse,
    164                  base::Unretained(this),
    165                  callback),
    166       false /* allowed_by_default */);
    167 }
    168 
    169 void ChromeWebViewPermissionHelperDelegate::OnPointerLockPermissionResponse(
    170     const base::Callback<void(bool)>& callback,
    171     bool allow,
    172     const std::string& user_input) {
    173   callback.Run(allow && web_view_guest()->attached());
    174 }
    175 
    176 void ChromeWebViewPermissionHelperDelegate::RequestGeolocationPermission(
    177     int bridge_id,
    178     const GURL& requesting_frame,
    179     bool user_gesture,
    180     const base::Callback<void(bool)>& callback) {
    181   base::DictionaryValue request_info;
    182   request_info.SetString(guestview::kUrl, requesting_frame.spec());
    183   request_info.SetBoolean(guestview::kUserGesture, user_gesture);
    184 
    185   // It is safe to hold an unretained pointer to
    186   // ChromeWebViewPermissionHelperDelegate because this callback is called from
    187   // ChromeWebViewPermissionHelperDelegate::SetPermission.
    188   const extensions::WebViewPermissionHelper::PermissionResponseCallback
    189       permission_callback =
    190       base::Bind(&ChromeWebViewPermissionHelperDelegate::
    191                      OnGeolocationPermissionResponse,
    192                  base::Unretained(this),
    193                  bridge_id,
    194                  user_gesture,
    195                  callback);
    196   int request_id = web_view_permission_helper()->RequestPermission(
    197       WEB_VIEW_PERMISSION_TYPE_GEOLOCATION,
    198       request_info,
    199       permission_callback,
    200       false /* allowed_by_default */);
    201   bridge_id_to_request_id_map_[bridge_id] = request_id;
    202 }
    203 
    204 void ChromeWebViewPermissionHelperDelegate::OnGeolocationPermissionResponse(
    205     int bridge_id,
    206     bool user_gesture,
    207     const base::Callback<void(bool)>& callback,
    208     bool allow,
    209     const std::string& user_input) {
    210   // The <webview> embedder has allowed the permission. We now need to make sure
    211   // that the embedder has geolocation permission.
    212   RemoveBridgeID(bridge_id);
    213 
    214   if (!allow || !web_view_guest()->attached()) {
    215     callback.Run(false);
    216     return;
    217   }
    218 
    219   Profile* profile = Profile::FromBrowserContext(
    220       web_view_guest()->browser_context());
    221   GeolocationPermissionContextFactory::GetForProfile(profile)->
    222       RequestGeolocationPermission(
    223           web_view_guest()->embedder_web_contents(),
    224           // The geolocation permission request here is not initiated
    225           // through WebGeolocationPermissionRequest. We are only interested
    226           // in the fact whether the embedder/app has geolocation
    227           // permission. Therefore we use an invalid |bridge_id|.
    228           -1,
    229           web_view_guest()->embedder_web_contents()->GetLastCommittedURL(),
    230           user_gesture,
    231           callback,
    232           NULL);
    233 }
    234 
    235 void ChromeWebViewPermissionHelperDelegate::CancelGeolocationPermissionRequest(
    236     int bridge_id) {
    237   int request_id = RemoveBridgeID(bridge_id);
    238   web_view_permission_helper()->CancelPendingPermissionRequest(request_id);
    239 }
    240 
    241 int ChromeWebViewPermissionHelperDelegate::RemoveBridgeID(int bridge_id) {
    242   std::map<int, int>::iterator bridge_itr =
    243       bridge_id_to_request_id_map_.find(bridge_id);
    244   if (bridge_itr == bridge_id_to_request_id_map_.end())
    245     return webview::kInvalidPermissionRequestID;
    246 
    247   int request_id = bridge_itr->second;
    248   bridge_id_to_request_id_map_.erase(bridge_itr);
    249   return request_id;
    250 }
    251 
    252 void ChromeWebViewPermissionHelperDelegate::RequestFileSystemPermission(
    253     const GURL& url,
    254     bool allowed_by_default,
    255     const base::Callback<void(bool)>& callback) {
    256   base::DictionaryValue request_info;
    257   request_info.SetString(guestview::kUrl, url.spec());
    258   web_view_permission_helper()->RequestPermission(
    259       WEB_VIEW_PERMISSION_TYPE_FILESYSTEM,
    260       request_info,
    261       base::Bind(&ChromeWebViewPermissionHelperDelegate::
    262                      OnFileSystemPermissionResponse,
    263                  base::Unretained(this),
    264                  callback),
    265       allowed_by_default);
    266 }
    267 
    268 void ChromeWebViewPermissionHelperDelegate::OnFileSystemPermissionResponse(
    269     const base::Callback<void(bool)>& callback,
    270     bool allow,
    271     const std::string& user_input) {
    272   callback.Run(allow && web_view_guest()->attached());
    273 }
    274 
    275 void ChromeWebViewPermissionHelperDelegate::FileSystemAccessedAsync(
    276     int render_process_id,
    277     int render_frame_id,
    278     int request_id,
    279     const GURL& url,
    280     bool blocked_by_policy) {
    281   RequestFileSystemPermission(
    282       url,
    283       !blocked_by_policy,
    284       base::Bind(&ChromeWebViewPermissionHelperDelegate::
    285                      FileSystemAccessedAsyncResponse,
    286                  base::Unretained(this),
    287                  render_process_id,
    288                  render_frame_id,
    289                  request_id,
    290                  url));
    291 }
    292 
    293 void ChromeWebViewPermissionHelperDelegate::FileSystemAccessedAsyncResponse(
    294     int render_process_id,
    295     int render_frame_id,
    296     int request_id,
    297     const GURL& url,
    298     bool allowed) {
    299   TabSpecificContentSettings::FileSystemAccessed(
    300       render_process_id, render_frame_id, url, !allowed);
    301   Send(new ChromeViewMsg_RequestFileSystemAccessAsyncResponse(
    302       render_frame_id, request_id, allowed));
    303 }
    304 
    305 void ChromeWebViewPermissionHelperDelegate::FileSystemAccessedSync(
    306     int render_process_id,
    307     int render_frame_id,
    308     const GURL& url,
    309     bool blocked_by_policy,
    310     IPC::Message* reply_msg) {
    311   RequestFileSystemPermission(
    312       url,
    313       !blocked_by_policy,
    314       base::Bind(&ChromeWebViewPermissionHelperDelegate::
    315                      FileSystemAccessedSyncResponse,
    316                  base::Unretained(this),
    317                  render_process_id,
    318                  render_frame_id,
    319                  url,
    320                  reply_msg));
    321 }
    322 
    323 void ChromeWebViewPermissionHelperDelegate::FileSystemAccessedSyncResponse(
    324     int render_process_id,
    325     int render_frame_id,
    326     const GURL& url,
    327     IPC::Message* reply_msg,
    328     bool allowed) {
    329   TabSpecificContentSettings::FileSystemAccessed(
    330       render_process_id, render_frame_id, url, !allowed);
    331   ChromeViewHostMsg_RequestFileSystemAccessSync::WriteReplyParams(reply_msg,
    332                                                                   allowed);
    333   Send(reply_msg);
    334 }
    335