1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
|
// Copyright 2022 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "components/permissions/android/permissions_reprompt_controller_android.h"
#include "base/check.h"
#include "components/permissions/android/android_permission_util.h"
#include "components/permissions/permissions_client.h"
#include "content/public/browser/web_contents.h"
#include "ui/android/window_android.h"
namespace permissions {
void PermissionsRepromptControllerAndroid::RepromptPermissionRequest(
const std::vector<ContentSettingsType>& content_settings_types,
ContentSettingsType permission_context_content_setting_type,
RepromptPermissionRequestCallback callback) {
DCHECK_EQ(permissions::ShouldRepromptUserForPermissions(
&GetWebContents(), content_settings_types),
permissions::PermissionRepromptState::kShow)
<< "Caller should check ShouldRepromptUserForPermissions before "
"reprompting";
const auto filtered_content_settings_types =
GetContentSettingsWithMissingRequiredAndroidPermissions(
content_settings_types, &GetWebContents());
RepromptPermissionRequestInternal(
content_settings_types, filtered_content_settings_types,
permission_context_content_setting_type, std::move(callback));
}
void PermissionsRepromptControllerAndroid::OnRepromptPermissionRequestDone(
const RequestKey& request_key,
bool success) {
auto it = pending_callbacks_.find(request_key);
CHECK(it != pending_callbacks_.end());
for (auto& callback : it->second.second) {
std::move(callback).Run(success);
}
pending_callbacks_.erase(request_key);
}
void PermissionsRepromptControllerAndroid::RepromptPermissionRequestInternal(
const std::vector<ContentSettingsType>& content_settings_types,
const std::vector<ContentSettingsType>& filtered_content_settings_types,
ContentSettingsType permission_context_content_setting_type,
RepromptPermissionRequestCallback callback) {
RequestKey key(filtered_content_settings_types);
auto it = pending_callbacks_.find(key);
if (it != pending_callbacks_.end()) {
auto& context_set = it->second.first;
// Simply bail out if we are requesting duplicated requests from the
// same PermissionContext
if (context_set.find(permission_context_content_setting_type) !=
context_set.end())
return;
context_set.insert(permission_context_content_setting_type);
auto& callbacks = it->second.second;
callbacks.push_back(std::move(callback));
return;
}
PermissionsContextSet new_context_set{
permission_context_content_setting_type};
RequestCallbacksList new_callbacks;
new_callbacks.push_back(std::move(callback));
pending_callbacks_[key] =
std::make_pair(std::move(new_context_set), std::move(new_callbacks));
PermissionsClient::Get()->RepromptForAndroidPermissions(
&GetWebContents(), content_settings_types,
filtered_content_settings_types, key.required_permissions,
key.optional_permissions,
base::BindOnce(&PermissionsRepromptControllerAndroid::
OnRepromptPermissionRequestDone,
weak_factory_.GetWeakPtr(), key));
}
PermissionsRepromptControllerAndroid::PermissionsRepromptControllerAndroid(
content::WebContents* web_contents)
: content::WebContentsUserData<PermissionsRepromptControllerAndroid>(
*web_contents) {}
PermissionsRepromptControllerAndroid::~PermissionsRepromptControllerAndroid() {
for (auto& it : pending_callbacks_) {
for (auto& callback : it.second.second) {
// If we don't know the state of the OS permission due to destroyed
// web_content, assume we don't have the permission.
std::move(callback).Run(/* permission_granted */ false);
}
}
pending_callbacks_.clear();
}
PermissionsRepromptControllerAndroid::RequestKey::RequestKey(
const std::vector<ContentSettingsType>& content_setting_types) {
AppendRequiredAndOptionalAndroidPermissionsForContentSettings(
content_setting_types, required_permissions, optional_permissions);
}
PermissionsRepromptControllerAndroid::RequestKey::RequestKey(
const RequestKey& RequestKey) = default;
PermissionsRepromptControllerAndroid::RequestKey::RequestKey(
RequestKey&& RequestKey) = default;
PermissionsRepromptControllerAndroid::RequestKey::~RequestKey() = default;
bool PermissionsRepromptControllerAndroid::RequestKey::operator<(
const RequestKey& rhs) const {
return std::tie(required_permissions, optional_permissions) <
std::tie(rhs.required_permissions, rhs.optional_permissions);
}
WEB_CONTENTS_USER_DATA_KEY_IMPL(PermissionsRepromptControllerAndroid);
} // namespace permissions
|