blob: 5be04d5fa60f3e84fc39bcac48d44e3c1fc73150 [file] [log] [blame]
// 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/permissions/permission_manager_factory.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/common/webui_url_constants.h"
#include "chrome/test/base/chrome_render_view_host_test_harness.h"
#include "chrome/test/base/testing_browser_process.h"
#include "chrome/test/base/testing_profile.h"
#include "components/permissions/permission_manager.h"
#include "components/permissions/permission_util.h"
#include "components/permissions/permissions_client.h"
#include "components/permissions/test/permission_test_util.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/permission_controller.h"
#include "content/public/browser/permission_descriptor_util.h"
#include "content/public/browser/web_contents.h"
#include "content/public/test/mock_render_process_host.h"
#include "content/public/test/navigation_simulator.h"
#include "content/public/test/permissions_test_utils.h"
#include "services/network/public/cpp/permissions_policy/origin_with_possible_wildcards.h"
#include "services/network/public/cpp/permissions_policy/permissions_policy_declaration.h"
#include "services/network/public/mojom/permissions_policy/permissions_policy_feature.mojom.h"
#include "third_party/blink/public/common/permissions/permission_utils.h"
#include "url/origin.h"
using blink::PermissionType;
using network::mojom::PermissionsPolicyFeature;
// This class tests PermissionStatus.onChange observer.
class PermissionSubscriptionTest : public ChromeRenderViewHostTestHarness {
public:
void OnPermissionChange(content::PermissionResult permission_result) {
if (!quit_closure_.is_null()) {
std::move(quit_closure_).Run();
}
callback_called_ = true;
callback_count_++;
callback_result_ = permission_result.status;
}
protected:
PermissionSubscriptionTest()
: url_(url::Origin::Create(GURL("https://example.com"))),
other_url_(url::Origin::Create(GURL("https://foo.com"))) {}
permissions::PermissionManager* GetPermissionManager() {
return static_cast<permissions::PermissionManager*>(
profile()->GetPermissionControllerDelegate());
}
content::PermissionController* GetPermissionController() {
return GetBrowserContext()->GetPermissionController();
}
HostContentSettingsMap* GetHostContentSettingsMap() {
return permissions::PermissionsClient::Get()->GetSettingsMap(
GetBrowserContext());
}
void CheckPermissionStatus(blink::PermissionType type,
PermissionStatus expected) {
EXPECT_EQ(expected,
GetPermissionController()
->GetPermissionResultForOriginWithoutContext(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(type),
url_, url_)
.status);
}
void SetPermission(blink::PermissionType permission,
PermissionStatus status) {
SetPermission(url_.GetURL(), url_.GetURL(), permission, status);
}
void SetPermission(const GURL& url,
blink::PermissionType permission,
PermissionStatus status) {
SetPermission(url, url, permission, status);
}
void SetPermission(const GURL& requesting_origin,
const GURL& embedding_origin,
blink::PermissionType permission,
PermissionStatus status) {
GetHostContentSettingsMap()->SetContentSettingDefaultScope(
requesting_origin, embedding_origin,
permissions::PermissionUtil::PermissionTypeToContentSettingsType(
permission),
permissions::PermissionUtil::PermissionStatusToContentSetting(status));
}
PermissionStatus GetPermissionStatusForCurrentDocument(
blink::PermissionType permission,
content::RenderFrameHost* render_frame_host) {
return GetPermissionController()->GetPermissionStatusForCurrentDocument(
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(permission),
render_frame_host);
}
const GURL url() const { return url_.GetURL(); }
const GURL other_url() const { return other_url_.GetURL(); }
bool callback_called() const { return callback_called_; }
int callback_count() const { return callback_count_; }
PermissionStatus callback_result() const { return callback_result_; }
void Reset() {
callback_called_ = false;
callback_count_ = 0;
callback_result_ = PermissionStatus::ASK;
}
content::RenderFrameHost* AddChildRFH(
content::RenderFrameHost* parent,
const GURL& origin,
PermissionsPolicyFeature feature = PermissionsPolicyFeature::kNotFound) {
network::ParsedPermissionsPolicy frame_policy = {};
if (feature != PermissionsPolicyFeature::kNotFound) {
frame_policy.emplace_back(
feature,
std::vector{*network::OriginWithPossibleWildcards::FromOrigin(
url::Origin::Create(origin))},
/*self_if_matches=*/std::nullopt,
/*matches_all_origins=*/false,
/*matches_opaque_src=*/false);
}
content::RenderFrameHost* result =
content::RenderFrameHostTester::For(parent)->AppendChildWithPolicy(
"", frame_policy);
content::RenderFrameHostTester::For(result)
->InitializeRenderFrameIfNeeded();
SimulateNavigation(&result, origin);
return result;
}
void SimulateNavigation(content::RenderFrameHost** rfh, const GURL& url) {
auto navigation_simulator =
content::NavigationSimulator::CreateRendererInitiated(url, *rfh);
navigation_simulator->Commit();
*rfh = navigation_simulator->GetFinalRenderFrameHost();
}
private:
void SetUp() override {
TestingBrowserProcess::GetGlobal()->CreateGlobalFeaturesForTesting();
ChromeRenderViewHostTestHarness::SetUp();
profile()->SetPermissionControllerDelegate(
permissions::GetPermissionControllerDelegate(GetBrowserContext()));
NavigateAndCommit(url());
}
void TearDown() override {
GetPermissionManager()->Shutdown();
RenderViewHostTestHarness::TearDown();
}
const url::Origin url_;
const url::Origin other_url_;
bool callback_called_ = false;
int callback_count_ = 0;
PermissionStatus callback_result_ = PermissionStatus::ASK;
base::OnceClosure quit_closure_;
};
TEST_F(PermissionSubscriptionTest,
SubscriptionDestroyedCleanlyWithoutUnsubscribe) {
// Test that the PermissionManager shuts down cleanly with subscriptions that
// haven't been removed, crbug.com/720071.
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
}
TEST_F(PermissionSubscriptionTest, SubscribeUnsubscribeAfterShutdown) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
// Simulate Keyed Services shutdown pass. Note: Shutdown will be called second
// time during browser_context destruction. This is ok for now: Shutdown is
// reenterant.
GetPermissionManager()->Shutdown();
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
// Check that subscribe/unsubscribe after shutdown don't crash.
content::PermissionController::SubscriptionId subscription2_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription2_id);
}
TEST_F(PermissionSubscriptionTest, SameTypeChangeNotifies) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, DifferentTypeChangeDoesNotNotify) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::NOTIFICATIONS, PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, ChangeAfterUnsubscribeDoesNotNotify) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
}
TEST_F(PermissionSubscriptionTest,
ChangeAfterUnsubscribeOnlyNotifiesActiveSubscribers) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_EQ(callback_count(), 1);
}
TEST_F(PermissionSubscriptionTest, DifferentPrimaryUrlDoesNotNotify) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(other_url(), url(), PermissionType::GEOLOCATION,
PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, DifferentSecondaryUrlDoesNotNotify) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::STORAGE_ACCESS_GRANT),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(url(), other_url(), PermissionType::STORAGE_ACCESS_GRANT,
PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, WildCardPatternNotifies) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetHostContentSettingsMap()->SetDefaultContentSetting(
ContentSettingsType::GEOLOCATION, CONTENT_SETTING_ALLOW);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, ClearSettingsNotifies) {
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetHostContentSettingsMap()->ClearSettingsForOneType(
ContentSettingsType::GEOLOCATION);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::ASK, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, NewValueCorrectlyPassed) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::DENIED, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, ChangeWithoutPermissionChangeDoesNotNotify) {
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, ChangesBackAndForth) {
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
Reset();
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::ASK, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, ChangesBackAndForthWorker) {
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
process(),
/*render_frame_host=*/nullptr, url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
Reset();
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::ASK);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::ASK, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, SubscribeMIDIPermission) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(PermissionType::MIDI),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::ASK);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
CheckPermissionStatus(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_FALSE(callback_called());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, SubscribeWithPermissionDelegation) {
NavigateAndCommit(url());
content::RenderFrameHost* parent = main_rfh();
content::RenderFrameHost* child = AddChildRFH(parent, other_url());
// Allow access for the top level origin.
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
// Enabling geolocation by FP should allow the child to request access also.
child =
AddChildRFH(parent, other_url(), PermissionsPolicyFeature::kGeolocation);
EXPECT_EQ(PermissionStatus::GRANTED, GetPermissionStatusForCurrentDocument(
PermissionType::GEOLOCATION, child));
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, child, other_url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
EXPECT_FALSE(callback_called());
// Blocking access to the parent should trigger the callback to be run for the
// child also.
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::DENIED, callback_result());
EXPECT_EQ(PermissionStatus::DENIED, GetPermissionStatusForCurrentDocument(
PermissionType::GEOLOCATION, child));
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
TEST_F(PermissionSubscriptionTest, SubscribeUnsubscribeAndResubscribe) {
NavigateAndCommit(url());
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
EXPECT_EQ(callback_count(), 0);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_EQ(callback_count(), 1);
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
// ensure no callbacks are received when unsubscribed.
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_EQ(callback_count(), 1);
content::PermissionController::SubscriptionId subscription_id_2 =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
EXPECT_EQ(callback_count(), 1);
SetPermission(PermissionType::GEOLOCATION, PermissionStatus::DENIED);
EXPECT_EQ(callback_count(), 2);
EXPECT_EQ(PermissionStatus::DENIED, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id_2);
}
TEST_F(PermissionSubscriptionTest, SubscribersAreNotifedOfEmbargoEvents) {
NavigateAndCommit(url());
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
EXPECT_EQ(callback_count(), 0);
auto* autoblocker =
permissions::PermissionsClient::Get()->GetPermissionDecisionAutoBlocker(
GetBrowserContext());
// 3 dismisses will trigger embargo, which should call the subscription
// callback.
autoblocker->RecordDismissAndEmbargo(url(), ContentSettingsType::GEOLOCATION,
/*dismissed_prompt_was_quiet=*/false);
EXPECT_EQ(callback_count(), 0);
autoblocker->RecordDismissAndEmbargo(url(), ContentSettingsType::GEOLOCATION,
/*dismissed_prompt_was_quiet=*/false);
EXPECT_EQ(callback_count(), 0);
autoblocker->RecordDismissAndEmbargo(url(), ContentSettingsType::GEOLOCATION,
/*dismissed_prompt_was_quiet=*/false);
EXPECT_EQ(callback_count(), 1);
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
// TODO(b/339158416): Add back
// RequestableDevicePermissionChangesLazilyNotifiesObservers and
// NonrequestableDevicePermissionChangesLazilyNotifiesObservers tests once the
// implementation is finished.
TEST_F(PermissionSubscriptionTest,
SubscribeUnsubscribeForNotAddedPermissionContext) {
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::TOP_LEVEL_STORAGE_ACCESS),
/*render_process_host=*/nullptr, main_rfh(), url(),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}
// TODO(https://crbug.com/359831269): Fix new tab page test for Android.
#if BUILDFLAG(IS_ANDROID)
#define MAYBE_SubscribeUnsubscribeForNewTabPage \
DISABLED_SubscribeUnsubscribeForNewTabPage
#else
#define MAYBE_SubscribeUnsubscribeForNewTabPage \
SubscribeUnsubscribeForNewTabPage
#endif
TEST_F(PermissionSubscriptionTest, MAYBE_SubscribeUnsubscribeForNewTabPage) {
NavigateAndCommit(GURL(chrome::kChromeUINewTabURL));
EXPECT_EQ(GURL(chrome::kChromeUINewTabPageThirdPartyURL),
main_rfh()->GetLastCommittedOrigin().GetURL());
content::PermissionController::SubscriptionId subscription_id =
content::SubscribeToPermissionResultChange(
GetPermissionController(),
content::PermissionDescriptorUtil::
CreatePermissionDescriptorForPermissionType(
PermissionType::GEOLOCATION),
/*render_process_host=*/nullptr, main_rfh(),
GURL(chrome::kChromeUINewTabPageThirdPartyURL),
/*should_include_device_status=*/false,
base::BindRepeating(&PermissionSubscriptionTest::OnPermissionChange,
base::Unretained(this)));
SetPermission(GURL(chrome::kChromeUINewTabPageThirdPartyURL),
PermissionType::GEOLOCATION, PermissionStatus::GRANTED);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::GRANTED, callback_result());
SetPermission(GURL(chrome::kChromeUINewTabPageThirdPartyURL),
PermissionType::GEOLOCATION, PermissionStatus::ASK);
EXPECT_TRUE(callback_called());
EXPECT_EQ(PermissionStatus::ASK, callback_result());
GetBrowserContext()
->GetPermissionController()
->UnsubscribeFromPermissionResultChange(subscription_id);
}