Remove linux_chromium_gn_dbg from the chromium CQ.
[chromium-blink-merge.git] / extensions / browser / guest_view / web_view / web_view_permission_helper.cc
blob46ded6bf4fbd41aa24f5ce8f41fd9b73195e460d
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.
5 #include "extensions/browser/guest_view/web_view/web_view_permission_helper.h"
7 #include "components/guest_view/browser/guest_view_event.h"
8 #include "content/public/browser/render_process_host.h"
9 #include "content/public/browser/render_view_host.h"
10 #include "content/public/browser/user_metrics.h"
11 #include "extensions/browser/api/extensions_api_client.h"
12 #include "extensions/browser/guest_view/web_view/web_view_constants.h"
13 #include "extensions/browser/guest_view/web_view/web_view_guest.h"
14 #include "extensions/browser/guest_view/web_view/web_view_permission_helper_delegate.h"
15 #include "extensions/browser/guest_view/web_view/web_view_permission_types.h"
17 using content::BrowserPluginGuestDelegate;
18 using content::RenderViewHost;
19 using guest_view::GuestViewEvent;
21 namespace extensions {
23 namespace {
24 static std::string PermissionTypeToString(WebViewPermissionType type) {
25 switch (type) {
26 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
27 return webview::kPermissionTypeDownload;
28 case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
29 return webview::kPermissionTypeFileSystem;
30 case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
31 return webview::kPermissionTypeFullscreen;
32 case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
33 return webview::kPermissionTypeGeolocation;
34 case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
35 return webview::kPermissionTypeDialog;
36 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
37 return webview::kPermissionTypeLoadPlugin;
38 case WEB_VIEW_PERMISSION_TYPE_MEDIA:
39 return webview::kPermissionTypeMedia;
40 case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
41 return webview::kPermissionTypeNewWindow;
42 case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
43 return webview::kPermissionTypePointerLock;
44 default:
45 NOTREACHED();
46 return std::string();
50 // static
51 void RecordUserInitiatedUMA(
52 const WebViewPermissionHelper::PermissionResponseInfo& info,
53 bool allow) {
54 if (allow) {
55 // Note that |allow| == true means the embedder explicitly allowed the
56 // request. For some requests they might still fail. An example of such
57 // scenario would be: an embedder allows geolocation request but doesn't
58 // have geolocation access on its own.
59 switch (info.permission_type) {
60 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
61 content::RecordAction(
62 UserMetricsAction("WebView.PermissionAllow.Download"));
63 break;
64 case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
65 content::RecordAction(
66 UserMetricsAction("WebView.PermissionAllow.FileSystem"));
67 break;
68 case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
69 content::RecordAction(
70 UserMetricsAction("WebView.PermissionAllow.Fullscreen"));
71 break;
72 case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
73 content::RecordAction(
74 UserMetricsAction("WebView.PermissionAllow.Geolocation"));
75 break;
76 case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
77 content::RecordAction(
78 UserMetricsAction("WebView.PermissionAllow.JSDialog"));
79 break;
80 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
81 content::RecordAction(
82 UserMetricsAction("WebView.Guest.PermissionAllow.PluginLoad"));
83 case WEB_VIEW_PERMISSION_TYPE_MEDIA:
84 content::RecordAction(
85 UserMetricsAction("WebView.PermissionAllow.Media"));
86 break;
87 case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
88 content::RecordAction(
89 UserMetricsAction("BrowserPlugin.PermissionAllow.NewWindow"));
90 break;
91 case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
92 content::RecordAction(
93 UserMetricsAction("WebView.PermissionAllow.PointerLock"));
94 break;
95 default:
96 break;
98 } else {
99 switch (info.permission_type) {
100 case WEB_VIEW_PERMISSION_TYPE_DOWNLOAD:
101 content::RecordAction(
102 UserMetricsAction("WebView.PermissionDeny.Download"));
103 break;
104 case WEB_VIEW_PERMISSION_TYPE_FILESYSTEM:
105 content::RecordAction(
106 UserMetricsAction("WebView.PermissionDeny.FileSystem"));
107 break;
108 case WEB_VIEW_PERMISSION_TYPE_FULLSCREEN:
109 content::RecordAction(
110 UserMetricsAction("WebView.PermissionDeny.Fullscreen"));
111 break;
112 case WEB_VIEW_PERMISSION_TYPE_GEOLOCATION:
113 content::RecordAction(
114 UserMetricsAction("WebView.PermissionDeny.Geolocation"));
115 break;
116 case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG:
117 content::RecordAction(
118 UserMetricsAction("WebView.PermissionDeny.JSDialog"));
119 break;
120 case WEB_VIEW_PERMISSION_TYPE_LOAD_PLUGIN:
121 content::RecordAction(
122 UserMetricsAction("WebView.Guest.PermissionDeny.PluginLoad"));
123 break;
124 case WEB_VIEW_PERMISSION_TYPE_MEDIA:
125 content::RecordAction(
126 UserMetricsAction("WebView.PermissionDeny.Media"));
127 break;
128 case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW:
129 content::RecordAction(
130 UserMetricsAction("BrowserPlugin.PermissionDeny.NewWindow"));
131 break;
132 case WEB_VIEW_PERMISSION_TYPE_POINTER_LOCK:
133 content::RecordAction(
134 UserMetricsAction("WebView.PermissionDeny.PointerLock"));
135 break;
136 default:
137 break;
142 } // namespace
144 WebViewPermissionHelper::WebViewPermissionHelper(WebViewGuest* web_view_guest)
145 : content::WebContentsObserver(web_view_guest->web_contents()),
146 next_permission_request_id_(guest_view::kInstanceIDNone),
147 web_view_guest_(web_view_guest),
148 weak_factory_(this) {
149 web_view_permission_helper_delegate_.reset(
150 ExtensionsAPIClient::Get()->CreateWebViewPermissionHelperDelegate(
151 this));
154 WebViewPermissionHelper::~WebViewPermissionHelper() {
157 // static
158 WebViewPermissionHelper* WebViewPermissionHelper::FromFrameID(
159 int render_process_id,
160 int render_frame_id) {
161 WebViewGuest* web_view_guest = WebViewGuest::FromFrameID(
162 render_process_id, render_frame_id);
163 if (!web_view_guest) {
164 return NULL;
166 return web_view_guest->web_view_permission_helper_.get();
169 // static
170 WebViewPermissionHelper* WebViewPermissionHelper::FromWebContents(
171 content::WebContents* web_contents) {
172 WebViewGuest* web_view_guest = WebViewGuest::FromWebContents(web_contents);
173 if (!web_view_guest)
174 return NULL;
175 return web_view_guest->web_view_permission_helper_.get();
178 #if defined(ENABLE_PLUGINS)
179 bool WebViewPermissionHelper::OnMessageReceived(
180 const IPC::Message& message,
181 content::RenderFrameHost* render_frame_host) {
182 return web_view_permission_helper_delegate_->OnMessageReceived(
183 message, render_frame_host);
186 bool WebViewPermissionHelper::OnMessageReceived(const IPC::Message& message) {
187 return web_view_permission_helper_delegate_->OnMessageReceived(message);
189 #endif // defined(ENABLE_PLUGINS)
191 void WebViewPermissionHelper::RequestMediaAccessPermission(
192 content::WebContents* source,
193 const content::MediaStreamRequest& request,
194 const content::MediaResponseCallback& callback) {
195 base::DictionaryValue request_info;
196 request_info.SetString(guest_view::kUrl, request.security_origin.spec());
197 RequestPermission(
198 WEB_VIEW_PERMISSION_TYPE_MEDIA,
199 request_info,
200 base::Bind(&WebViewPermissionHelper::OnMediaPermissionResponse,
201 weak_factory_.GetWeakPtr(),
202 request,
203 callback),
204 false /* allowed_by_default */);
207 bool WebViewPermissionHelper::CheckMediaAccessPermission(
208 content::WebContents* source,
209 const GURL& security_origin,
210 content::MediaStreamType type) {
211 if (!web_view_guest()->attached() ||
212 !web_view_guest()->embedder_web_contents()->GetDelegate()) {
213 return false;
215 return web_view_guest()
216 ->embedder_web_contents()
217 ->GetDelegate()
218 ->CheckMediaAccessPermission(
219 web_view_guest()->embedder_web_contents(), security_origin, type);
222 void WebViewPermissionHelper::OnMediaPermissionResponse(
223 const content::MediaStreamRequest& request,
224 const content::MediaResponseCallback& callback,
225 bool allow,
226 const std::string& user_input) {
227 if (!allow) {
228 callback.Run(content::MediaStreamDevices(),
229 content::MEDIA_DEVICE_PERMISSION_DENIED,
230 scoped_ptr<content::MediaStreamUI>());
231 return;
233 if (!web_view_guest()->attached() ||
234 !web_view_guest()->embedder_web_contents()->GetDelegate()) {
235 callback.Run(content::MediaStreamDevices(),
236 content::MEDIA_DEVICE_INVALID_STATE,
237 scoped_ptr<content::MediaStreamUI>());
238 return;
241 web_view_guest()
242 ->embedder_web_contents()
243 ->GetDelegate()
244 ->RequestMediaAccessPermission(
245 web_view_guest()->embedder_web_contents(), request, callback);
248 void WebViewPermissionHelper::CanDownload(
249 const GURL& url,
250 const std::string& request_method,
251 const base::Callback<void(bool)>& callback) {
252 web_view_permission_helper_delegate_->CanDownload(url, request_method,
253 callback);
256 void WebViewPermissionHelper::RequestPointerLockPermission(
257 bool user_gesture,
258 bool last_unlocked_by_target,
259 const base::Callback<void(bool)>& callback) {
260 web_view_permission_helper_delegate_->RequestPointerLockPermission(
261 user_gesture, last_unlocked_by_target, callback);
264 void WebViewPermissionHelper::RequestGeolocationPermission(
265 int bridge_id,
266 const GURL& requesting_frame,
267 bool user_gesture,
268 const base::Callback<void(bool)>& callback) {
269 web_view_permission_helper_delegate_->RequestGeolocationPermission(
270 bridge_id, requesting_frame, user_gesture, callback);
273 void WebViewPermissionHelper::CancelGeolocationPermissionRequest(
274 int bridge_id) {
275 web_view_permission_helper_delegate_->CancelGeolocationPermissionRequest(
276 bridge_id);
279 void WebViewPermissionHelper::RequestFileSystemPermission(
280 const GURL& url,
281 bool allowed_by_default,
282 const base::Callback<void(bool)>& callback) {
283 web_view_permission_helper_delegate_->RequestFileSystemPermission(
284 url, allowed_by_default, callback);
287 void WebViewPermissionHelper::FileSystemAccessedAsync(int render_process_id,
288 int render_frame_id,
289 int request_id,
290 const GURL& url,
291 bool blocked_by_policy) {
292 web_view_permission_helper_delegate_->FileSystemAccessedAsync(
293 render_process_id, render_frame_id, request_id, url, blocked_by_policy);
296 void WebViewPermissionHelper::FileSystemAccessedSync(int render_process_id,
297 int render_frame_id,
298 const GURL& url,
299 bool blocked_by_policy,
300 IPC::Message* reply_msg) {
301 web_view_permission_helper_delegate_->FileSystemAccessedSync(
302 render_process_id, render_frame_id, url, blocked_by_policy, reply_msg);
305 int WebViewPermissionHelper::RequestPermission(
306 WebViewPermissionType permission_type,
307 const base::DictionaryValue& request_info,
308 const PermissionResponseCallback& callback,
309 bool allowed_by_default) {
310 // If there are too many pending permission requests then reject this request.
311 if (pending_permission_requests_.size() >=
312 webview::kMaxOutstandingPermissionRequests) {
313 // Let the stack unwind before we deny the permission request so that
314 // objects held by the permission request are not destroyed immediately
315 // after creation. This is to allow those same objects to be accessed again
316 // in the same scope without fear of use after freeing.
317 base::MessageLoop::current()->PostTask(
318 FROM_HERE,
319 base::Bind(&PermissionResponseCallback::Run,
320 base::Owned(new PermissionResponseCallback(callback)),
321 allowed_by_default,
322 std::string()));
323 return webview::kInvalidPermissionRequestID;
326 int request_id = next_permission_request_id_++;
327 pending_permission_requests_[request_id] =
328 PermissionResponseInfo(callback, permission_type, allowed_by_default);
329 scoped_ptr<base::DictionaryValue> args(new base::DictionaryValue());
330 args->Set(webview::kRequestInfo, request_info.DeepCopy());
331 args->SetInteger(webview::kRequestId, request_id);
332 switch (permission_type) {
333 case WEB_VIEW_PERMISSION_TYPE_NEW_WINDOW: {
334 web_view_guest_->DispatchEventToView(
335 new GuestViewEvent(webview::kEventNewWindow, args.Pass()));
336 break;
338 case WEB_VIEW_PERMISSION_TYPE_JAVASCRIPT_DIALOG: {
339 web_view_guest_->DispatchEventToView(
340 new GuestViewEvent(webview::kEventDialog, args.Pass()));
341 break;
343 default: {
344 args->SetString(webview::kPermission,
345 PermissionTypeToString(permission_type));
346 web_view_guest_->DispatchEventToView(new GuestViewEvent(
347 webview::kEventPermissionRequest, args.Pass()));
348 break;
351 return request_id;
354 WebViewPermissionHelper::SetPermissionResult
355 WebViewPermissionHelper::SetPermission(
356 int request_id,
357 PermissionResponseAction action,
358 const std::string& user_input) {
359 RequestMap::iterator request_itr =
360 pending_permission_requests_.find(request_id);
362 if (request_itr == pending_permission_requests_.end())
363 return SET_PERMISSION_INVALID;
365 const PermissionResponseInfo& info = request_itr->second;
366 bool allow = (action == ALLOW) ||
367 ((action == DEFAULT) && info.allowed_by_default);
369 info.callback.Run(allow, user_input);
371 // Only record user initiated (i.e. non-default) actions.
372 if (action != DEFAULT)
373 RecordUserInitiatedUMA(info, allow);
375 pending_permission_requests_.erase(request_itr);
377 return allow ? SET_PERMISSION_ALLOWED : SET_PERMISSION_DENIED;
380 void WebViewPermissionHelper::CancelPendingPermissionRequest(int request_id) {
381 RequestMap::iterator request_itr =
382 pending_permission_requests_.find(request_id);
384 if (request_itr == pending_permission_requests_.end())
385 return;
387 pending_permission_requests_.erase(request_itr);
390 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo()
391 : permission_type(WEB_VIEW_PERMISSION_TYPE_UNKNOWN),
392 allowed_by_default(false) {
395 WebViewPermissionHelper::PermissionResponseInfo::PermissionResponseInfo(
396 const PermissionResponseCallback& callback,
397 WebViewPermissionType permission_type,
398 bool allowed_by_default)
399 : callback(callback),
400 permission_type(permission_type),
401 allowed_by_default(allowed_by_default) {
404 WebViewPermissionHelper::PermissionResponseInfo::~PermissionResponseInfo() {
407 } // namespace extensions