mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 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. |
| 4 | |
| 5 | #include "android_webview/browser/aw_permission_manager.h" |
| 6 | |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 7 | #include <memory> |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 8 | #include <string> |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 9 | #include <utility> |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 10 | |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 11 | #include "android_webview/browser/aw_browser_permission_request_delegate.h" |
| 12 | #include "base/callback.h" |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 13 | #include "base/containers/hash_tables.h" |
| 14 | #include "base/logging.h" |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 15 | #include "content/public/browser/permission_type.h" |
mlamouri | 5fc460f | 2015-06-03 17:30:28 | [diff] [blame] | 16 | #include "content/public/browser/render_frame_host.h" |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 17 | #include "content/public/browser/render_process_host.h" |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 18 | #include "content/public/browser/web_contents.h" |
| 19 | |
mathp | cc29ae5 | 2016-05-04 15:22:17 | [diff] [blame] | 20 | using blink::mojom::PermissionStatus; |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 21 | using content::PermissionType; |
| 22 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 23 | using RequestPermissionsCallback = |
| 24 | base::Callback<void(const std::vector<PermissionStatus>&)>; |
| 25 | |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 26 | namespace android_webview { |
| 27 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 28 | namespace { |
| 29 | |
| 30 | void PermissionRequestResponseCallbackWrapper( |
| 31 | const base::Callback<void(PermissionStatus)>& callback, |
| 32 | const std::vector<PermissionStatus>& vector) { |
| 33 | DCHECK_EQ(vector.size(), 1ul); |
| 34 | callback.Run(vector[0]); |
| 35 | } |
| 36 | |
| 37 | } // namespace |
| 38 | |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 39 | class LastRequestResultCache { |
| 40 | public: |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 41 | LastRequestResultCache() = default; |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 42 | |
| 43 | void SetResult(PermissionType permission, |
| 44 | const GURL& requesting_origin, |
| 45 | const GURL& embedding_origin, |
| 46 | PermissionStatus status) { |
sammc | fcd191d | 2016-04-01 10:03:03 | [diff] [blame] | 47 | DCHECK(status == PermissionStatus::GRANTED || |
| 48 | status == PermissionStatus::DENIED); |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 49 | |
| 50 | // TODO(ddorwin): We should be denying empty origins at a higher level. |
| 51 | if (requesting_origin.is_empty() || embedding_origin.is_empty()) { |
| 52 | DLOG(WARNING) << "Not caching result because of empty origin."; |
| 53 | return; |
| 54 | } |
| 55 | |
| 56 | if (!requesting_origin.is_valid()) { |
| 57 | NOTREACHED() << requesting_origin.possibly_invalid_spec(); |
| 58 | return; |
| 59 | } |
| 60 | if (!embedding_origin.is_valid()) { |
| 61 | NOTREACHED() << embedding_origin.possibly_invalid_spec(); |
| 62 | return; |
| 63 | } |
| 64 | |
| 65 | if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) { |
| 66 | // Other permissions are not cached. |
| 67 | return; |
| 68 | } |
| 69 | |
| 70 | std::string key = GetCacheKey(requesting_origin, embedding_origin); |
| 71 | if (key.empty()) { |
| 72 | NOTREACHED(); |
| 73 | // Never store an empty key because it could inadvertently be used for |
| 74 | // another combination. |
| 75 | return; |
| 76 | } |
| 77 | pmi_result_cache_[key] = status; |
| 78 | } |
| 79 | |
| 80 | PermissionStatus GetResult(PermissionType permission, |
| 81 | const GURL& requesting_origin, |
| 82 | const GURL& embedding_origin) const { |
| 83 | // TODO(ddorwin): We should be denying empty origins at a higher level. |
| 84 | if (requesting_origin.is_empty() || embedding_origin.is_empty()) { |
sammc | fcd191d | 2016-04-01 10:03:03 | [diff] [blame] | 85 | return PermissionStatus::ASK; |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 86 | } |
| 87 | |
| 88 | DCHECK(requesting_origin.is_valid()) |
| 89 | << requesting_origin.possibly_invalid_spec(); |
| 90 | DCHECK(embedding_origin.is_valid()) |
| 91 | << embedding_origin.possibly_invalid_spec(); |
| 92 | |
| 93 | if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) { |
| 94 | NOTREACHED() << "Results are only cached for PROTECTED_MEDIA_IDENTIFIER"; |
sammc | fcd191d | 2016-04-01 10:03:03 | [diff] [blame] | 95 | return PermissionStatus::ASK; |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 96 | } |
| 97 | |
| 98 | std::string key = GetCacheKey(requesting_origin, embedding_origin); |
| 99 | StatusMap::const_iterator it = pmi_result_cache_.find(key); |
| 100 | if (it == pmi_result_cache_.end()) { |
| 101 | DLOG(WARNING) << "GetResult() called for uncached origins: " << key; |
sammc | fcd191d | 2016-04-01 10:03:03 | [diff] [blame] | 102 | return PermissionStatus::ASK; |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 103 | } |
| 104 | |
| 105 | DCHECK(!key.empty()); |
| 106 | return it->second; |
| 107 | } |
| 108 | |
| 109 | void ClearResult(PermissionType permission, |
| 110 | const GURL& requesting_origin, |
| 111 | const GURL& embedding_origin) { |
| 112 | // TODO(ddorwin): We should be denying empty origins at a higher level. |
| 113 | if (requesting_origin.is_empty() || embedding_origin.is_empty()) { |
| 114 | return; |
| 115 | } |
| 116 | |
| 117 | DCHECK(requesting_origin.is_valid()) |
| 118 | << requesting_origin.possibly_invalid_spec(); |
| 119 | DCHECK(embedding_origin.is_valid()) |
| 120 | << embedding_origin.possibly_invalid_spec(); |
| 121 | |
| 122 | |
| 123 | if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) { |
| 124 | // Other permissions are not cached, so nothing to clear. |
| 125 | return; |
| 126 | } |
| 127 | |
| 128 | std::string key = GetCacheKey(requesting_origin, embedding_origin); |
| 129 | pmi_result_cache_.erase(key); |
| 130 | } |
| 131 | |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 132 | private: |
| 133 | // Returns a concatenation of the origins to be used as the index. |
| 134 | // Returns the empty string if either origin is invalid or empty. |
| 135 | static std::string GetCacheKey(const GURL& requesting_origin, |
| 136 | const GURL& embedding_origin) { |
| 137 | const std::string& requesting = requesting_origin.spec(); |
| 138 | const std::string& embedding = embedding_origin.spec(); |
| 139 | if (requesting.empty() || embedding.empty()) |
| 140 | return std::string(); |
| 141 | return requesting + "," + embedding; |
| 142 | } |
| 143 | |
| 144 | using StatusMap = base::hash_map<std::string, PermissionStatus>; |
| 145 | StatusMap pmi_result_cache_; |
| 146 | |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 147 | DISALLOW_COPY_AND_ASSIGN(LastRequestResultCache); |
| 148 | }; |
| 149 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 150 | class AwPermissionManager::PendingRequest { |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 151 | public: |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 152 | PendingRequest(const std::vector<PermissionType> permissions, |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 153 | GURL requesting_origin, |
| 154 | GURL embedding_origin, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 155 | int render_process_id, |
| 156 | int render_frame_id, |
| 157 | const RequestPermissionsCallback callback) |
| 158 | : permissions(permissions), |
| 159 | requesting_origin(requesting_origin), |
| 160 | embedding_origin(embedding_origin), |
| 161 | render_process_id(render_process_id), |
| 162 | render_frame_id(render_frame_id), |
| 163 | callback(callback), |
| 164 | results(permissions.size(), PermissionStatus::DENIED), |
| 165 | cancelled_(false) { |
| 166 | for (size_t i = 0; i < permissions.size(); ++i) |
| 167 | permission_index_map_.insert(std::make_pair(permissions[i], i)); |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 168 | } |
| 169 | |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 170 | ~PendingRequest() = default; |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 171 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 172 | void SetPermissionStatus(PermissionType type, PermissionStatus status) { |
| 173 | auto result = permission_index_map_.find(type); |
| 174 | if (result == permission_index_map_.end()) { |
| 175 | NOTREACHED(); |
| 176 | return; |
| 177 | } |
| 178 | DCHECK(!IsCompleted()); |
| 179 | results[result->second] = status; |
| 180 | resolved_permissions_.insert(type); |
| 181 | } |
| 182 | |
| 183 | PermissionStatus GetPermissionStatus(PermissionType type) { |
| 184 | auto result = permission_index_map_.find(type); |
| 185 | if (result == permission_index_map_.end()) { |
| 186 | NOTREACHED(); |
| 187 | return PermissionStatus::DENIED; |
| 188 | } |
| 189 | return results[result->second]; |
| 190 | } |
| 191 | |
| 192 | bool HasPermissionType(PermissionType type) { |
| 193 | return permission_index_map_.find(type) != permission_index_map_.end(); |
| 194 | } |
| 195 | |
| 196 | bool IsCompleted() const { |
| 197 | return results.size() == resolved_permissions_.size(); |
| 198 | } |
| 199 | |
| 200 | bool IsCompleted(PermissionType type) const { |
| 201 | return resolved_permissions_.count(type) != 0; |
| 202 | } |
| 203 | |
| 204 | void Cancel() { cancelled_ = true; } |
| 205 | |
| 206 | bool IsCancelled() const { return cancelled_; } |
| 207 | |
| 208 | std::vector<PermissionType> permissions; |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 209 | GURL requesting_origin; |
| 210 | GURL embedding_origin; |
| 211 | int render_process_id; |
| 212 | int render_frame_id; |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 213 | RequestPermissionsCallback callback; |
| 214 | std::vector<PermissionStatus> results; |
| 215 | |
| 216 | private: |
| 217 | std::map<PermissionType, size_t> permission_index_map_; |
| 218 | std::set<PermissionType> resolved_permissions_; |
| 219 | bool cancelled_; |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 220 | }; |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 221 | |
| 222 | AwPermissionManager::AwPermissionManager() |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 223 | : content::PermissionManager(), |
| 224 | result_cache_(new LastRequestResultCache), |
| 225 | weak_ptr_factory_(this) { |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 226 | } |
| 227 | |
| 228 | AwPermissionManager::~AwPermissionManager() { |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 229 | CancelPermissionRequests(); |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 230 | } |
| 231 | |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 232 | int AwPermissionManager::RequestPermission( |
ddorwin | 5e77de58 | 2015-05-29 23:49:57 | [diff] [blame] | 233 | PermissionType permission, |
mlamouri | 5fc460f | 2015-06-03 17:30:28 | [diff] [blame] | 234 | content::RenderFrameHost* render_frame_host, |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 235 | const GURL& requesting_origin, |
benwells | fd2b155 | 2016-07-05 04:26:53 | [diff] [blame] | 236 | bool user_gesture, |
ddorwin | 5e77de58 | 2015-05-29 23:49:57 | [diff] [blame] | 237 | const base::Callback<void(PermissionStatus)>& callback) { |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 238 | return RequestPermissions( |
| 239 | std::vector<PermissionType>(1, permission), render_frame_host, |
| 240 | requesting_origin, user_gesture, |
| 241 | base::Bind(&PermissionRequestResponseCallbackWrapper, callback)); |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 242 | } |
| 243 | |
mlamouri | 8b5ec90 | 2015-10-24 00:52:03 | [diff] [blame] | 244 | int AwPermissionManager::RequestPermissions( |
| 245 | const std::vector<PermissionType>& permissions, |
| 246 | content::RenderFrameHost* render_frame_host, |
| 247 | const GURL& requesting_origin, |
benwells | fd2b155 | 2016-07-05 04:26:53 | [diff] [blame] | 248 | bool user_gesture, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 249 | const base::Callback<void(const std::vector<PermissionStatus>&)>& |
| 250 | callback) { |
| 251 | if (permissions.empty()) { |
| 252 | callback.Run(std::vector<PermissionStatus>()); |
| 253 | return kNoPendingOperation; |
mlamouri | 8b5ec90 | 2015-10-24 00:52:03 | [diff] [blame] | 254 | } |
| 255 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 256 | const GURL& embedding_origin = LastCommittedOrigin(render_frame_host); |
| 257 | |
Gyuyoung Kim | dae5f10 | 2017-12-04 15:55:38 | [diff] [blame] | 258 | auto pending_request = std::make_unique<PendingRequest>( |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 259 | permissions, requesting_origin, embedding_origin, |
| 260 | GetRenderProcessID(render_frame_host), |
| 261 | GetRenderFrameID(render_frame_host), callback); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 262 | std::vector<bool> should_delegate_requests = |
| 263 | std::vector<bool>(permissions.size(), true); |
| 264 | for (size_t i = 0; i < permissions.size(); ++i) { |
| 265 | for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_); |
| 266 | !it.IsAtEnd(); it.Advance()) { |
| 267 | if (it.GetCurrentValue()->HasPermissionType(permissions[i]) && |
| 268 | it.GetCurrentValue()->requesting_origin == requesting_origin) { |
| 269 | if (it.GetCurrentValue()->IsCompleted(permissions[i])) { |
| 270 | pending_request->SetPermissionStatus( |
| 271 | permissions[i], |
| 272 | it.GetCurrentValue()->GetPermissionStatus(permissions[i])); |
| 273 | } |
| 274 | should_delegate_requests[i] = false; |
| 275 | break; |
| 276 | } |
| 277 | } |
| 278 | } |
| 279 | |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 280 | // Keep copy of pointer for performing further operations after ownership is |
| 281 | // transferred to pending_requests_ |
| 282 | PendingRequest* pending_request_raw = pending_request.get(); |
| 283 | int request_id = pending_requests_.Add(std::move(pending_request)); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 284 | |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 285 | AwBrowserPermissionRequestDelegate* delegate = |
| 286 | GetDelegate(pending_request_raw->render_process_id, |
| 287 | pending_request_raw->render_frame_id); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 288 | |
| 289 | for (size_t i = 0; i < permissions.size(); ++i) { |
| 290 | if (!should_delegate_requests[i]) |
| 291 | continue; |
| 292 | |
| 293 | if (!delegate) { |
| 294 | DVLOG(0) << "Dropping permissions request for " |
| 295 | << static_cast<int>(permissions[i]); |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 296 | pending_request_raw->SetPermissionStatus(permissions[i], |
| 297 | PermissionStatus::DENIED); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 298 | continue; |
| 299 | } |
| 300 | |
| 301 | switch (permissions[i]) { |
| 302 | case PermissionType::GEOLOCATION: |
| 303 | delegate->RequestGeolocationPermission( |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 304 | pending_request_raw->requesting_origin, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 305 | base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(), |
| 306 | request_id, permissions[i])); |
| 307 | break; |
| 308 | case PermissionType::PROTECTED_MEDIA_IDENTIFIER: |
| 309 | delegate->RequestProtectedMediaIdentifierPermission( |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 310 | pending_request_raw->requesting_origin, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 311 | base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(), |
| 312 | request_id, permissions[i])); |
| 313 | break; |
| 314 | case PermissionType::MIDI_SYSEX: |
| 315 | delegate->RequestMIDISysexPermission( |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 316 | pending_request_raw->requesting_origin, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 317 | base::Bind(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(), |
| 318 | request_id, permissions[i])); |
| 319 | break; |
| 320 | case PermissionType::AUDIO_CAPTURE: |
| 321 | case PermissionType::VIDEO_CAPTURE: |
| 322 | case PermissionType::NOTIFICATIONS: |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 323 | case PermissionType::DURABLE_STORAGE: |
| 324 | case PermissionType::BACKGROUND_SYNC: |
rijubrata.bhaumik | 7b072ad | 2017-08-02 07:49:29 | [diff] [blame] | 325 | case PermissionType::SENSORS: |
raymes | 086f762 | 2016-09-22 03:53:14 | [diff] [blame] | 326 | case PermissionType::FLASH: |
Dominic Mazzoni | 7b82a6d | 2017-08-30 04:52:26 | [diff] [blame] | 327 | case PermissionType::ACCESSIBILITY_EVENTS: |
Gary Kacmarcik | 726325ee | 2017-11-17 07:12:08 | [diff] [blame] | 328 | case PermissionType::CLIPBOARD_READ: |
| 329 | case PermissionType::CLIPBOARD_WRITE: |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 330 | NOTIMPLEMENTED() << "RequestPermissions is not implemented for " |
| 331 | << static_cast<int>(permissions[i]); |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 332 | pending_request_raw->SetPermissionStatus(permissions[i], |
| 333 | PermissionStatus::DENIED); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 334 | break; |
| 335 | case PermissionType::MIDI: |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 336 | pending_request_raw->SetPermissionStatus(permissions[i], |
| 337 | PermissionStatus::GRANTED); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 338 | break; |
| 339 | case PermissionType::NUM: |
| 340 | NOTREACHED() << "PermissionType::NUM was not expected here."; |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 341 | pending_request_raw->SetPermissionStatus(permissions[i], |
| 342 | PermissionStatus::DENIED); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 343 | break; |
| 344 | } |
| 345 | } |
| 346 | |
| 347 | // If delegate resolve the permission synchronously, all requests could be |
| 348 | // already resolved here. |
| 349 | if (!pending_requests_.Lookup(request_id)) |
| 350 | return kNoPendingOperation; |
| 351 | |
| 352 | // If requests are resolved without calling delegate functions, e.g. |
| 353 | // PermissionType::MIDI is permitted within the previous for-loop, all |
| 354 | // requests could be already resolved, but still in the |pending_requests_| |
| 355 | // without invoking the callback. |
rlanday | 6eada032 | 2016-11-30 18:59:30 | [diff] [blame] | 356 | if (pending_request_raw->IsCompleted()) { |
| 357 | std::vector<PermissionStatus> results = pending_request_raw->results; |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 358 | pending_requests_.Remove(request_id); |
| 359 | callback.Run(results); |
| 360 | return kNoPendingOperation; |
| 361 | } |
| 362 | |
| 363 | return request_id; |
mlamouri | 8b5ec90 | 2015-10-24 00:52:03 | [diff] [blame] | 364 | } |
| 365 | |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 366 | // static |
| 367 | void AwPermissionManager::OnRequestResponse( |
| 368 | const base::WeakPtr<AwPermissionManager>& manager, |
| 369 | int request_id, |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 370 | PermissionType permission, |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 371 | bool allowed) { |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 372 | // All delegate functions should be cancelled when the manager runs |
| 373 | // destructor. Therefore |manager| should be always valid here. |
| 374 | DCHECK(manager); |
| 375 | |
sammc | fcd191d | 2016-04-01 10:03:03 | [diff] [blame] | 376 | PermissionStatus status = |
| 377 | allowed ? PermissionStatus::GRANTED : PermissionStatus::DENIED; |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 378 | PendingRequest* pending_request = |
| 379 | manager->pending_requests_.Lookup(request_id); |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 380 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 381 | manager->result_cache_->SetResult(permission, |
| 382 | pending_request->requesting_origin, |
| 383 | pending_request->embedding_origin, status); |
| 384 | |
| 385 | std::vector<int> complete_request_ids; |
| 386 | std::vector<std::pair<const RequestPermissionsCallback, |
| 387 | std::vector<PermissionStatus>>> |
| 388 | complete_request_pairs; |
| 389 | for (PendingRequestsMap::Iterator<PendingRequest> it( |
| 390 | &manager->pending_requests_); |
| 391 | !it.IsAtEnd(); it.Advance()) { |
| 392 | if (!it.GetCurrentValue()->HasPermissionType(permission) || |
| 393 | it.GetCurrentValue()->requesting_origin != |
| 394 | pending_request->requesting_origin) { |
| 395 | continue; |
| 396 | } |
| 397 | it.GetCurrentValue()->SetPermissionStatus(permission, status); |
| 398 | if (it.GetCurrentValue()->IsCompleted()) { |
| 399 | complete_request_ids.push_back(it.GetCurrentKey()); |
| 400 | if (!it.GetCurrentValue()->IsCancelled()) { |
| 401 | complete_request_pairs.push_back(std::make_pair( |
| 402 | it.GetCurrentValue()->callback, it.GetCurrentValue()->results)); |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 403 | } |
| 404 | } |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 405 | } |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 406 | for (auto id : complete_request_ids) |
| 407 | manager->pending_requests_.Remove(id); |
| 408 | for (auto pair : complete_request_pairs) |
| 409 | pair.first.Run(pair.second); |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 410 | } |
| 411 | |
Raymes Khoury | 5bf2b08 | 2018-01-28 23:32:16 | [diff] [blame] | 412 | void AwPermissionManager::ResetPermission(PermissionType permission, |
| 413 | const GURL& requesting_origin, |
| 414 | const GURL& embedding_origin) { |
| 415 | result_cache_->ClearResult(permission, requesting_origin, embedding_origin); |
| 416 | } |
| 417 | |
| 418 | PermissionStatus AwPermissionManager::GetPermissionStatus( |
| 419 | PermissionType permission, |
| 420 | const GURL& requesting_origin, |
| 421 | const GURL& embedding_origin) { |
| 422 | // Method is called outside the Permissions API only for this permission. |
| 423 | if (permission == PermissionType::PROTECTED_MEDIA_IDENTIFIER) { |
| 424 | return result_cache_->GetResult(permission, requesting_origin, |
| 425 | embedding_origin); |
| 426 | } else if (permission == PermissionType::MIDI || |
| 427 | permission == PermissionType::SENSORS) { |
| 428 | return PermissionStatus::GRANTED; |
| 429 | } |
| 430 | |
| 431 | return PermissionStatus::DENIED; |
| 432 | } |
| 433 | |
| 434 | int AwPermissionManager::SubscribePermissionStatusChange( |
| 435 | PermissionType permission, |
| 436 | const GURL& requesting_origin, |
| 437 | const GURL& embedding_origin, |
| 438 | const base::Callback<void(PermissionStatus)>& callback) { |
| 439 | return kNoPendingOperation; |
| 440 | } |
| 441 | |
| 442 | void AwPermissionManager::UnsubscribePermissionStatusChange( |
| 443 | int subscription_id) {} |
| 444 | |
lalitm | 5bd7eb04 | 2015-10-02 16:00:29 | [diff] [blame] | 445 | void AwPermissionManager::CancelPermissionRequest(int request_id) { |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 446 | PendingRequest* pending_request = pending_requests_.Lookup(request_id); |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 447 | if (!pending_request || pending_request->IsCancelled()) |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 448 | return; |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 449 | pending_request->Cancel(); |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 450 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 451 | const GURL& embedding_origin = pending_request->embedding_origin; |
| 452 | const GURL& requesting_origin = pending_request->requesting_origin; |
| 453 | for (auto permission : pending_request->permissions) |
| 454 | result_cache_->ClearResult(permission, requesting_origin, embedding_origin); |
lalitm | 5bd7eb04 | 2015-10-02 16:00:29 | [diff] [blame] | 455 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 456 | AwBrowserPermissionRequestDelegate* delegate = GetDelegate( |
| 457 | pending_request->render_process_id, pending_request->render_frame_id); |
ddorwin | 9774ee89 | 2015-05-29 20:08:56 | [diff] [blame] | 458 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 459 | for (auto permission : pending_request->permissions) { |
| 460 | // If the permission was already resolved, we do not need to cancel it. |
| 461 | if (pending_request->IsCompleted(permission)) |
| 462 | continue; |
| 463 | |
| 464 | // If another pending_request waits for the same permission being resolved, |
| 465 | // we should not cancel the delegate's request. |
| 466 | bool should_not_cancel_ = false; |
| 467 | for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_); |
| 468 | !it.IsAtEnd(); it.Advance()) { |
| 469 | if (it.GetCurrentValue() != pending_request && |
| 470 | it.GetCurrentValue()->HasPermissionType(permission) && |
| 471 | it.GetCurrentValue()->requesting_origin == requesting_origin && |
| 472 | !it.GetCurrentValue()->IsCompleted(permission)) { |
| 473 | should_not_cancel_ = true; |
| 474 | break; |
| 475 | } |
| 476 | } |
| 477 | if (should_not_cancel_) |
| 478 | continue; |
| 479 | |
| 480 | switch (permission) { |
| 481 | case PermissionType::GEOLOCATION: |
| 482 | if (delegate) |
| 483 | delegate->CancelGeolocationPermissionRequests(requesting_origin); |
| 484 | break; |
| 485 | case PermissionType::PROTECTED_MEDIA_IDENTIFIER: |
| 486 | if (delegate) |
| 487 | delegate->CancelProtectedMediaIdentifierPermissionRequests( |
| 488 | requesting_origin); |
| 489 | break; |
| 490 | case PermissionType::MIDI_SYSEX: |
| 491 | if (delegate) |
| 492 | delegate->CancelMIDISysexPermissionRequests(requesting_origin); |
| 493 | break; |
| 494 | case PermissionType::NOTIFICATIONS: |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 495 | case PermissionType::DURABLE_STORAGE: |
| 496 | case PermissionType::AUDIO_CAPTURE: |
| 497 | case PermissionType::VIDEO_CAPTURE: |
| 498 | case PermissionType::BACKGROUND_SYNC: |
rijubrata.bhaumik | 7b072ad | 2017-08-02 07:49:29 | [diff] [blame] | 499 | case PermissionType::SENSORS: |
raymes | 086f762 | 2016-09-22 03:53:14 | [diff] [blame] | 500 | case PermissionType::FLASH: |
Dominic Mazzoni | 7b82a6d | 2017-08-30 04:52:26 | [diff] [blame] | 501 | case PermissionType::ACCESSIBILITY_EVENTS: |
Gary Kacmarcik | 726325ee | 2017-11-17 07:12:08 | [diff] [blame] | 502 | case PermissionType::CLIPBOARD_READ: |
| 503 | case PermissionType::CLIPBOARD_WRITE: |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 504 | NOTIMPLEMENTED() << "CancelPermission not implemented for " |
| 505 | << static_cast<int>(permission); |
| 506 | break; |
| 507 | case PermissionType::MIDI: |
| 508 | // There is nothing to cancel so this is simply ignored. |
| 509 | break; |
| 510 | case PermissionType::NUM: |
| 511 | NOTREACHED() << "PermissionType::NUM was not expected here."; |
| 512 | break; |
| 513 | } |
| 514 | pending_request->SetPermissionStatus(permission, PermissionStatus::DENIED); |
| 515 | } |
| 516 | |
| 517 | // If there are still active requests, we should not remove request_id here, |
| 518 | // but just do not invoke a relevant callback when the request is resolved in |
| 519 | // OnRequestResponse(). |
| 520 | if (pending_request->IsCompleted()) |
lalitm | 27583e9 | 2015-10-02 11:34:17 | [diff] [blame] | 521 | pending_requests_.Remove(request_id); |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 522 | } |
| 523 | |
toyoshim | 055d3a21 | 2016-07-28 10:47:41 | [diff] [blame] | 524 | void AwPermissionManager::CancelPermissionRequests() { |
| 525 | std::vector<int> request_ids; |
| 526 | for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_); |
| 527 | !it.IsAtEnd(); it.Advance()) { |
| 528 | request_ids.push_back(it.GetCurrentKey()); |
| 529 | } |
| 530 | for (auto request_id : request_ids) |
| 531 | CancelPermissionRequest(request_id); |
| 532 | DCHECK(pending_requests_.IsEmpty()); |
| 533 | } |
| 534 | |
| 535 | int AwPermissionManager::GetRenderProcessID( |
| 536 | content::RenderFrameHost* render_frame_host) { |
| 537 | return render_frame_host->GetProcess()->GetID(); |
| 538 | } |
| 539 | |
| 540 | int AwPermissionManager::GetRenderFrameID( |
| 541 | content::RenderFrameHost* render_frame_host) { |
| 542 | return render_frame_host->GetRoutingID(); |
| 543 | } |
| 544 | |
| 545 | GURL AwPermissionManager::LastCommittedOrigin( |
| 546 | content::RenderFrameHost* render_frame_host) { |
| 547 | return content::WebContents::FromRenderFrameHost(render_frame_host) |
| 548 | ->GetLastCommittedURL().GetOrigin(); |
| 549 | } |
| 550 | |
| 551 | AwBrowserPermissionRequestDelegate* AwPermissionManager::GetDelegate( |
| 552 | int render_process_id, int render_frame_id) { |
| 553 | return AwBrowserPermissionRequestDelegate::FromID(render_process_id, |
| 554 | render_frame_id); |
| 555 | } |
| 556 | |
mlamouri | 4e37202 | 2015-03-29 14:51:06 | [diff] [blame] | 557 | } // namespace android_webview |