Chromium Code Reviews| Index: chrome/browser/chromeos/extensions/public_session_permission_helper.cc |
| diff --git a/chrome/browser/chromeos/extensions/public_session_permission_helper.cc b/chrome/browser/chromeos/extensions/public_session_permission_helper.cc |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..1490630ebbfc36ac186603cb662486246fb6ac8b |
| --- /dev/null |
| +++ b/chrome/browser/chromeos/extensions/public_session_permission_helper.cc |
| @@ -0,0 +1,165 @@ |
| +// Copyright 2017 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/chromeos/extensions/public_session_permission_helper.h" |
| + |
| +#include <map> |
| +#include <utility> |
| + |
| +#include "base/bind.h" |
| +#include "base/bind_helpers.h" |
| +#include "base/lazy_instance.h" |
| +#include "base/macros.h" |
| +#include "base/memory/ptr_util.h" |
| +#include "content/public/browser/browser_thread.h" |
| +#include "content/public/browser/web_contents.h" |
| +#include "extensions/common/extension.h" |
| +#include "extensions/common/permissions/api_permission_set.h" |
| +#include "extensions/common/permissions/manifest_permission_set.h" |
| +#include "extensions/common/permissions/permission_set.h" |
| +#include "extensions/common/url_pattern_set.h" |
| + |
| +namespace extensions { |
| + |
| +namespace { |
| + |
| +base::LazyInstance<std::map<ExtensionId, PublicSessionPermissionHelper>>::Leaky |
| + g_helpers = LAZY_INSTANCE_INITIALIZER; |
| + |
| +} // namespace |
| + |
| +// static |
| +void PublicSessionPermissionHelper::HandlePermissionRequest( |
| + const Extension& extension, |
| + PermissionHelperSet requested_permissions, |
| + content::WebContents* web_contents, |
| + const base::Closure& success_callback, |
| + const base::Closure& failure_callback) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + return g_helpers.Get()[extension.id()].HandlePermissionRequestImpl( |
| + extension, requested_permissions, web_contents, success_callback, |
| + failure_callback); |
| +} |
| + |
| +// static |
| +bool PublicSessionPermissionHelper::PermissionAllowed( |
| + ExtensionId extension_id, |
| + APIPermission::ID permission_id) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + return g_helpers.Get()[extension_id].PermissionAllowedImpl(permission_id); |
| +} |
| + |
| +PublicSessionPermissionHelper::PublicSessionPermissionHelper() {} |
| + |
| +PublicSessionPermissionHelper::PublicSessionPermissionHelper( |
| + PublicSessionPermissionHelper&& other) = default; |
| + |
| +PublicSessionPermissionHelper::~PublicSessionPermissionHelper() {} |
| + |
| +void PublicSessionPermissionHelper::HandlePermissionRequestImpl( |
| + const Extension& extension, |
| + PermissionHelperSet requested_permissions, |
| + content::WebContents* web_contents, |
| + const base::Closure& success_callback, |
| + const base::Closure& failure_callback) { |
| + CHECK(web_contents); |
| + |
| + PermissionIDSet requested_permission_set; |
| + for (auto permission : requested_permissions) { |
| + requested_permission_set.insert(permission); |
| + } |
| + |
| + PermissionIDSet unresolved_permissions = PermissionIDSet::Difference( |
| + requested_permission_set, allowed_permission_set_); |
| + if (unresolved_permissions.empty()) { |
| + success_callback.Run(); |
| + return; |
| + } |
| + unresolved_permissions = PermissionIDSet::Difference( |
| + unresolved_permissions, denied_permission_set_); |
| + if (unresolved_permissions.empty()) { |
| + failure_callback.Run(); |
| + return; |
| + } |
| + |
| + // Since not all permissions are resolved yet, queue the callback to be called |
| + // when all of them are resolved. |
| + callbacks_.push_back(RequestCallback( |
| + success_callback, failure_callback, requested_permissions)); |
| + |
| + PermissionIDSet unprompted_permissions = PermissionIDSet::Difference( |
| + unresolved_permissions, prompted_permission_set_); |
| + if (unprompted_permissions.empty()) return; |
| + |
| + APIPermissionSet new_apis; |
| + for (const auto& permission : unprompted_permissions) { |
| + prompted_permission_set_.insert(permission.id()); |
| + new_apis.insert(permission.id()); |
| + } |
| + auto permission_set = base::MakeUnique<PermissionSet>( |
| + new_apis, ManifestPermissionSet(), URLPatternSet(), URLPatternSet()); |
| + auto prompt = base::MakeUnique<ExtensionInstallPrompt>(web_contents); |
| + prompt->ShowDialog( |
| + base::Bind(&PublicSessionPermissionHelper::ResolvePermissionPrompt, |
| + base::Unretained(this), &prompt, |
|
Devlin
2017/01/30 17:04:17
nit: add a comment explaining why this Unretained
Ivan Šandrk
2017/01/30 18:14:20
Done.
|
| + std::move(unprompted_permissions)), |
| + &extension, |
| + nullptr, // Use the extension icon. |
| + base::MakeUnique<ExtensionInstallPrompt::Prompt>( |
| + ExtensionInstallPrompt::PERMISSIONS_PROMPT), |
| + std::move(permission_set), |
| + ExtensionInstallPrompt::GetDefaultShowDialogCallback()); |
| + prompts_.insert(std::move(prompt)); |
| +} |
| + |
| +bool PublicSessionPermissionHelper::PermissionAllowedImpl( |
| + APIPermission::ID permission_id) { |
| + if (allowed_permission_set_.ContainsID(permission_id)) |
|
Devlin
2017/01/30 17:04:17
if (foo)
return true;
return false;
->
return
Ivan Šandrk
2017/01/30 18:14:20
Done.
|
| + return true; |
| + return false; |
| +} |
| + |
| +void PublicSessionPermissionHelper::ResolvePermissionPrompt( |
| + const std::unique_ptr<ExtensionInstallPrompt>* prompt, |
| + PermissionIDSet unprompted_permissions, |
|
Devlin
2017/01/30 17:04:17
const PermissionIDSet&
Ivan Šandrk
2017/01/30 18:14:20
Done.
|
| + ExtensionInstallPrompt::Result prompt_result) { |
| + // Dispose of the prompt as it's not needed anymore. |
| + prompts_.erase(*prompt); |
|
Devlin
2017/01/30 17:04:16
for paranoia, can we do something like:
size_t era
Ivan Šandrk
2017/01/30 18:14:20
Done.
|
| + |
| + bool allowed = prompt_result == ExtensionInstallPrompt::Result::ACCEPTED; |
| + for (const auto& permission : unprompted_permissions) { |
| + prompted_permission_set_.erase(permission.id()); |
| + if (allowed) |
| + allowed_permission_set_.insert(permission.id()); |
| + else |
| + denied_permission_set_.insert(permission.id()); |
| + } |
| + |
| + for (auto callback = callbacks_.begin(); callback != callbacks_.end(); ) { |
| + if (prompted_permission_set_.ContainsAnyID(callback->permission_list)) { |
|
Devlin
2017/01/30 17:04:17
nit: maybe add a comment like:
// The request is s
Ivan Šandrk
2017/01/30 18:14:20
Makes sense here. Done.
|
| + callback++; |
| + continue; |
| + } |
| + if (denied_permission_set_.ContainsAnyID(callback->permission_list)) |
| + callback->failure_callback.Run(); |
| + else |
| + callback->success_callback.Run(); |
| + callback = callbacks_.erase(callback); |
| + } |
| +} |
| + |
| +PublicSessionPermissionHelper::RequestCallback::RequestCallback( |
| + const base::Closure& success_callback, |
| + const base::Closure& failure_callback, |
| + const PermissionHelperSet& permission_list) |
| + : success_callback(success_callback), |
| + failure_callback(failure_callback), |
| + permission_list(permission_list) {} |
| + |
| +PublicSessionPermissionHelper::RequestCallback::RequestCallback( |
| + const RequestCallback& other) = default; |
| + |
| +PublicSessionPermissionHelper::RequestCallback::~RequestCallback() {} |
| + |
| +} // namespace extensions |