Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1109)

Side by Side Diff: android_webview/browser/aw_permission_manager.cc

Issue 1726323002: Have Permission{Manager,Service} use Origin. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Clarify and test Origin.empty_. Created 4 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright 2015 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "android_webview/browser/aw_permission_manager.h" 5 #include "android_webview/browser/aw_permission_manager.h"
6 6
7 #include <string> 7 #include <string>
8 8
9 #include "android_webview/browser/aw_browser_permission_request_delegate.h" 9 #include "android_webview/browser/aw_browser_permission_request_delegate.h"
10 #include "base/callback.h" 10 #include "base/callback.h"
11 #include "base/containers/hash_tables.h" 11 #include "base/containers/hash_tables.h"
12 #include "base/logging.h" 12 #include "base/logging.h"
13 #include "content/public/browser/permission_type.h" 13 #include "content/public/browser/permission_type.h"
14 #include "content/public/browser/render_frame_host.h" 14 #include "content/public/browser/render_frame_host.h"
15 #include "content/public/browser/render_process_host.h" 15 #include "content/public/browser/render_process_host.h"
16 #include "content/public/browser/web_contents.h" 16 #include "content/public/browser/web_contents.h"
17 17
18 using content::PermissionStatus; 18 using content::PermissionStatus;
19 using content::PermissionType; 19 using content::PermissionType;
20 20
21 namespace android_webview { 21 namespace android_webview {
22 22
23 class LastRequestResultCache { 23 class LastRequestResultCache {
24 public: 24 public:
25 LastRequestResultCache() = default; 25 LastRequestResultCache() = default;
26 26
27 void SetResult(PermissionType permission, 27 void SetResult(PermissionType permission,
28 const GURL& requesting_origin, 28 const url::Origin& requesting_origin,
29 const GURL& embedding_origin, 29 const url::Origin& embedding_origin,
30 PermissionStatus status) { 30 PermissionStatus status) {
31 DCHECK(status == content::PermissionStatus::GRANTED || 31 DCHECK(status == content::PermissionStatus::GRANTED ||
32 status == content::PermissionStatus::DENIED); 32 status == content::PermissionStatus::DENIED);
33 33
34 // TODO(ddorwin): We should be denying empty origins at a higher level. 34 // TODO(ddorwin): We should be denying empty origins at a higher level.
35 if (requesting_origin.is_empty() || embedding_origin.is_empty()) { 35 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
36 DLOG(WARNING) << "Not caching result because of empty origin."; 36 DLOG(WARNING) << "Not caching result because of empty origin.";
37 return; 37 return;
38 } 38 }
39 39
(...skipping 15 matching lines...) Expand all
55 if (key.empty()) { 55 if (key.empty()) {
56 NOTREACHED(); 56 NOTREACHED();
57 // Never store an empty key because it could inadvertently be used for 57 // Never store an empty key because it could inadvertently be used for
58 // another combination. 58 // another combination.
59 return; 59 return;
60 } 60 }
61 pmi_result_cache_[key] = status; 61 pmi_result_cache_[key] = status;
62 } 62 }
63 63
64 PermissionStatus GetResult(PermissionType permission, 64 PermissionStatus GetResult(PermissionType permission,
65 const GURL& requesting_origin, 65 const url::Origin& requesting_origin,
66 const GURL& embedding_origin) const { 66 const url::Origin& embedding_origin) const {
67 // TODO(ddorwin): We should be denying empty origins at a higher level. 67 // TODO(ddorwin): We should be denying empty origins at a higher level.
68 if (requesting_origin.is_empty() || embedding_origin.is_empty()) { 68 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
69 return content::PermissionStatus::ASK; 69 return content::PermissionStatus::ASK;
70 } 70 }
71 71
72 DCHECK(requesting_origin.is_valid()) 72 DCHECK(requesting_origin.is_valid())
73 << requesting_origin.possibly_invalid_spec(); 73 << requesting_origin.possibly_invalid_spec();
74 DCHECK(embedding_origin.is_valid()) 74 DCHECK(embedding_origin.is_valid())
75 << embedding_origin.possibly_invalid_spec(); 75 << embedding_origin.possibly_invalid_spec();
76 76
77 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) { 77 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
78 NOTREACHED() << "Results are only cached for PROTECTED_MEDIA_IDENTIFIER"; 78 NOTREACHED() << "Results are only cached for PROTECTED_MEDIA_IDENTIFIER";
79 return content::PermissionStatus::ASK; 79 return content::PermissionStatus::ASK;
80 } 80 }
81 81
82 std::string key = GetCacheKey(requesting_origin, embedding_origin); 82 std::string key = GetCacheKey(requesting_origin, embedding_origin);
83 StatusMap::const_iterator it = pmi_result_cache_.find(key); 83 StatusMap::const_iterator it = pmi_result_cache_.find(key);
84 if (it == pmi_result_cache_.end()) { 84 if (it == pmi_result_cache_.end()) {
85 DLOG(WARNING) << "GetResult() called for uncached origins: " << key; 85 DLOG(WARNING) << "GetResult() called for uncached origins: " << key;
86 return content::PermissionStatus::ASK; 86 return content::PermissionStatus::ASK;
87 } 87 }
88 88
89 DCHECK(!key.empty()); 89 DCHECK(!key.empty());
90 return it->second; 90 return it->second;
91 } 91 }
92 92
93 void ClearResult(PermissionType permission, 93 void ClearResult(PermissionType permission,
94 const GURL& requesting_origin, 94 const url::Origin& requesting_origin,
95 const GURL& embedding_origin) { 95 const url::Origin& embedding_origin) {
96 // TODO(ddorwin): We should be denying empty origins at a higher level. 96 // TODO(ddorwin): We should be denying empty origins at a higher level.
97 if (requesting_origin.is_empty() || embedding_origin.is_empty()) { 97 if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
98 return; 98 return;
99 } 99 }
100 100
101 DCHECK(requesting_origin.is_valid()) 101 DCHECK(requesting_origin.is_valid())
102 << requesting_origin.possibly_invalid_spec(); 102 << requesting_origin.possibly_invalid_spec();
103 DCHECK(embedding_origin.is_valid()) 103 DCHECK(embedding_origin.is_valid())
104 << embedding_origin.possibly_invalid_spec(); 104 << embedding_origin.possibly_invalid_spec();
105 105
106 106
107 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) { 107 if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
108 // Other permissions are not cached, so nothing to clear. 108 // Other permissions are not cached, so nothing to clear.
109 return; 109 return;
110 } 110 }
111 111
112 std::string key = GetCacheKey(requesting_origin, embedding_origin); 112 std::string key = GetCacheKey(requesting_origin, embedding_origin);
113 pmi_result_cache_.erase(key); 113 pmi_result_cache_.erase(key);
114 } 114 }
115 115
116 private: 116 private:
117 // Returns a concatenation of the origins to be used as the index. 117 // Returns a concatenation of the origins to be used as the index.
118 // Returns the empty string if either origin is invalid or empty. 118 // Returns the empty string if either origin is invalid or empty.
119 static std::string GetCacheKey(const GURL& requesting_origin, 119 static std::string GetCacheKey(const url::Origin& requesting_origin,
120 const GURL& embedding_origin) { 120 const url::Origin& embedding_origin) {
121 const std::string& requesting = requesting_origin.spec(); 121 const std::string& requesting = requesting_origin.spec();
122 const std::string& embedding = embedding_origin.spec(); 122 const std::string& embedding = embedding_origin.spec();
123 if (requesting.empty() || embedding.empty()) 123 if (requesting.empty() || embedding.empty())
124 return std::string(); 124 return std::string();
125 return requesting + "," + embedding; 125 return requesting + "," + embedding;
126 } 126 }
127 127
128 using StatusMap = base::hash_map<std::string, PermissionStatus>; 128 using StatusMap = base::hash_map<std::string, PermissionStatus>;
129 StatusMap pmi_result_cache_; 129 StatusMap pmi_result_cache_;
130 130
131 DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache); 131 DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache);
132 }; 132 };
133 133
134 struct AwPermissionManager::PendingRequest { 134 struct AwPermissionManager::PendingRequest {
135 public: 135 public:
136 PendingRequest(PermissionType permission, 136 PendingRequest(PermissionType permission,
137 GURL requesting_origin, 137 url::Origin requesting_origin,
138 GURL embedding_origin, 138 url::Origin embedding_origin,
139 content::RenderFrameHost* render_frame_host, 139 content::RenderFrameHost* render_frame_host,
140 const base::Callback<void(PermissionStatus)>& callback) 140 const base::Callback<void(PermissionStatus)>& callback)
141 : permission(permission), 141 : permission(permission),
142 requesting_origin(requesting_origin), 142 requesting_origin(requesting_origin),
143 embedding_origin(embedding_origin), 143 embedding_origin(embedding_origin),
144 render_process_id(render_frame_host->GetProcess()->GetID()), 144 render_process_id(render_frame_host->GetProcess()->GetID()),
145 render_frame_id(render_frame_host->GetRoutingID()), 145 render_frame_id(render_frame_host->GetRoutingID()),
146 callback(callback) { 146 callback(callback) {}
147 }
148 147
149 ~PendingRequest() = default; 148 ~PendingRequest() = default;
150 149
151 PermissionType permission; 150 PermissionType permission;
152 GURL requesting_origin; 151 url::Origin requesting_origin;
153 GURL embedding_origin; 152 url::Origin embedding_origin;
154 int render_process_id; 153 int render_process_id;
155 int render_frame_id; 154 int render_frame_id;
156 base::Callback<void(PermissionStatus)> callback; 155 base::Callback<void(PermissionStatus)> callback;
157 }; 156 };
158 157
159 AwPermissionManager::AwPermissionManager() 158 AwPermissionManager::AwPermissionManager()
160 : content::PermissionManager(), 159 : content::PermissionManager(),
161 result_cache_(new LastRequestResultCache), 160 result_cache_(new LastRequestResultCache),
162 weak_ptr_factory_(this) { 161 weak_ptr_factory_(this) {
163 } 162 }
164 163
165 AwPermissionManager::~AwPermissionManager() { 164 AwPermissionManager::~AwPermissionManager() {
166 } 165 }
167 166
168 int AwPermissionManager::RequestPermission( 167 int AwPermissionManager::RequestPermission(
169 PermissionType permission, 168 PermissionType permission,
170 content::RenderFrameHost* render_frame_host, 169 content::RenderFrameHost* render_frame_host,
171 const GURL& requesting_origin, 170 const url::Origin& requesting_origin,
172 const base::Callback<void(PermissionStatus)>& callback) { 171 const base::Callback<void(PermissionStatus)>& callback) {
173 int render_process_id = render_frame_host->GetProcess()->GetID(); 172 int render_process_id = render_frame_host->GetProcess()->GetID();
174 int render_frame_id = render_frame_host->GetRoutingID(); 173 int render_frame_id = render_frame_host->GetRoutingID();
175 AwBrowserPermissionRequestDelegate* delegate = 174 AwBrowserPermissionRequestDelegate* delegate =
176 AwBrowserPermissionRequestDelegate::FromID(render_process_id, 175 AwBrowserPermissionRequestDelegate::FromID(render_process_id,
177 render_frame_id); 176 render_frame_id);
178 if (!delegate) { 177 if (!delegate) {
179 DVLOG(0) << "Dropping permission request for " 178 DVLOG(0) << "Dropping permission request for "
180 << static_cast<int>(permission); 179 << static_cast<int>(permission);
181 callback.Run(content::PermissionStatus::DENIED); 180 callback.Run(content::PermissionStatus::DENIED);
182 return kNoPendingOperation; 181 return kNoPendingOperation;
183 } 182 }
184 183
185 // Do not delegate any requests which are already pending. 184 // Do not delegate any requests which are already pending.
186 bool should_delegate_request = true; 185 bool should_delegate_request = true;
187 for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_); 186 for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
188 !it.IsAtEnd(); it.Advance()) { 187 !it.IsAtEnd(); it.Advance()) {
189 if (permission == it.GetCurrentValue()->permission) { 188 if (permission == it.GetCurrentValue()->permission) {
190 should_delegate_request = false; 189 should_delegate_request = false;
191 break; 190 break;
192 } 191 }
193 } 192 }
194 193
195 const GURL& embedding_origin = 194 const url::Origin& embedding_origin =
196 content::WebContents::FromRenderFrameHost(render_frame_host) 195 content::WebContents::FromRenderFrameHost(render_frame_host)
197 ->GetLastCommittedURL().GetOrigin(); 196 ->GetLastCommittedURL()
197 .GetOrigin();
198 198
199 int request_id = kNoPendingOperation; 199 int request_id = kNoPendingOperation;
200 switch (permission) { 200 switch (permission) {
201 case PermissionType::GEOLOCATION: 201 case PermissionType::GEOLOCATION:
202 request_id = pending_requests_.Add(new PendingRequest( 202 request_id = pending_requests_.Add(new PendingRequest(
203 permission, requesting_origin, 203 permission, requesting_origin,
204 embedding_origin, render_frame_host, 204 embedding_origin, render_frame_host,
205 callback)); 205 callback));
206 if (should_delegate_request) { 206 if (should_delegate_request) {
207 delegate->RequestGeolocationPermission( 207 delegate->RequestGeolocationPermission(
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after
254 NOTREACHED() << "PermissionType::NUM was not expected here."; 254 NOTREACHED() << "PermissionType::NUM was not expected here.";
255 callback.Run(content::PermissionStatus::DENIED); 255 callback.Run(content::PermissionStatus::DENIED);
256 break; 256 break;
257 } 257 }
258 return request_id; 258 return request_id;
259 } 259 }
260 260
261 int AwPermissionManager::RequestPermissions( 261 int AwPermissionManager::RequestPermissions(
262 const std::vector<PermissionType>& permissions, 262 const std::vector<PermissionType>& permissions,
263 content::RenderFrameHost* render_frame_host, 263 content::RenderFrameHost* render_frame_host,
264 const GURL& requesting_origin, 264 const url::Origin& requesting_origin,
265 const base::Callback<void( 265 const base::Callback<void(const std::vector<PermissionStatus>&)>&
266 const std::vector<PermissionStatus>&)>& callback) { 266 callback) {
267 NOTIMPLEMENTED() << "RequestPermissions has not been implemented in WebView"; 267 NOTIMPLEMENTED() << "RequestPermissions has not been implemented in WebView";
268 268
269 std::vector<PermissionStatus> result(permissions.size()); 269 std::vector<PermissionStatus> result(permissions.size());
270 const GURL& embedding_origin = 270 const url::Origin& embedding_origin =
271 content::WebContents::FromRenderFrameHost(render_frame_host) 271 content::WebContents::FromRenderFrameHost(render_frame_host)
272 ->GetLastCommittedURL().GetOrigin(); 272 ->GetLastCommittedURL()
273 .GetOrigin();
273 274
274 for (PermissionType type : permissions) { 275 for (PermissionType type : permissions) {
275 result.push_back(GetPermissionStatus( 276 result.push_back(GetPermissionStatus(
276 type, requesting_origin, embedding_origin)); 277 type, requesting_origin, embedding_origin));
277 } 278 }
278 279
279 callback.Run(result); 280 callback.Run(result);
280 return kNoPendingOperation; 281 return kNoPendingOperation;
281 } 282 }
282 283
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
320 content::RenderFrameHost* render_frame_host = 321 content::RenderFrameHost* render_frame_host =
321 content::RenderFrameHost::FromID(pending_request->render_process_id, 322 content::RenderFrameHost::FromID(pending_request->render_process_id,
322 pending_request->render_frame_id); 323 pending_request->render_frame_id);
323 content::WebContents* web_contents = 324 content::WebContents* web_contents =
324 content::WebContents::FromRenderFrameHost(render_frame_host); 325 content::WebContents::FromRenderFrameHost(render_frame_host);
325 DCHECK(web_contents); 326 DCHECK(web_contents);
326 327
327 // The caller is canceling (presumably) the most recent request. Assuming the 328 // The caller is canceling (presumably) the most recent request. Assuming the
328 // request did not complete, the user did not respond to the requset. 329 // request did not complete, the user did not respond to the requset.
329 // Thus, assume we do not know the result. 330 // Thus, assume we do not know the result.
330 const GURL& embedding_origin = web_contents 331 const url::Origin& embedding_origin =
331 ->GetLastCommittedURL().GetOrigin(); 332 web_contents->GetLastCommittedURL().GetOrigin();
332 result_cache_->ClearResult( 333 result_cache_->ClearResult(
333 pending_request->permission, 334 pending_request->permission,
334 pending_request->requesting_origin, 335 pending_request->requesting_origin,
335 embedding_origin); 336 embedding_origin);
336 337
337 AwBrowserPermissionRequestDelegate* delegate = 338 AwBrowserPermissionRequestDelegate* delegate =
338 AwBrowserPermissionRequestDelegate::FromID( 339 AwBrowserPermissionRequestDelegate::FromID(
339 pending_request->render_process_id, 340 pending_request->render_process_id,
340 pending_request->render_frame_id); 341 pending_request->render_frame_id);
341 if (!delegate) { 342 if (!delegate) {
(...skipping 28 matching lines...) Expand all
370 break; 371 break;
371 case PermissionType::NUM: 372 case PermissionType::NUM:
372 NOTREACHED() << "PermissionType::NUM was not expected here."; 373 NOTREACHED() << "PermissionType::NUM was not expected here.";
373 break; 374 break;
374 } 375 }
375 376
376 pending_requests_.Remove(request_id); 377 pending_requests_.Remove(request_id);
377 } 378 }
378 379
379 void AwPermissionManager::ResetPermission(PermissionType permission, 380 void AwPermissionManager::ResetPermission(PermissionType permission,
380 const GURL& requesting_origin, 381 const url::Origin& requesting_origin,
381 const GURL& embedding_origin) { 382 const url::Origin& embedding_origin) {
382 result_cache_->ClearResult(permission, requesting_origin, embedding_origin); 383 result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
383 } 384 }
384 385
385 PermissionStatus AwPermissionManager::GetPermissionStatus( 386 PermissionStatus AwPermissionManager::GetPermissionStatus(
386 PermissionType permission, 387 PermissionType permission,
387 const GURL& requesting_origin, 388 const url::Origin& requesting_origin,
388 const GURL& embedding_origin) { 389 const url::Origin& embedding_origin) {
389 // Method is called outside the Permissions API only for this permission. 390 // Method is called outside the Permissions API only for this permission.
390 if (permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER) { 391 if (permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
391 return result_cache_->GetResult(permission, requesting_origin, 392 return result_cache_->GetResult(permission, requesting_origin,
392 embedding_origin); 393 embedding_origin);
393 } else if (permission == PermissionType::MIDI) { 394 } else if (permission == PermissionType::MIDI) {
394 return content::PermissionStatus::GRANTED; 395 return content::PermissionStatus::GRANTED;
395 } 396 }
396 397
397 return content::PermissionStatus::DENIED; 398 return content::PermissionStatus::DENIED;
398 } 399 }
399 400
400 void AwPermissionManager::RegisterPermissionUsage( 401 void AwPermissionManager::RegisterPermissionUsage(
401 PermissionType permission, 402 PermissionType permission,
402 const GURL& requesting_origin, 403 const url::Origin& requesting_origin,
403 const GURL& embedding_origin) { 404 const url::Origin& embedding_origin) {}
404 }
405 405
406 int AwPermissionManager::SubscribePermissionStatusChange( 406 int AwPermissionManager::SubscribePermissionStatusChange(
407 PermissionType permission, 407 PermissionType permission,
408 const GURL& requesting_origin, 408 const url::Origin& requesting_origin,
409 const GURL& embedding_origin, 409 const url::Origin& embedding_origin,
410 const base::Callback<void(PermissionStatus)>& callback) { 410 const base::Callback<void(PermissionStatus)>& callback) {
411 return kNoPendingOperation; 411 return kNoPendingOperation;
412 } 412 }
413 413
414 void AwPermissionManager::UnsubscribePermissionStatusChange( 414 void AwPermissionManager::UnsubscribePermissionStatusChange(
415 int subscription_id) { 415 int subscription_id) {
416 } 416 }
417 417
418 } // namespace android_webview 418 } // namespace android_webview
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698