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 17ChromeWebViewPermissionHelperDelegate::ChromeWebViewPermissionHelperDelegate( 18 extensions::WebViewPermissionHelper* web_view_permission_helper) 19 : WebViewPermissionHelperDelegate(web_view_permission_helper), 20 weak_factory_(this) { 21} 22 23ChromeWebViewPermissionHelperDelegate::~ChromeWebViewPermissionHelperDelegate() 24{} 25 26#if defined(ENABLE_PLUGINS) 27bool 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 47bool 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 64void 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 84void ChromeWebViewPermissionHelperDelegate::OnCouldNotLoadPlugin( 85 const base::FilePath& plugin_path) { 86} 87 88void ChromeWebViewPermissionHelperDelegate::OnBlockedOutdatedPlugin( 89 int placeholder_id, 90 const std::string& identifier) { 91} 92 93void ChromeWebViewPermissionHelperDelegate::OnNPAPINotSupported( 94 const std::string& id) { 95} 96 97void ChromeWebViewPermissionHelperDelegate::OnOpenAboutPlugins() { 98} 99 100#if defined(ENABLE_PLUGIN_INSTALLATION) 101void ChromeWebViewPermissionHelperDelegate::OnFindMissingPlugin( 102 int placeholder_id, 103 const std::string& mime_type) { 104 Send(new ChromeViewMsg_DidNotFindMissingPlugin(placeholder_id)); 105} 106 107void ChromeWebViewPermissionHelperDelegate::OnRemovePluginPlaceholderHost( 108 int placeholder_id) { 109} 110#endif // defined(ENABLE_PLUGIN_INSTALLATION) 111 112void 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 124void 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 141void 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 148void 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 169void 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 176void 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 204void 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 235void ChromeWebViewPermissionHelperDelegate::CancelGeolocationPermissionRequest( 236 int bridge_id) { 237 int request_id = RemoveBridgeID(bridge_id); 238 web_view_permission_helper()->CancelPendingPermissionRequest(request_id); 239} 240 241int 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 252void 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 268void 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 275void 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 293void 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 305void 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 323void 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