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