cygprofile: increase timeouts to allow showing web contents
[chromium-blink-merge.git] / android_webview / browser / aw_permission_manager.cc
blob6fe1e1e400a906ab5816b4c019c3057bae5bda3f
1 // Copyright 2015 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 "android_webview/browser/aw_permission_manager.h"
7 #include <string>
9 #include "android_webview/browser/aw_browser_permission_request_delegate.h"
10 #include "base/callback.h"
11 #include "base/containers/hash_tables.h"
12 #include "base/logging.h"
13 #include "base/memory/weak_ptr.h"
14 #include "content/public/browser/permission_type.h"
15 #include "content/public/browser/render_frame_host.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/web_contents.h"
19 using content::PermissionStatus;
20 using content::PermissionType;
22 namespace android_webview {
24 class LastRequestResultCache {
25 public:
26 LastRequestResultCache() : weak_factory_(this) {}
28 void SetResult(PermissionType permission,
29 const GURL& requesting_origin,
30 const GURL& embedding_origin,
31 PermissionStatus status) {
32 DCHECK(status == content::PERMISSION_STATUS_GRANTED ||
33 status == content::PERMISSION_STATUS_DENIED);
35 // TODO(ddorwin): We should be denying empty origins at a higher level.
36 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
37 DLOG(WARNING) << "Not caching result because of empty origin.";
38 return;
41 if (!requesting_origin.is_valid()) {
42 NOTREACHED() << requesting_origin.possibly_invalid_spec();
43 return;
45 if (!embedding_origin.is_valid()) {
46 NOTREACHED() << embedding_origin.possibly_invalid_spec();
47 return;
50 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
51 // Other permissions are not cached.
52 return;
55 std::string key = GetCacheKey(requesting_origin, embedding_origin);
56 if (key.empty()) {
57 NOTREACHED();
58 // Never store an empty key because it could inadvertently be used for
59 // another combination.
60 return;
62 pmi_result_cache_[key] = status;
65 PermissionStatus GetResult(PermissionType permission,
66 const GURL& requesting_origin,
67 const GURL& embedding_origin) const {
68 // TODO(ddorwin): We should be denying empty origins at a higher level.
69 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
70 return content::PERMISSION_STATUS_ASK;
73 DCHECK(requesting_origin.is_valid())
74 << requesting_origin.possibly_invalid_spec();
75 DCHECK(embedding_origin.is_valid())
76 << embedding_origin.possibly_invalid_spec();
78 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
79 NOTREACHED() << "Results are only cached for PROTECTED_MEDIA_IDENTIFIER";
80 return content::PERMISSION_STATUS_ASK;
83 std::string key = GetCacheKey(requesting_origin, embedding_origin);
84 StatusMap::const_iterator it = pmi_result_cache_.find(key);
85 if (it == pmi_result_cache_.end()) {
86 DLOG(WARNING) << "GetResult() called for uncached origins: " << key;
87 return content::PERMISSION_STATUS_ASK;
90 DCHECK(!key.empty());
91 return it->second;
94 void ClearResult(PermissionType permission,
95 const GURL& requesting_origin,
96 const GURL& embedding_origin) {
97 // TODO(ddorwin): We should be denying empty origins at a higher level.
98 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
99 return;
102 DCHECK(requesting_origin.is_valid())
103 << requesting_origin.possibly_invalid_spec();
104 DCHECK(embedding_origin.is_valid())
105 << embedding_origin.possibly_invalid_spec();
108 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
109 // Other permissions are not cached, so nothing to clear.
110 return;
113 std::string key = GetCacheKey(requesting_origin, embedding_origin);
114 pmi_result_cache_.erase(key);
117 base::WeakPtr<LastRequestResultCache> GetWeakPtr() {
118 return weak_factory_.GetWeakPtr();
121 private:
122 // Returns a concatenation of the origins to be used as the index.
123 // Returns the empty string if either origin is invalid or empty.
124 static std::string GetCacheKey(const GURL& requesting_origin,
125 const GURL& embedding_origin) {
126 const std::string& requesting = requesting_origin.spec();
127 const std::string& embedding = embedding_origin.spec();
128 if (requesting.empty() || embedding.empty())
129 return std::string();
130 return requesting + "," + embedding;
133 using StatusMap = base::hash_map<std::string, PermissionStatus>;
134 StatusMap pmi_result_cache_;
136 base::WeakPtrFactory<LastRequestResultCache> weak_factory_;
138 DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache);
141 namespace {
143 void CallbackPermisisonStatusWrapper(
144 const base::WeakPtr<LastRequestResultCache>& result_cache,
145 const base::Callback<void(PermissionStatus)>& callback,
146 PermissionType permission,
147 const GURL& requesting_origin,
148 const GURL& embedding_origin,
149 bool allowed) {
150 PermissionStatus status = allowed ? content::PERMISSION_STATUS_GRANTED
151 : content::PERMISSION_STATUS_DENIED;
152 if (result_cache.get()) {
153 result_cache->SetResult(permission, requesting_origin, embedding_origin,
154 status);
157 callback.Run(status);
160 } // anonymous namespace
162 AwPermissionManager::AwPermissionManager()
163 : content::PermissionManager(), result_cache_(new LastRequestResultCache) {
166 AwPermissionManager::~AwPermissionManager() {
169 void AwPermissionManager::RequestPermission(
170 PermissionType permission,
171 content::RenderFrameHost* render_frame_host,
172 int request_id,
173 const GURL& origin,
174 bool user_gesture,
175 const base::Callback<void(PermissionStatus)>& callback) {
176 int render_process_id = render_frame_host->GetProcess()->GetID();
177 int render_frame_id = render_frame_host->GetRoutingID();
178 AwBrowserPermissionRequestDelegate* delegate =
179 AwBrowserPermissionRequestDelegate::FromID(render_process_id,
180 render_frame_id);
181 if (!delegate) {
182 DVLOG(0) << "Dropping permission request for "
183 << static_cast<int>(permission);
184 callback.Run(content::PERMISSION_STATUS_DENIED);
185 return;
188 const GURL& embedding_origin =
189 content::WebContents::FromRenderFrameHost(render_frame_host)
190 ->GetLastCommittedURL().GetOrigin();
192 switch (permission) {
193 case PermissionType::GEOLOCATION:
194 delegate->RequestGeolocationPermission(
195 origin, base::Bind(&CallbackPermisisonStatusWrapper,
196 result_cache_->GetWeakPtr(), callback, permission,
197 origin, embedding_origin));
198 break;
199 case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
200 delegate->RequestProtectedMediaIdentifierPermission(
201 origin, base::Bind(&CallbackPermisisonStatusWrapper,
202 result_cache_->GetWeakPtr(), callback, permission,
203 origin, embedding_origin));
204 break;
205 case PermissionType::MIDI_SYSEX:
206 delegate->RequestMIDISysexPermission(
207 origin, base::Bind(&CallbackPermisisonStatusWrapper,
208 result_cache_->GetWeakPtr(), callback, permission,
209 origin, embedding_origin));
210 break;
211 case PermissionType::AUDIO_CAPTURE:
212 case PermissionType::VIDEO_CAPTURE:
213 case PermissionType::NOTIFICATIONS:
214 case PermissionType::PUSH_MESSAGING:
215 case PermissionType::DURABLE_STORAGE:
216 NOTIMPLEMENTED() << "RequestPermission is not implemented for "
217 << static_cast<int>(permission);
218 callback.Run(content::PERMISSION_STATUS_DENIED);
219 break;
220 case PermissionType::MIDI:
221 callback.Run(content::PERMISSION_STATUS_GRANTED);
222 break;
223 case PermissionType::NUM:
224 NOTREACHED() << "PermissionType::NUM was not expected here.";
225 callback.Run(content::PERMISSION_STATUS_DENIED);
226 break;
230 void AwPermissionManager::CancelPermissionRequest(
231 PermissionType permission,
232 content::RenderFrameHost* render_frame_host,
233 int request_id,
234 const GURL& origin) {
235 // The caller is canceling (presumably) the most recent request. Assuming the
236 // request did not complete, the user did not respond to the requset.
237 // Thus, assume we do not know the result.
238 const GURL& embedding_origin =
239 content::WebContents::FromRenderFrameHost(render_frame_host)
240 ->GetLastCommittedURL().GetOrigin();
241 result_cache_->ClearResult(permission, origin, embedding_origin);
243 int render_process_id = render_frame_host->GetProcess()->GetID();
244 int render_frame_id = render_frame_host->GetRoutingID();
245 AwBrowserPermissionRequestDelegate* delegate =
246 AwBrowserPermissionRequestDelegate::FromID(render_process_id,
247 render_frame_id);
248 if (!delegate)
249 return;
251 switch (permission) {
252 case PermissionType::GEOLOCATION:
253 delegate->CancelGeolocationPermissionRequests(origin);
254 break;
255 case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
256 delegate->CancelProtectedMediaIdentifierPermissionRequests(origin);
257 break;
258 case PermissionType::MIDI_SYSEX:
259 delegate->CancelMIDISysexPermissionRequests(origin);
260 break;
261 case PermissionType::NOTIFICATIONS:
262 case PermissionType::PUSH_MESSAGING:
263 case PermissionType::DURABLE_STORAGE:
264 case PermissionType::AUDIO_CAPTURE:
265 case PermissionType::VIDEO_CAPTURE:
266 NOTIMPLEMENTED() << "CancelPermission not implemented for "
267 << static_cast<int>(permission);
268 break;
269 case PermissionType::MIDI:
270 // There is nothing to cancel so this is simply ignored.
271 break;
272 case PermissionType::NUM:
273 NOTREACHED() << "PermissionType::NUM was not expected here.";
274 break;
278 void AwPermissionManager::ResetPermission(PermissionType permission,
279 const GURL& requesting_origin,
280 const GURL& embedding_origin) {
281 result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
284 PermissionStatus AwPermissionManager::GetPermissionStatus(
285 PermissionType permission,
286 const GURL& requesting_origin,
287 const GURL& embedding_origin) {
288 // Method is called outside the Permissions API only for this permission.
289 if (permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
290 return result_cache_->GetResult(permission, requesting_origin,
291 embedding_origin);
292 } else if (permission == PermissionType::MIDI) {
293 return content::PERMISSION_STATUS_GRANTED;
296 return content::PERMISSION_STATUS_DENIED;
299 void AwPermissionManager::RegisterPermissionUsage(
300 PermissionType permission,
301 const GURL& requesting_origin,
302 const GURL& embedding_origin) {
305 int AwPermissionManager::SubscribePermissionStatusChange(
306 PermissionType permission,
307 const GURL& requesting_origin,
308 const GURL& embedding_origin,
309 const base::Callback<void(PermissionStatus)>& callback) {
310 return -1;
313 void AwPermissionManager::UnsubscribePermissionStatusChange(
314 int subscription_id) {
317 } // namespace android_webview