diff options
Diffstat (limited to 'chromium/extensions/browser/api/management')
6 files changed, 66 insertions, 212 deletions
diff --git a/chromium/extensions/browser/api/management/BUILD.gn b/chromium/extensions/browser/api/management/BUILD.gn index 7692a4e1b99..7670df786f0 100644 --- a/chromium/extensions/browser/api/management/BUILD.gn +++ b/chromium/extensions/browser/api/management/BUILD.gn @@ -14,7 +14,6 @@ source_set("management") { "management_api_constants.cc", "management_api_constants.h", "management_api_delegate.h", - "supervised_user_service_delegate.h", ] deps = [ "//extensions/common/api" ] diff --git a/chromium/extensions/browser/api/management/management_api.cc b/chromium/extensions/browser/api/management/management_api.cc index f19d3e9253f..c44d29df281 100644 --- a/chromium/extensions/browser/api/management/management_api.cc +++ b/chromium/extensions/browser/api/management/management_api.cc @@ -48,11 +48,6 @@ #include "url/gurl.h" #include "url/url_constants.h" -#if defined(OS_CHROMEOS) -#include "components/web_modal/web_contents_modal_dialog_manager.h" -#include "content/public/browser/web_contents.h" -#endif - using content::BrowserThread; namespace keys = extension_management_api_constants; @@ -436,53 +431,42 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() { bool should_enable = params->enabled; - const SupervisedUserServiceDelegate* supervised_user_service_delegate = - ManagementAPI::GetFactoryInstance() - ->Get(browser_context()) - ->GetSupervisedUserServiceDelegate(); - - const bool is_supervised_child_who_may_install_extensions = - supervised_user_service_delegate - ? supervised_user_service_delegate - ->IsSupervisedChildWhoMayInstallExtensions(browser_context()) - : false; - const ManagementPolicy* policy = ExtensionSystem::Get(browser_context())->management_policy(); - if (!policy->ExtensionMayModifySettings(extension(), target_extension, nullptr)) { return RespondNow(Error(keys::kUserCantModifyError, extension_id_)); } - disable_reason::DisableReason reason = disable_reason::DISABLE_NONE; - bool disallow_enable = - should_enable && - policy->MustRemainDisabled(target_extension, &reason, nullptr); - - // Figure out if we should prompt for parental approval. - bool prompt_parent_for_approval = - disallow_enable && is_supervised_child_who_may_install_extensions && - reason == disable_reason::DISABLE_CUSTODIAN_APPROVAL_REQUIRED; - - // If the extension can't be enabled, only continue if we plan to prompt for - // parental approval. For any child or other type of managed user, if - // extension installation has been blocked, we stop the enabling of the - // extension here. - if (disallow_enable && !prompt_parent_for_approval) { - LOG(ERROR) << "ManagementSetEnabledFunction::Run: extension may not be " - "enabled, and we're not prompting for parent approval"; + SupervisedUserExtensionsDelegate* supervised_user_extensions_delegate = + ManagementAPI::GetFactoryInstance() + ->Get(browser_context()) + ->GetSupervisedUserExtensionsDelegate(); + if (supervised_user_extensions_delegate && + supervised_user_extensions_delegate->IsChild(browser_context()) && + // Don't prompt the user if the extension has unsupported requirements. + // TODO(crbug/1071978): If OnRequirementsChecked() passes, the extension + // will enable, bypassing parent approval. + !HasUnsupportedRequirements(extension_id_) && + // Only ask for parent approval if the extension still requires approval. + !supervised_user_extensions_delegate->IsExtensionAllowedByParent( + *target_extension, browser_context())) { + // Either ask for parent permission or notify the child that their parent + // has disabled this action. + auto parent_permission_callback = base::BindOnce( + &ManagementSetEnabledFunction::OnParentPermissionDialogDone, this); + auto error_callback = base::BindOnce( + &ManagementSetEnabledFunction::OnBlockedByParentDialogDone, this); + AddRef(); // Matched in OnParentPermissionDialogDone() or + // OnBlockedByParentDialogDone(). + supervised_user_extensions_delegate->PromptForParentPermissionOrShowError( + *target_extension, browser_context(), GetSenderWebContents(), + std::move(parent_permission_callback), std::move(error_callback)); + return RespondLater(); + } -#if defined(OS_CHROMEOS) - // On ChromeOS, if this is a child, show the dialog indicating that enabling - // extensions has been blocked by a parent. - if (supervised_user_service_delegate && - supervised_user_service_delegate->IsChild(browser_context())) { - AddRef(); // Matched in OnBlockedByParentDialogDone(). - ShowBlockedByParentDialog(target_extension); - return RespondLater(); - } -#endif + if (should_enable && + policy->MustRemainDisabled(target_extension, nullptr, nullptr)) { return RespondNow(Error(keys::kUserCantModifyError, extension_id_)); } @@ -492,8 +476,7 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() { if (!currently_enabled && should_enable) { ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context()); - if (!prompt_parent_for_approval && - prefs->DidExtensionEscalatePermissions(extension_id_)) { + if (prefs->DidExtensionEscalatePermissions(extension_id_)) { if (!user_gesture()) return RespondNow(Error(keys::kGestureNeededForEscalationError)); @@ -503,8 +486,7 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() { base::Bind(&ManagementSetEnabledFunction::OnInstallPromptDone, this)); return RespondLater(); } - if (prefs->GetDisableReasons(extension_id_) & - disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT) { + if (HasUnsupportedRequirements(extension_id_)) { // Recheck the requirements. requirements_checker_ = std::make_unique<RequirementsChecker>(target_extension); @@ -513,18 +495,6 @@ ExtensionFunction::ResponseAction ManagementSetEnabledFunction::Run() { this)); // This bind creates a reference. return RespondLater(); } - // Handle parental approval for child accounts that have the ability to - // install extensions. - if (prompt_parent_for_approval && - // Don't re-prompt the parent for extensions that have already been - // approved for a child. - !supervised_user_service_delegate->IsExtensionAllowedByParent( - *target_extension, browser_context())) { - LOG(ERROR) << "ManagementSetEnabledFunction::Run: prompting for parent " - "approval"; - return RequestParentPermission(target_extension); - } - delegate->EnableExtension(browser_context(), extension_id_); } else if (currently_enabled && !params->enabled) { delegate->DisableExtension( @@ -551,6 +521,13 @@ void ManagementSetEnabledFunction::OnInstallPromptDone(bool did_accept) { Release(); // Balanced in Run(). } +bool ManagementSetEnabledFunction::HasUnsupportedRequirements( + const std::string& extension_id) { + ExtensionPrefs* prefs = ExtensionPrefs::Get(browser_context()); + return prefs->GetDisableReasons(extension_id) & + disable_reason::DISABLE_UNSUPPORTED_REQUIREMENT; +} + void ManagementSetEnabledFunction::OnRequirementsChecked( const PreloadCheck::Errors& errors) { if (errors.empty()) { @@ -564,30 +541,11 @@ void ManagementSetEnabledFunction::OnRequirementsChecked( } } -ExtensionFunction::ResponseAction -ManagementSetEnabledFunction::RequestParentPermission( - const Extension* extension) { - content::WebContents* web_contents = GetSenderWebContents(); - if (!web_contents) - return RespondNow(Error(keys::kWebContentsDisappearedError)); - - // Show parental approval prompt. - auto callback = base::BindOnce( - &ManagementSetEnabledFunction::OnParentPermissionDone, this); - SupervisedUserServiceDelegate* supervised_user_service_delegate = - ManagementAPI::GetFactoryInstance() - ->Get(browser_context()) - ->GetSupervisedUserServiceDelegate(); - DCHECK(supervised_user_service_delegate); - supervised_user_service_delegate->ShowParentPermissionDialogForExtension( - *extension, browser_context(), web_contents, std::move(callback)); - return RespondLater(); -} - -void ManagementSetEnabledFunction::OnParentPermissionDone( - SupervisedUserServiceDelegate::ParentPermissionDialogResult result) { +void ManagementSetEnabledFunction::OnParentPermissionDialogDone( + SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result) { +#if defined(OS_CHROMEOS) switch (result) { - case SupervisedUserServiceDelegate::ParentPermissionDialogResult:: + case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult:: kParentPermissionReceived: { const ManagementAPIDelegate* delegate = ManagementAPI::GetFactoryInstance() @@ -598,49 +556,21 @@ void ManagementSetEnabledFunction::OnParentPermissionDone( break; } - case SupervisedUserServiceDelegate::ParentPermissionDialogResult:: + case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult:: kParentPermissionCanceled: { Respond(Error(keys::kUserDidNotReEnableError)); break; } - case SupervisedUserServiceDelegate::ParentPermissionDialogResult:: + case SupervisedUserExtensionsDelegate::ParentPermissionDialogResult:: kParentPermissionFailed: { Respond(Error(keys::kParentPermissionFailedError)); break; } } -} - -void ManagementSetEnabledFunction::ShowBlockedByParentDialog( - const Extension* extension) { -#if defined(OS_CHROMEOS) - DCHECK(extension); - SupervisedUserServiceDelegate* supervised_user_service_delegate = - ManagementAPI::GetFactoryInstance() - ->Get(browser_context()) - ->GetSupervisedUserServiceDelegate(); - - supervised_user_service_delegate - ->RecordExtensionEnableBlockedByParentDialogUmaMetric(); - - content::WebContents* contents = GetSenderWebContents(); - web_modal::WebContentsModalDialogManager* manager = - web_modal::WebContentsModalDialogManager::FromWebContents(contents); - if (!contents || !contents->GetTopLevelNativeWindow() || !manager) { - // If the contents are null, or there is no top level native window to - // anchor the dialog on, or no dialog manager, skip showing the dialog and - // return the error immediately. - OnBlockedByParentDialogDone(); - return; - } - supervised_user_service_delegate - ->ShowExtensionEnableBlockedByParentDialogForExtension( - extension, contents, - base::BindOnce( - &ManagementSetEnabledFunction::OnBlockedByParentDialogDone, - this)); -#endif + // Matches the AddRef in Run(). + Release(); +#endif // defined(OS_CHROMEOS) } void ManagementSetEnabledFunction::OnBlockedByParentDialogDone() { @@ -648,7 +578,7 @@ void ManagementSetEnabledFunction::OnBlockedByParentDialogDone() { Respond(Error(keys::kUserCantModifyError, extension_id_)); // Matches the AddRef in Run(). Release(); -#endif +#endif // defined(OS_CHROMEOS) } ManagementUninstallFunctionBase::ManagementUninstallFunctionBase() = default; @@ -1180,8 +1110,9 @@ void ManagementEventRouter::BroadcastEvent( ManagementAPI::ManagementAPI(content::BrowserContext* context) : browser_context_(context), delegate_(ExtensionsAPIClient::Get()->CreateManagementAPIDelegate()), - supervised_user_service_delegate_( - ExtensionsAPIClient::Get()->CreateSupervisedUserServiceDelegate()) { + supervised_user_extensions_delegate_( + ExtensionsAPIClient::Get() + ->CreateSupervisedUserExtensionsDelegate()) { EventRouter* event_router = EventRouter::Get(browser_context_); event_router->RegisterObserver(this, management::OnInstalled::kEventName); event_router->RegisterObserver(this, management::OnUninstalled::kEventName); diff --git a/chromium/extensions/browser/api/management/management_api.h b/chromium/extensions/browser/api/management/management_api.h index 1e195465151..89b4205333a 100644 --- a/chromium/extensions/browser/api/management/management_api.h +++ b/chromium/extensions/browser/api/management/management_api.h @@ -14,13 +14,13 @@ #include "base/strings/string16.h" #include "components/keyed_service/core/keyed_service.h" #include "extensions/browser/api/management/management_api_delegate.h" -#include "extensions/browser/api/management/supervised_user_service_delegate.h" #include "extensions/browser/browser_context_keyed_api_factory.h" #include "extensions/browser/event_router.h" #include "extensions/browser/extension_event_histogram_value.h" #include "extensions/browser/extension_function.h" #include "extensions/browser/extension_registry_observer.h" #include "extensions/browser/preload_check.h" +#include "extensions/browser/supervised_user_extensions_delegate.h" #include "services/data_decoder/public/cpp/data_decoder.h" namespace extensions { @@ -115,24 +115,18 @@ class ManagementSetEnabledFunction : public ExtensionFunction { private: void OnInstallPromptDone(bool did_accept); - void OnRequirementsChecked(const PreloadCheck::Errors& errors); - - ExtensionFunction::ResponseAction RequestParentPermission( - const Extension* extension); + bool HasUnsupportedRequirements(const std::string& extension_id); - void OnParentPermissionDone( - SupervisedUserServiceDelegate::ParentPermissionDialogResult result); + void OnRequirementsChecked(const PreloadCheck::Errors& errors); - // Shows the dialog that tells the user that the parent has blocked the - // installation of extensions, apps, etc. - void ShowBlockedByParentDialog(const Extension* extension); + // Called when the user dismisses the Parent Permission Dialog. + void OnParentPermissionDialogDone( + SupervisedUserExtensionsDelegate::ParentPermissionDialogResult result); - // Called when the dialog shown by ShowBlockedByParentDialog() is dismissed. + // Called when the user dismisses the Extension Install Blocked By Parent + // Dialog. void OnBlockedByParentDialogDone(); - std::unique_ptr<SupervisedUserServiceDelegate::ParentPermissionDialogResult> - parental_permission_dialog_; - std::string extension_id_; std::unique_ptr<InstallPromptDelegate> install_prompt_; @@ -334,16 +328,17 @@ class ManagementAPI : public BrowserContextKeyedAPI, // Returns the SupervisedUserService delegate, which might be null depending // on the extensions embedder. - SupervisedUserServiceDelegate* GetSupervisedUserServiceDelegate() const { - return supervised_user_service_delegate_.get(); + SupervisedUserExtensionsDelegate* GetSupervisedUserExtensionsDelegate() + const { + return supervised_user_extensions_delegate_.get(); } void set_delegate_for_test(std::unique_ptr<ManagementAPIDelegate> delegate) { delegate_ = std::move(delegate); } - void set_supervised_user_service_delegate_for_test( - std::unique_ptr<SupervisedUserServiceDelegate> delegate) { - supervised_user_service_delegate_ = std::move(delegate); + void set_supervised_user_extensions_delegate_for_test( + std::unique_ptr<SupervisedUserExtensionsDelegate> delegate) { + supervised_user_extensions_delegate_ = std::move(delegate); } private: @@ -360,8 +355,8 @@ class ManagementAPI : public BrowserContextKeyedAPI, std::unique_ptr<ManagementEventRouter> management_event_router_; std::unique_ptr<ManagementAPIDelegate> delegate_; - std::unique_ptr<SupervisedUserServiceDelegate> - supervised_user_service_delegate_; + std::unique_ptr<SupervisedUserExtensionsDelegate> + supervised_user_extensions_delegate_; DISALLOW_COPY_AND_ASSIGN(ManagementAPI); }; diff --git a/chromium/extensions/browser/api/management/management_api_constants.cc b/chromium/extensions/browser/api/management/management_api_constants.cc index 5069a509e44..686075749ac 100644 --- a/chromium/extensions/browser/api/management/management_api_constants.cc +++ b/chromium/extensions/browser/api/management/management_api_constants.cc @@ -63,8 +63,6 @@ const char kInstallReplacementAndroidAppNotFromWebstoreError[] = "Only extensions from the web store can install replacement Android apps."; const char kInstallReplacementAndroidAppCannotInstallApp[] = "Could not install Android App."; -const char kWebContentsDisappearedError[] = - "Web contents disappeared while attempting to enable extension."; const char kParentPermissionFailedError[] = "Parent Permission Request Failed."; } // namespace extension_management_api_constants diff --git a/chromium/extensions/browser/api/management/management_api_constants.h b/chromium/extensions/browser/api/management/management_api_constants.h index d93cbbdcf57..a0c5aeb7736 100644 --- a/chromium/extensions/browser/api/management/management_api_constants.h +++ b/chromium/extensions/browser/api/management/management_api_constants.h @@ -44,7 +44,6 @@ extern const char kGestureNeededForInstallReplacementAndroidAppError[]; extern const char kInstallReplacementAndroidAppCannotInstallApp[]; extern const char kInstallReplacementAndroidAppInvalidContextError[]; extern const char kInstallReplacementAndroidAppNotFromWebstoreError[]; -extern const char kWebContentsDisappearedError[]; extern const char kParentPermissionFailedError[]; } // namespace extension_management_api_constants diff --git a/chromium/extensions/browser/api/management/supervised_user_service_delegate.h b/chromium/extensions/browser/api/management/supervised_user_service_delegate.h deleted file mode 100644 index 57b879d844c..00000000000 --- a/chromium/extensions/browser/api/management/supervised_user_service_delegate.h +++ /dev/null @@ -1,68 +0,0 @@ -// Copyright 2020 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. - -#ifndef EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_ -#define EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_ - -#include "base/callback.h" -#include "extensions/common/extension.h" - -namespace content { -class BrowserContext; -class WebContents; -} // namespace content - -namespace extensions { - -class SupervisedUserServiceDelegate { - public: - virtual ~SupervisedUserServiceDelegate() = default; - - // Returns true if |context| represents a supervised child account. - virtual bool IsChild(content::BrowserContext* context) const = 0; - - // Returns true if |context| represents a supervised child account - // who may install extensions with parent permission. - virtual bool IsSupervisedChildWhoMayInstallExtensions( - content::BrowserContext* context) const = 0; - - // Returns true if the current child user is allowed to install the specified - // |extension|. - virtual bool IsExtensionAllowedByParent( - const extensions::Extension& extension, - content::BrowserContext* context) const = 0; - - // Result of the parent permission dialog invocation. - enum class ParentPermissionDialogResult { - kParentPermissionReceived, - kParentPermissionCanceled, - kParentPermissionFailed, - }; - - using ParentPermissionDialogDoneCallback = - base::OnceCallback<void(ParentPermissionDialogResult)>; - - // Shows a parent permission dialog for |extension| and call |done_callback| - // when it completes. - virtual void ShowParentPermissionDialogForExtension( - const extensions::Extension& extension, - content::BrowserContext* context, - content::WebContents* contents, - ParentPermissionDialogDoneCallback done_callback) = 0; - - // Shows a dialog indicating that |extension| has been blocked and call - // |done_callback| when it completes. - virtual void ShowExtensionEnableBlockedByParentDialogForExtension( - const extensions::Extension* extension, - content::WebContents* contents, - base::OnceClosure done_callback) = 0; - - // Records UMA metrics for supervised users trying to install or enable an - // extension when this action is blocked by the parent. - virtual void RecordExtensionEnableBlockedByParentDialogUmaMetric() = 0; -}; - -} // namespace extensions - -#endif // EXTENSIONS_BROWSER_API_MANAGEMENT_SUPERVISED_USER_SERVICE_DELEGATE_H_ |