#include "android_webview/browser/aw_permission_manager.h"
#include <memory>
#include <string>
#include <unordered_map>
#include <utility>
#include "android_webview/browser/aw_browser_permission_request_delegate.h"
#include "android_webview/browser/aw_contents.h"
#include "android_webview/browser/aw_context_permissions_delegate.h"
#include "android_webview/browser/aw_settings.h"
#include "android_webview/common/aw_features.h"
#include "base/check.h"
#include "base/containers/contains.h"
#include "base/functional/bind.h"
#include "base/functional/callback.h"
#include "base/logging.h"
#include "base/notimplemented.h"
#include "base/notreached.h"
#include "base/sequence_checker.h"
#include "base/task/thread_pool.h"
#include "components/permissions/permission_manager.h"
#include "components/permissions/permission_util.h"
#include "content/public/browser/child_process_security_policy.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_result.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "third_party/blink/public/common/features.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
using blink::PermissionType;
using blink::mojom::PermissionStatus;
using RequestPermissionsCallback =
base::OnceCallback<void(const std::vector<content::PermissionResult>&)>;
namespace android_webview {
class LastRequestResultCache {
public:
LastRequestResultCache() = default;
LastRequestResultCache(const LastRequestResultCache&) = delete;
LastRequestResultCache& operator=(const LastRequestResultCache&) = delete;
void SetResult(PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin,
PermissionStatus status) {
DCHECK(status == PermissionStatus::GRANTED ||
status == PermissionStatus::DENIED);
if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
DLOG(WARNING) << "Not caching result because of empty origin.";
return;
}
if (!requesting_origin.is_valid()) {
NOTREACHED() << requesting_origin.possibly_invalid_spec();
}
if (!embedding_origin.is_valid()) {
NOTREACHED() << embedding_origin.possibly_invalid_spec();
}
switch (permission) {
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
case PermissionType::TOP_LEVEL_STORAGE_ACCESS:
break;
default:
return;
}
std::string key = GetCacheKey(requesting_origin, embedding_origin);
CHECK(!key.empty());
pmi_result_cache_[key] = status;
}
PermissionStatus GetResult(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
const GURL& requesting_origin,
const GURL& embedding_origin) const {
if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
return PermissionStatus::ASK;
}
DCHECK(requesting_origin.is_valid())
<< requesting_origin.possibly_invalid_spec();
DCHECK(embedding_origin.is_valid())
<< embedding_origin.possibly_invalid_spec();
const PermissionType permission =
blink::PermissionDescriptorToPermissionType(permission_descriptor);
switch (permission) {
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
case PermissionType::TOP_LEVEL_STORAGE_ACCESS:
break;
default:
NOTREACHED()
<< "Results are only cached for PROTECTED_MEDIA_IDENTIFIER";
}
std::string key = GetCacheKey(requesting_origin, embedding_origin);
StatusMap::const_iterator it = pmi_result_cache_.find(key);
if (it == pmi_result_cache_.end()) {
DLOG(WARNING) << "GetResult() called for uncached origins: " << key;
return PermissionStatus::ASK;
}
DCHECK(!key.empty());
return it->second;
}
void ClearResult(PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {
if (requesting_origin.is_empty() || embedding_origin.is_empty()) {
return;
}
DCHECK(requesting_origin.is_valid())
<< requesting_origin.possibly_invalid_spec();
DCHECK(embedding_origin.is_valid())
<< embedding_origin.possibly_invalid_spec();
if (permission != PermissionType::PROTECTED_MEDIA_IDENTIFIER) {
return;
}
std::string key = GetCacheKey(requesting_origin, embedding_origin);
pmi_result_cache_.erase(key);
}
private:
static std::string GetCacheKey(const GURL& requesting_origin,
const GURL& embedding_origin) {
const std::string& requesting = requesting_origin.spec();
const std::string& embedding = embedding_origin.spec();
if (requesting.empty() || embedding.empty())
return std::string();
return requesting + "," + embedding;
}
using StatusMap = std::unordered_map<std::string, PermissionStatus>;
StatusMap pmi_result_cache_;
};
class AwPermissionManager::PendingRequest {
public:
PendingRequest(const std::vector<PermissionType>& permissions,
GURL requesting_origin,
GURL embedding_origin,
int render_process_id,
int render_frame_id,
RequestPermissionsCallback callback)
: permissions(permissions),
requesting_origin(requesting_origin),
embedding_origin(embedding_origin),
render_process_id(render_process_id),
render_frame_id(render_frame_id),
callback(std::move(callback)),
results(permissions.size(),
content::PermissionResult(PermissionStatus::DENIED)),
cancelled_(false) {
for (size_t i = 0; i < permissions.size(); ++i) {
permission_index_map_.insert(std::make_pair(permissions[i], i));
}
}
~PendingRequest() = default;
void SetPermissionResult(PermissionType type,
content::PermissionResult permission_result) {
auto result = permission_index_map_.find(type);
if (result == permission_index_map_.end()) {
NOTREACHED();
}
DCHECK(!IsCompleted());
results[result->second] = permission_result;
if (base::FeatureList::IsEnabled(blink::features::kBlockMidiByDefault)) {
if (type == PermissionType::MIDI &&
permission_result.status == PermissionStatus::GRANTED) {
content::ChildProcessSecurityPolicy::GetInstance()
->GrantSendMidiMessage(render_process_id);
}
}
if (type == PermissionType::MIDI_SYSEX &&
permission_result.status == PermissionStatus::GRANTED) {
content::ChildProcessSecurityPolicy::GetInstance()
->GrantSendMidiSysExMessage(render_process_id);
}
resolved_permissions_.insert(type);
}
content::PermissionResult GetPermissionResult(PermissionType type) {
auto result = permission_index_map_.find(type);
if (result == permission_index_map_.end()) {
NOTREACHED();
}
return results[result->second];
}
bool HasPermissionType(PermissionType type) {
return base::Contains(permission_index_map_, type);
}
bool IsCompleted() const {
return results.size() == resolved_permissions_.size();
}
bool IsCompleted(PermissionType type) const {
return resolved_permissions_.count(type) != 0;
}
void Cancel() { cancelled_ = true; }
bool IsCancelled() const { return cancelled_; }
std::vector<PermissionType> permissions;
GURL requesting_origin;
GURL embedding_origin;
int render_process_id;
int render_frame_id;
RequestPermissionsCallback callback;
std::vector<content::PermissionResult> results;
private:
std::map<PermissionType, size_t> permission_index_map_;
std::set<PermissionType> resolved_permissions_;
bool cancelled_;
};
AwPermissionManager::AwPermissionManager(
const AwContextPermissionsDelegate& context_delegate)
: context_delegate_(context_delegate),
result_cache_(new LastRequestResultCache) {}
AwPermissionManager::~AwPermissionManager() {
CancelPermissionRequests();
}
void AwPermissionManager::RequestPermissions(
content::RenderFrameHost* render_frame_host,
const content::PermissionRequestDescription& request_description,
base::OnceCallback<void(const std::vector<content::PermissionResult>&)>
callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
auto const& permissions = blink::PermissionDescriptorToPermissionTypes(
request_description.permissions);
if (permissions.empty()) {
std::move(callback).Run(std::vector<content::PermissionResult>());
return;
}
const GURL& embedding_origin = LastCommittedMainOrigin(render_frame_host);
const GURL& requesting_origin = request_description.requesting_origin;
auto pending_request = std::make_unique<PendingRequest>(
permissions, requesting_origin, embedding_origin,
GetRenderProcessID(render_frame_host),
GetRenderFrameID(render_frame_host), std::move(callback));
std::vector<bool> should_delegate_requests =
std::vector<bool>(permissions.size(), true);
for (size_t i = 0; i < permissions.size(); ++i) {
for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
!it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue()->HasPermissionType(permissions[i]) &&
it.GetCurrentValue()->requesting_origin == requesting_origin) {
if (it.GetCurrentValue()->IsCompleted(permissions[i])) {
pending_request->SetPermissionResult(
permissions[i],
it.GetCurrentValue()->GetPermissionResult(permissions[i]));
}
should_delegate_requests[i] = false;
break;
}
}
}
PendingRequest* pending_request_raw = pending_request.get();
const int request_id = pending_requests_.Add(std::move(pending_request));
AwBrowserPermissionRequestDelegate* delegate =
GetDelegate(pending_request_raw->render_process_id,
pending_request_raw->render_frame_id);
for (size_t i = 0; i < permissions.size(); ++i) {
if (!should_delegate_requests[i])
continue;
if (!delegate) {
DVLOG(0) << "Dropping permissions request for "
<< static_cast<int>(permissions[i]);
pending_request_raw->SetPermissionResult(
permissions[i], content::PermissionResult(PermissionStatus::DENIED));
continue;
}
switch (permissions[i]) {
case PermissionType::GEOLOCATION:
delegate->RequestGeolocationPermission(
pending_request_raw->requesting_origin,
base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
request_id, permissions[i]));
break;
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
delegate->RequestProtectedMediaIdentifierPermission(
pending_request_raw->requesting_origin,
base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
request_id, permissions[i]));
break;
case PermissionType::MIDI_SYSEX:
delegate->RequestMIDISysexPermission(
pending_request_raw->requesting_origin,
base::BindOnce(&OnRequestResponse, weak_ptr_factory_.GetWeakPtr(),
request_id, permissions[i]));
break;
case PermissionType::CLIPBOARD_SANITIZED_WRITE:
pending_request_raw->SetPermissionResult(
permissions[i],
content::PermissionResult(PermissionStatus::GRANTED));
break;
case PermissionType::AUDIO_CAPTURE:
case PermissionType::VIDEO_CAPTURE:
case PermissionType::NOTIFICATIONS:
case PermissionType::DURABLE_STORAGE:
case PermissionType::BACKGROUND_SYNC:
case PermissionType::CLIPBOARD_READ_WRITE:
case PermissionType::PAYMENT_HANDLER:
case PermissionType::BACKGROUND_FETCH:
case PermissionType::IDLE_DETECTION:
case PermissionType::PERIODIC_BACKGROUND_SYNC:
case PermissionType::NFC:
case PermissionType::VR:
case PermissionType::AR:
case PermissionType::HAND_TRACKING:
case PermissionType::CAMERA_PAN_TILT_ZOOM:
case PermissionType::WINDOW_MANAGEMENT:
case PermissionType::LOCAL_FONTS:
case PermissionType::DISPLAY_CAPTURE:
case PermissionType::CAPTURED_SURFACE_CONTROL:
case PermissionType::SMART_CARD:
case PermissionType::WEB_PRINTING:
case PermissionType::SPEAKER_SELECTION:
case PermissionType::KEYBOARD_LOCK:
case PermissionType::POINTER_LOCK:
case PermissionType::AUTOMATIC_FULLSCREEN:
case PermissionType::WEB_APP_INSTALLATION:
case PermissionType::STORAGE_ACCESS_GRANT:
case PermissionType::TOP_LEVEL_STORAGE_ACCESS:
NOTIMPLEMENTED() << "RequestPermissions is not implemented for "
<< static_cast<int>(permissions[i]);
pending_request_raw->SetPermissionResult(
permissions[i],
content::PermissionResult(PermissionStatus::DENIED));
break;
case PermissionType::MIDI:
case PermissionType::SENSORS:
case PermissionType::WAKE_LOCK_SCREEN:
pending_request_raw->SetPermissionResult(
permissions[i],
content::PermissionResult(PermissionStatus::GRANTED));
break;
case PermissionType::WAKE_LOCK_SYSTEM:
pending_request_raw->SetPermissionResult(
permissions[i],
content::PermissionResult(PermissionStatus::DENIED));
break;
case PermissionType::LOCAL_NETWORK_ACCESS:
pending_request_raw->SetPermissionResult(
permissions[i],
content::PermissionResult(PermissionStatus::GRANTED));
break;
case PermissionType::NUM:
NOTREACHED() << "PermissionType::NUM was not expected here.";
}
}
if (!pending_requests_.Lookup(request_id)) {
return;
}
if (pending_request_raw->IsCompleted()) {
std::vector<content::PermissionResult> results =
pending_request_raw->results;
RequestPermissionsCallback completed_callback =
std::move(pending_request_raw->callback);
pending_requests_.Remove(request_id);
std::move(completed_callback).Run(results);
}
}
void AwPermissionManager::OnRequestResponse(
const base::WeakPtr<AwPermissionManager>& manager,
int request_id,
PermissionType permission,
bool allowed) {
CHECK(manager);
PermissionStatus status =
allowed ? PermissionStatus::GRANTED : PermissionStatus::DENIED;
PendingRequest* pending_request =
manager->pending_requests_.Lookup(request_id);
manager->result_cache_->SetResult(permission,
pending_request->requesting_origin,
pending_request->embedding_origin, status);
std::vector<int> complete_request_ids;
std::vector<std::pair<RequestPermissionsCallback,
std::vector<content::PermissionResult>>>
complete_request_pairs;
for (PendingRequestsMap::Iterator<PendingRequest> it(
&manager->pending_requests_);
!it.IsAtEnd(); it.Advance()) {
if (!it.GetCurrentValue()->HasPermissionType(permission) ||
it.GetCurrentValue()->requesting_origin !=
pending_request->requesting_origin) {
continue;
}
it.GetCurrentValue()->SetPermissionResult(
permission, content::PermissionResult(status));
if (it.GetCurrentValue()->IsCompleted()) {
complete_request_ids.push_back(it.GetCurrentKey());
if (!it.GetCurrentValue()->IsCancelled()) {
complete_request_pairs.emplace_back(
std::move(it.GetCurrentValue()->callback),
std::move(it.GetCurrentValue()->results));
}
}
}
for (auto id : complete_request_ids)
manager->pending_requests_.Remove(id);
for (auto& pair : complete_request_pairs)
std::move(pair.first).Run(pair.second);
}
void AwPermissionManager::ResetPermission(PermissionType permission,
const GURL& requesting_origin,
const GURL& embedding_origin) {
result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
}
void AwPermissionManager::RequestPermissionsFromCurrentDocument(
content::RenderFrameHost* render_frame_host,
const content::PermissionRequestDescription& request_description,
base::OnceCallback<void(const std::vector<content::PermissionResult>&)>
callback) {
RequestPermissions(render_frame_host, request_description,
std::move(callback));
}
PermissionStatus AwPermissionManager::GetPermissionStatus(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
const GURL& requesting_origin,
const GURL& embedding_origin) {
return GetPermissionStatusInternal(permission_descriptor, requesting_origin,
embedding_origin,
nullptr);
}
PermissionStatus AwPermissionManager::GetPermissionStatusInternal(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
const GURL& requesting_origin,
const GURL& embedding_origin,
content::WebContents* web_contents) {
const blink::PermissionType permission_type =
blink::PermissionDescriptorToPermissionType(permission_descriptor);
switch (permission_type) {
case blink::PermissionType::PROTECTED_MEDIA_IDENTIFIER:
return result_cache_->GetResult(permission_descriptor, requesting_origin,
embedding_origin);
case blink::PermissionType::GEOLOCATION:
return GetGeolocationPermission(requesting_origin, web_contents);
case blink::PermissionType::CLIPBOARD_SANITIZED_WRITE:
case blink::PermissionType::MIDI:
case blink::PermissionType::SENSORS:
case blink::PermissionType::LOCAL_NETWORK_ACCESS:
return PermissionStatus::GRANTED;
case blink::PermissionType::MIDI_SYSEX:
case blink::PermissionType::AUDIO_CAPTURE:
case blink::PermissionType::VIDEO_CAPTURE:
return PermissionStatus::ASK;
case blink::PermissionType::AR:
case blink::PermissionType::AUTOMATIC_FULLSCREEN:
case blink::PermissionType::BACKGROUND_FETCH:
case blink::PermissionType::BACKGROUND_SYNC:
case blink::PermissionType::CAMERA_PAN_TILT_ZOOM:
case blink::PermissionType::CAPTURED_SURFACE_CONTROL:
case blink::PermissionType::CLIPBOARD_READ_WRITE:
case blink::PermissionType::DISPLAY_CAPTURE:
case blink::PermissionType::DURABLE_STORAGE:
case blink::PermissionType::HAND_TRACKING:
case blink::PermissionType::IDLE_DETECTION:
case blink::PermissionType::KEYBOARD_LOCK:
case blink::PermissionType::LOCAL_FONTS:
case blink::PermissionType::NFC:
case blink::PermissionType::NOTIFICATIONS:
case blink::PermissionType::NUM:
case blink::PermissionType::PAYMENT_HANDLER:
case blink::PermissionType::PERIODIC_BACKGROUND_SYNC:
case blink::PermissionType::POINTER_LOCK:
case blink::PermissionType::SMART_CARD:
case blink::PermissionType::SPEAKER_SELECTION:
case blink::PermissionType::VR:
case blink::PermissionType::WAKE_LOCK_SCREEN:
case blink::PermissionType::WAKE_LOCK_SYSTEM:
case blink::PermissionType::WEB_APP_INSTALLATION:
case blink::PermissionType::WEB_PRINTING:
case blink::PermissionType::WINDOW_MANAGEMENT:
case blink::PermissionType::STORAGE_ACCESS_GRANT:
case blink::PermissionType::TOP_LEVEL_STORAGE_ACCESS:
return PermissionStatus::DENIED;
}
NOTREACHED() << "Unhandled permission type: "
<< static_cast<int>(permission_type);
}
PermissionStatus AwPermissionManager::GetGeolocationPermission(
const GURL& requesting_origin,
content::WebContents* web_contents) {
if (!web_contents) {
return PermissionStatus::ASK;
}
AwSettings* settings = AwSettings::FromWebContents(web_contents);
if (!settings) {
return PermissionStatus::ASK;
}
if (!settings->geolocation_enabled()) {
return PermissionStatus::DENIED;
}
return context_delegate_->GetGeolocationPermission(requesting_origin);
}
content::PermissionResult
AwPermissionManager::GetPermissionResultForOriginWithoutContext(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
const url::Origin& requesting_origin,
const url::Origin& embedding_origin) {
blink::mojom::PermissionStatus status =
GetPermissionStatus(permission_descriptor, requesting_origin.GetURL(),
embedding_origin.GetURL());
return content::PermissionResult(status);
}
content::PermissionResult
AwPermissionManager::GetPermissionResultForCurrentDocument(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderFrameHost* render_frame_host,
bool should_include_device_status) {
content::WebContents* web_contents =
content::WebContents::FromRenderFrameHost(render_frame_host);
return content::PermissionResult(GetPermissionStatusInternal(
permission_descriptor,
permissions::PermissionUtil::GetLastCommittedOriginAsURL(
render_frame_host),
permissions::PermissionUtil::GetLastCommittedOriginAsURL(
render_frame_host->GetMainFrame()),
web_contents));
}
content::PermissionResult AwPermissionManager::GetPermissionResultForWorker(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderProcessHost* render_process_host,
const GURL& worker_origin) {
return content::PermissionResult(
GetPermissionStatus(permission_descriptor, worker_origin, worker_origin));
}
content::PermissionResult
AwPermissionManager::GetPermissionResultForEmbeddedRequester(
const blink::mojom::PermissionDescriptorPtr& permission_descriptor,
content::RenderFrameHost* render_frame_host,
const url::Origin& requesting_origin) {
return content::PermissionResult(GetPermissionStatusInternal(
permission_descriptor, requesting_origin.GetURL(),
permissions::PermissionUtil::GetLastCommittedOriginAsURL(
render_frame_host->GetMainFrame()),
content::WebContents::FromRenderFrameHost(render_frame_host)));
}
void AwPermissionManager::CancelPermissionRequest(int request_id) {
PendingRequest* pending_request = pending_requests_.Lookup(request_id);
if (!pending_request || pending_request->IsCancelled())
return;
pending_request->Cancel();
const GURL& embedding_origin = pending_request->embedding_origin;
const GURL& requesting_origin = pending_request->requesting_origin;
for (auto permission : pending_request->permissions)
result_cache_->ClearResult(permission, requesting_origin, embedding_origin);
AwBrowserPermissionRequestDelegate* delegate = GetDelegate(
pending_request->render_process_id, pending_request->render_frame_id);
for (auto permission : pending_request->permissions) {
if (pending_request->IsCompleted(permission))
continue;
bool should_not_cancel_ = false;
for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
!it.IsAtEnd(); it.Advance()) {
if (it.GetCurrentValue() != pending_request &&
it.GetCurrentValue()->HasPermissionType(permission) &&
it.GetCurrentValue()->requesting_origin == requesting_origin &&
!it.GetCurrentValue()->IsCompleted(permission)) {
should_not_cancel_ = true;
break;
}
}
if (should_not_cancel_)
continue;
switch (permission) {
case PermissionType::GEOLOCATION:
if (delegate)
delegate->CancelGeolocationPermissionRequests(requesting_origin);
break;
case PermissionType::PROTECTED_MEDIA_IDENTIFIER:
if (delegate)
delegate->CancelProtectedMediaIdentifierPermissionRequests(
requesting_origin);
break;
case PermissionType::MIDI_SYSEX:
if (delegate)
delegate->CancelMIDISysexPermissionRequests(requesting_origin);
break;
case PermissionType::NOTIFICATIONS:
case PermissionType::DURABLE_STORAGE:
case PermissionType::AUDIO_CAPTURE:
case PermissionType::VIDEO_CAPTURE:
case PermissionType::BACKGROUND_SYNC:
case PermissionType::CLIPBOARD_READ_WRITE:
case PermissionType::CLIPBOARD_SANITIZED_WRITE:
case PermissionType::PAYMENT_HANDLER:
case PermissionType::BACKGROUND_FETCH:
case PermissionType::IDLE_DETECTION:
case PermissionType::PERIODIC_BACKGROUND_SYNC:
case PermissionType::NFC:
case PermissionType::HAND_TRACKING:
case PermissionType::VR:
case PermissionType::AR:
case PermissionType::STORAGE_ACCESS_GRANT:
case PermissionType::TOP_LEVEL_STORAGE_ACCESS:
case PermissionType::CAMERA_PAN_TILT_ZOOM:
case PermissionType::WINDOW_MANAGEMENT:
case PermissionType::LOCAL_FONTS:
case PermissionType::DISPLAY_CAPTURE:
case PermissionType::CAPTURED_SURFACE_CONTROL:
case PermissionType::SMART_CARD:
case PermissionType::WEB_PRINTING:
case PermissionType::SPEAKER_SELECTION:
case PermissionType::KEYBOARD_LOCK:
case PermissionType::POINTER_LOCK:
case PermissionType::AUTOMATIC_FULLSCREEN:
case PermissionType::WEB_APP_INSTALLATION:
NOTIMPLEMENTED() << "CancelPermission not implemented for "
<< static_cast<int>(permission);
break;
case PermissionType::MIDI:
case PermissionType::SENSORS:
case PermissionType::WAKE_LOCK_SCREEN:
case PermissionType::WAKE_LOCK_SYSTEM:
case PermissionType::LOCAL_NETWORK_ACCESS:
break;
case PermissionType::NUM:
NOTREACHED() << "PermissionType::NUM was not expected here.";
}
pending_request->SetPermissionResult(
permission, content::PermissionResult(PermissionStatus::DENIED));
}
if (pending_request->IsCompleted())
pending_requests_.Remove(request_id);
}
void AwPermissionManager::CancelPermissionRequests() {
std::vector<int> request_ids;
for (PendingRequestsMap::Iterator<PendingRequest> it(&pending_requests_);
!it.IsAtEnd(); it.Advance()) {
request_ids.push_back(it.GetCurrentKey());
}
for (auto request_id : request_ids)
CancelPermissionRequest(request_id);
DCHECK(pending_requests_.IsEmpty());
}
void AwPermissionManager::SetOriginCanReadEnumerateDevicesAudioLabels(
const url::Origin& origin,
bool audio) {
auto it = enumerate_devices_labels_cache_.find(origin);
if (it == enumerate_devices_labels_cache_.end()) {
enumerate_devices_labels_cache_[origin] = std::make_pair(audio, false);
} else {
it->second.first = audio;
}
}
void AwPermissionManager::SetOriginCanReadEnumerateDevicesVideoLabels(
const url::Origin& origin,
bool video) {
auto it = enumerate_devices_labels_cache_.find(origin);
if (it == enumerate_devices_labels_cache_.end())
enumerate_devices_labels_cache_[origin] = std::make_pair(false, video);
else
it->second.second = video;
}
bool AwPermissionManager::ShouldShowEnumerateDevicesAudioLabels(
const url::Origin& origin) {
auto it = enumerate_devices_labels_cache_.find(origin);
if (it == enumerate_devices_labels_cache_.end())
return false;
return it->second.first;
}
bool AwPermissionManager::ShouldShowEnumerateDevicesVideoLabels(
const url::Origin& origin) {
auto it = enumerate_devices_labels_cache_.find(origin);
if (it == enumerate_devices_labels_cache_.end())
return false;
return it->second.second;
}
void AwPermissionManager::ClearEnumerateDevicesCachedPermission(
const url::Origin& origin,
bool remove_audio,
bool remove_video) {
auto it = enumerate_devices_labels_cache_.find(origin);
if (it == enumerate_devices_labels_cache_.end())
return;
else if (remove_audio && remove_video) {
enumerate_devices_labels_cache_.erase(origin);
} else if (remove_audio) {
it->second.first = false;
} else if (remove_video) {
it->second.second = false;
}
}
int AwPermissionManager::GetRenderProcessID(
content::RenderFrameHost* render_frame_host) {
return render_frame_host->GetProcess()->GetDeprecatedID();
}
int AwPermissionManager::GetRenderFrameID(
content::RenderFrameHost* render_frame_host) {
return render_frame_host->GetRoutingID();
}
GURL AwPermissionManager::LastCommittedMainOrigin(
content::RenderFrameHost* render_frame_host) {
return permissions::PermissionUtil::GetLastCommittedOriginAsURL(
render_frame_host->GetMainFrame());
}
AwBrowserPermissionRequestDelegate* AwPermissionManager::GetDelegate(
int render_process_id,
int render_frame_id) {
return AwBrowserPermissionRequestDelegate::FromID(render_process_id,
render_frame_id);
}
}