chromium/chrome/browser/supervised_user/chromeos/parent_access_extension_approvals_manager.cc

// Copyright 2023 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/supervised_user/chromeos/parent_access_extension_approvals_manager.h"

#include <string>
#include <vector>

#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/extensions/extension_util.h"
#include "chrome/browser/extensions/install_prompt_permissions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/supervised_user/chromeos/chromeos_utils.h"
#include "chrome/browser/supervised_user/supervised_user_browser_utils.h"
#include "chrome/browser/supervised_user/supervised_user_extensions_metrics_recorder.h"
#include "chromeos/crosapi/mojom/parent_access.mojom.h"
#include "components/supervised_user/core/common/features.h"
#include "content/public/browser/browser_context.h"
#include "extensions/browser/supervised_user_extensions_delegate.h"
#include "extensions/common/extension.h"
#include "extensions/common/permissions/permission_set.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image_skia.h"

namespace {
extensions::TestExtensionApprovalsManagerObserver* test_observer = nullptr;
}  // namespace

namespace extensions {

ParentAccessExtensionApprovalsManager::ParentAccessExtensionApprovalsManager() =
    default;

ParentAccessExtensionApprovalsManager::
    ~ParentAccessExtensionApprovalsManager() = default;

void ParentAccessExtensionApprovalsManager::ShowParentAccessDialog(
    const Extension& extension,
    content::BrowserContext* context,
    const gfx::ImageSkia& icon,
    ExtensionInstallMode extension_install_mode,
    SupervisedUserExtensionsDelegate::ExtensionApprovalDoneCallback callback) {
  Profile* profile = Profile::FromBrowserContext(context);
  CHECK(profile);

  // Load permission strings.
  InstallPromptPermissions prompt_permissions;
  std::unique_ptr<const PermissionSet> permissions_to_display =
      util::GetInstallPromptPermissionSetForExtension(&extension, profile);
  prompt_permissions.LoadFromPermissionSet(permissions_to_display.get(),
                                           extension.GetType());
  const size_t permissions_count = prompt_permissions.permissions.size();
  CHECK_EQ(permissions_count, prompt_permissions.details.size());

  std::vector<crosapi::mojom::ExtensionPermissionPtr> extension_permissions;
  extension_permissions.reserve(permissions_count);
  for (size_t i = 0; i < permissions_count; ++i) {
    crosapi::mojom::ExtensionPermissionPtr permission =
        crosapi::mojom::ExtensionPermission::New(
            prompt_permissions.permissions[i], prompt_permissions.details[i]);
    extension_permissions.push_back(std::move(permission));
  }

  done_callback_ = std::move(callback);

  if (test_observer) {
    test_observer->OnTestParentAccessDialogCreated();
    OnParentAccessDialogClosed(test_observer->GetNextResult());
    return;
  }

  crosapi::mojom::ParentAccess* parent_access =
      supervised_user::GetParentAccessApi();
  CHECK(parent_access);
  parent_access->GetExtensionParentApproval(
      base::UTF8ToUTF16(extension.name()),
      base::UTF8ToUTF16(supervised_user::GetAccountGivenName(*profile)), icon,
      std::move(extension_permissions),
      /* requests_disabled= */ extension_install_mode ==
          ExtensionInstallMode::kInstallationDenied,
      base::BindOnce(
          &ParentAccessExtensionApprovalsManager::OnParentAccessDialogClosed,
          weak_ptr_factory_.GetWeakPtr()));
}

void ParentAccessExtensionApprovalsManager::OnParentAccessDialogClosed(
    crosapi::mojom::ParentAccessResultPtr result) {
  switch (result->which()) {
    case crosapi::mojom::ParentAccessResult::Tag::kApproved:
      std::move(done_callback_)
          .Run(SupervisedUserExtensionsDelegate::ExtensionApprovalResult::
                   kApproved);
      break;

    case crosapi::mojom::ParentAccessResult::Tag::kDeclined:
    case crosapi::mojom::ParentAccessResult::Tag::kCanceled:
      std::move(done_callback_)
          .Run(SupervisedUserExtensionsDelegate::ExtensionApprovalResult::
                   kCanceled);
      break;

    case crosapi::mojom::ParentAccessResult::Tag::kError:
      std::move(done_callback_)
          .Run(SupervisedUserExtensionsDelegate::ExtensionApprovalResult::
                   kFailed);
      break;
    case crosapi::mojom::ParentAccessResult::Tag::kDisabled:
      SupervisedUserExtensionsMetricsRecorder::RecordEnablementUmaMetrics(
          SupervisedUserExtensionsMetricsRecorder::EnablementState::
              kFailedToEnable);
      std::move(done_callback_)
          .Run(SupervisedUserExtensionsDelegate::ExtensionApprovalResult::
                   kBlocked);
      break;
  }
}

TestExtensionApprovalsManagerObserver::TestExtensionApprovalsManagerObserver(
    TestExtensionApprovalsManagerObserver* observer) {
  test_observer = observer;
}

TestExtensionApprovalsManagerObserver::
    ~TestExtensionApprovalsManagerObserver() {
  test_observer = nullptr;
}

void TestExtensionApprovalsManagerObserver::SetParentAccessDialogResult(
    crosapi::mojom::ParentAccessResultPtr result) {
  next_result_ = std::move(result);
}

crosapi::mojom::ParentAccessResultPtr
TestExtensionApprovalsManagerObserver::GetNextResult() {
  return std::move(next_result_);
}

}  // namespace extensions