chromium/chrome/browser/smart_card/smart_card_permission_uitest.cc

// Copyright 2024 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/chrome_content_browser_client.h"
#include "chrome/browser/content_settings/host_content_settings_map_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/smart_card/chromeos_smart_card_delegate.h"
#include "chrome/browser/ui/views/permissions/permission_prompt_bubble_base_view.h"
#include "chrome/test/interaction/interactive_browser_test.h"
#include "chrome/test/interaction/webcontents_interaction_test_util.h"
#include "components/content_settings/core/browser/host_content_settings_map.h"
#include "components/permissions/features.h"
#include "components/strings/grit/components_strings.h"
#include "content/public/common/content_client.h"
#include "content/public/test/browser_test.h"
#include "net/dns/mock_host_resolver.h"
#include "ui/base/l10n/l10n_util.h"

namespace {
DEFINE_LOCAL_ELEMENT_IDENTIFIER_VALUE(kTestTab);
constexpr char kFooReader[] = "foo reader";

DEFINE_LOCAL_STATE_IDENTIFIER_VALUE(
    ui::test::PollingStateObserver<std::optional<bool>>,
    kPermissionDecision);

class SmartCardPermissionUiTest : public InteractiveBrowserTest {
 public:
  void OnPermissionDecided(bool granted) {
    CHECK_EQ(permission_decision_.has_value(), false);
    permission_decision_ = granted;
  }

  auto CheckReaderPermission(bool has_permission) {
    return CheckResult(
        [this]() -> bool {
          return GetSmartCardDelegate()->HasReaderPermission(GetMainFrameHost(),
                                                             kFooReader);
        },
        has_permission);
  }

  auto RequestReaderPermission() {
    return Do([this]() {
      GetSmartCardDelegate()->RequestReaderPermission(
          GetMainFrameHost(), kFooReader,
          base::BindOnce(&SmartCardPermissionUiTest::OnPermissionDecided,
                         base::Unretained(this)));
    });
  }

  auto BlockPermission(const GURL& origin_url) {
    return Do([this, origin_url]() {
      auto* settings_map =
          HostContentSettingsMapFactory::GetForProfile(browser()->profile());
      settings_map->SetContentSettingDefaultScope(
          origin_url, GURL(), ContentSettingsType::SMART_CARD_GUARD,
          ContentSetting::CONTENT_SETTING_BLOCK);
    });
  }

  auto PressButtonAndWaitResult(ui::ElementIdentifier button_id, bool granted) {
    return Steps(PollState(kPermissionDecision,
                           [this]() { return permission_decision(); }),
                 PressButton(button_id),
                 Log("Wait for the prompt to be hidden."),
                 WaitForHide(PermissionPromptBubbleBaseView::kMainViewId),
                 Log("Wait for the permission decision."),
                 WaitForState(kPermissionDecision, granted));
  }

  std::optional<bool> permission_decision() { return permission_decision_; }

  content::SmartCardDelegate* GetSmartCardDelegate() {
    return content::GetContentClientForTesting()
        ->browser()
        ->GetSmartCardDelegate();
  }

  content::RenderFrameHost& GetMainFrameHost() {
    return *browser()
                ->tab_strip_model()
                ->GetActiveWebContents()
                ->GetPrimaryMainFrame();
  }

 private:
  void SetUpOnMainThread() override {
    InteractiveBrowserTest::SetUpOnMainThread();
    host_resolver()->AddRule("*", "127.0.0.1");
    ASSERT_TRUE(embedded_https_test_server().Start());
  }

  std::optional<bool> permission_decision_;

  base::test::ScopedFeatureList scoped_feature_list_{
      permissions::features::kOneTimePermission};
};

IN_PROC_BROWSER_TEST_F(SmartCardPermissionUiTest, AllowOnce) {
  RunTestSequence(
      InstrumentTab(kTestTab),
      NavigateWebContents(kTestTab, embedded_https_test_server().GetURL(
                                        "a.com", "/simple.html")),
      CheckReaderPermission(/*has_permission=*/false),
      RequestReaderPermission(),
      WaitForShow(PermissionPromptBubbleBaseView::kMainViewId),
      PressButtonAndWaitResult(
          PermissionPromptBubbleBaseView::kAllowOnceButtonElementId,
          /*granted=*/true),
      CheckReaderPermission(/*has_permission=*/true));
}

IN_PROC_BROWSER_TEST_F(SmartCardPermissionUiTest, AllowAlways) {
  RunTestSequence(
      InstrumentTab(kTestTab),
      NavigateWebContents(kTestTab, embedded_https_test_server().GetURL(
                                        "a.com", "/simple.html")),
      CheckReaderPermission(/*has_permission=*/false),
      RequestReaderPermission(),
      WaitForShow(PermissionPromptBubbleBaseView::kMainViewId),
      CheckViewProperty(
          PermissionPromptBubbleBaseView::kAllowButtonElementId,
          &views::LabelButton::GetText,
          l10n_util::GetStringUTF16(IDS_SMART_CARD_PERMISSION_ALWAYS_ALLOW)),
      PressButtonAndWaitResult(
          PermissionPromptBubbleBaseView::kAllowButtonElementId,
          /*granted=*/true),
      CheckReaderPermission(/*has_permission=*/true));
}

IN_PROC_BROWSER_TEST_F(SmartCardPermissionUiTest, Deny) {
  RunTestSequence(
      InstrumentTab(kTestTab),
      NavigateWebContents(kTestTab, embedded_https_test_server().GetURL(
                                        "a.com", "/simple.html")),
      CheckReaderPermission(/*has_permission=*/false),
      RequestReaderPermission(),
      WaitForShow(PermissionPromptBubbleBaseView::kMainViewId),
      PressButtonAndWaitResult(
          PermissionPromptBubbleBaseView::kBlockButtonElementId,
          /*granted=*/false),
      CheckReaderPermission(/*has_permission=*/false));
}

IN_PROC_BROWSER_TEST_F(SmartCardPermissionUiTest, Blocked) {
  auto simple_url =
      embedded_https_test_server().GetURL("a.com", "/simple.html");
  RunTestSequence(InstrumentTab(kTestTab),
                  NavigateWebContents(kTestTab, simple_url),
                  CheckReaderPermission(/*has_permission=*/false),
                  BlockPermission(simple_url),
                  PollState(kPermissionDecision,
                            [this]() { return permission_decision(); }),
                  RequestReaderPermission(),
                  WaitForState(kPermissionDecision, /*granted=*/false),
                  CheckReaderPermission(/*has_permission=*/false));
}

}  // anonymous namespace