| // Copyright 2012 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "components/permissions/contexts/geolocation_permission_context.h" |
| |
| #include <stddef.h> |
| |
| #include <map> |
| #include <memory> |
| #include <set> |
| #include <string> |
| #include <utility> |
| #include <vector> |
| |
| #include "base/command_line.h" |
| #include "base/containers/id_map.h" |
| #include "base/functional/bind.h" |
| #include "base/functional/callback_helpers.h" |
| #include "base/gtest_prod_util.h" |
| #include "base/memory/ptr_util.h" |
| #include "base/memory/raw_ptr.h" |
| #include "base/run_loop.h" |
| #include "base/strings/stringprintf.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/synchronization/waitable_event.h" |
| #include "base/test/metrics/histogram_tester.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/simple_test_clock.h" |
| #include "base/time/clock.h" |
| #include "base/values.h" |
| #include "build/build_config.h" |
| #include "components/content_settings/browser/page_specific_content_settings.h" |
| #include "components/content_settings/browser/test_page_specific_content_settings_delegate.h" |
| #include "components/content_settings/core/browser/content_settings_observer.h" |
| #include "components/content_settings/core/browser/content_settings_utils.h" |
| #include "components/content_settings/core/browser/host_content_settings_map.h" |
| #include "components/content_settings/core/common/content_settings.h" |
| #include "components/content_settings/core/common/content_settings_types.h" |
| #include "components/content_settings/core/common/content_settings_utils.h" |
| #include "components/content_settings/core/common/features.h" |
| #include "components/permissions/content_setting_permission_context_base.h" |
| #include "components/permissions/features.h" |
| #include "components/permissions/permission_manager.h" |
| #include "components/permissions/permission_request.h" |
| #include "components/permissions/permission_request_data.h" |
| #include "components/permissions/permission_request_id.h" |
| #include "components/permissions/permission_request_manager.h" |
| #include "components/permissions/permission_util.h" |
| #include "components/permissions/resolvers/content_setting_permission_resolver.h" |
| #include "components/permissions/resolvers/geolocation_permission_resolver.h" |
| #include "components/permissions/test/mock_permission_prompt_factory.h" |
| #include "components/permissions/test/permission_test_util.h" |
| #include "components/permissions/test/test_permissions_client.h" |
| #include "components/prefs/testing_pref_service.h" |
| #include "content/public/browser/browser_context.h" |
| #include "content/public/browser/browser_thread.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/navigation_entry.h" |
| #include "content/public/browser/permission_controller.h" |
| #include "content/public/browser/permission_descriptor_util.h" |
| #include "content/public/browser/permission_result.h" |
| #include "content/public/browser/render_frame_host.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/test_browser_context.h" |
| #include "content/public/test/test_renderer_host.h" |
| #include "content/public/test/test_utils.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "services/device/public/cpp/device_features.h" |
| #include "services/device/public/cpp/geolocation/buildflags.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/permissions/permission_utils.h" |
| #include "url/origin.h" |
| |
| #if BUILDFLAG(IS_ANDROID) |
| #include "components/location/android/location_settings_dialog_outcome.h" |
| #include "components/location/android/mock_location_settings.h" |
| #include "components/permissions/contexts/geolocation_permission_context_android.h" |
| #include "components/prefs/pref_service.h" |
| #endif |
| |
| #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| #include "components/permissions/contexts/geolocation_permission_context_system.h" |
| #include "services/device/public/cpp/test/fake_geolocation_system_permission_manager.h" |
| #endif // BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| |
| using content::MockRenderProcessHost; |
| |
| namespace permissions { |
| namespace { |
| |
| using blink::mojom::PermissionStatus; |
| |
| class TestGeolocationPermissionContextDelegate |
| : public GeolocationPermissionContext::Delegate { |
| public: |
| explicit TestGeolocationPermissionContextDelegate( |
| content::BrowserContext* browser_context) { |
| #if BUILDFLAG(IS_ANDROID) |
| GeolocationPermissionContextAndroid::RegisterProfilePrefs( |
| prefs_.registry()); |
| #endif |
| } |
| |
| bool DecidePermission(const PermissionRequestData& request_data, |
| BrowserPermissionCallback* callback, |
| GeolocationPermissionContext* context) override { |
| return false; |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| bool IsInteractable(content::WebContents* web_contents) override { |
| return true; |
| } |
| |
| PrefService* GetPrefs(content::BrowserContext* browser_context) override { |
| return &prefs_; |
| } |
| |
| bool IsRequestingOriginDSE(content::BrowserContext* browser_context, |
| const GURL& requesting_origin) override { |
| return dse_origin_ && |
| dse_origin_.value() == url::Origin::Create(requesting_origin); |
| } |
| #endif |
| |
| void SetDSEOriginForTesting(const url::Origin& dse_origin) { |
| dse_origin_ = dse_origin; |
| } |
| |
| private: |
| TestingPrefServiceSimple prefs_; |
| std::optional<url::Origin> dse_origin_; |
| }; |
| } // namespace |
| |
| // GeolocationPermissionContextTests ------------------------------------------ |
| |
| class GeolocationPermissionContextTests |
| : public content::RenderViewHostTestHarness, |
| public permissions::Observer { |
| public: |
| GeolocationPermissionContextTests(); |
| |
| protected: |
| // RenderViewHostTestHarness: |
| void SetUp() override; |
| void TearDown() override; |
| std::unique_ptr<content::BrowserContext> CreateBrowserContext() override; |
| |
| PermissionRequestID RequestID(int request_id); |
| PermissionRequestID RequestIDForTab(int tab, int request_id); |
| |
| void RequestGeolocationPermission( |
| const PermissionRequestID& id, |
| const GURL& requesting_frame, |
| bool user_gesture, |
| bool embedded_permission_element_initiated = false); |
| |
| blink::mojom::PermissionStatus GetPermissionStatus( |
| const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
| const GURL& requesting_origin); |
| |
| blink::mojom::PermissionStatus GetPermissionStatus( |
| blink::PermissionType permission_descriptor, |
| const GURL& requesting_origin); |
| |
| void PermissionResponse(const PermissionRequestID& id, |
| content::PermissionResult permission_result); |
| void CheckPermissionMessageSent(int request_id, bool allowed); |
| void CheckPermissionMessageSentForTab(int tab, int request_id, bool allowed); |
| void CheckPermissionMessageSentInternal(MockRenderProcessHost* process, |
| int request_id, |
| bool allowed); |
| void AddNewTab(const GURL& url); |
| void CheckTabContentsState(const GURL& requesting_frame, |
| ContentSetting expected_content_setting); |
| void SetupRequestManager(content::WebContents* web_contents); |
| |
| // permissions::Observer: |
| void OnPermissionChanged(const ContentSettingsPattern& primary_pattern, |
| const ContentSettingsPattern& secondary_pattern, |
| ContentSettingsTypeSet content_type_set) override; |
| |
| #if BUILDFLAG(IS_ANDROID) |
| bool RequestPermissionIsLSDShown(const GURL& origin); |
| bool RequestPermissionIsLSDShownWithPermissionPrompt(const GURL& origin); |
| void AddDayOffsetForTesting(int days); |
| #endif |
| void RequestManagerDocumentLoadCompleted(); |
| void RequestManagerDocumentLoadCompleted(content::WebContents* web_contents); |
| ContentSetting GetGeolocationContentSetting(GURL frame_0, GURL frame_1); |
| void SetGeolocationContentSetting(GURL frame_0, |
| GURL frame_1, |
| ContentSetting content_setting); |
| bool HasActivePrompt(); |
| bool HasActivePrompt(content::WebContents* web_contents); |
| void AcceptPrompt(); |
| void AcceptPrompt(content::WebContents* web_contents); |
| void AcceptPromptThisTime(); |
| void DenyPrompt(); |
| void ClosePrompt(); |
| std::u16string GetPromptText(); |
| |
| TestPermissionsClient client_; |
| // owned by |BrowserContest::GetPermissionControllerDelegate()| |
| raw_ptr<GeolocationPermissionContext, AcrossTasksDanglingUntriaged> |
| geolocation_permission_context_ = nullptr; |
| // owned by |geolocation_permission_context_| |
| raw_ptr<TestGeolocationPermissionContextDelegate, |
| AcrossTasksDanglingUntriaged> |
| delegate_ = nullptr; |
| std::vector<std::unique_ptr<content::WebContents>> extra_tabs_; |
| std::vector<std::unique_ptr<MockPermissionPromptFactory>> |
| mock_permission_prompt_factories_; |
| |
| #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| raw_ptr<device::FakeGeolocationSystemPermissionManager> |
| fake_geolocation_system_permission_manager_; |
| #endif // BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| |
| // A map between renderer child id and a pair represending the bridge id and |
| // whether the requested permission was allowed. |
| std::map<int, std::pair<PermissionRequestID::RequestLocalId, bool>> |
| responses_; |
| int num_permission_updates_ = 0; |
| raw_ptr<ContentSettingsPattern> expected_primary_pattern_ = nullptr; |
| raw_ptr<ContentSettingsPattern> expected_secondary_pattern_ = nullptr; |
| |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| GeolocationPermissionContextTests::GeolocationPermissionContextTests() { |
| #if BUILDFLAG(IS_WIN) |
| feature_list_.InitAndEnableFeature(::features::kWinSystemLocationPermission); |
| #endif // BUILDFLAG(IS_WIN) |
| } |
| |
| PermissionRequestID GeolocationPermissionContextTests::RequestID( |
| int request_id) { |
| return PermissionRequestID( |
| web_contents()->GetPrimaryMainFrame()->GetGlobalId(), |
| PermissionRequestID::RequestLocalId(request_id)); |
| } |
| |
| PermissionRequestID GeolocationPermissionContextTests::RequestIDForTab( |
| int tab, |
| int request_id) { |
| return PermissionRequestID( |
| extra_tabs_[tab]->GetPrimaryMainFrame()->GetGlobalId(), |
| PermissionRequestID::RequestLocalId(request_id)); |
| } |
| |
| void GeolocationPermissionContextTests::RequestGeolocationPermission( |
| const PermissionRequestID& id, |
| const GURL& requesting_frame, |
| bool user_gesture, |
| bool embedded_permission_element_initiated) { |
| auto request_data = std::make_unique<permissions::PermissionRequestData>( |
| std::make_unique<ContentSettingPermissionResolver>( |
| ContentSettingsType::GEOLOCATION), |
| id, user_gesture, requesting_frame); |
| if (embedded_permission_element_initiated) { |
| request_data->embedded_permission_request_descriptor = |
| blink::mojom::EmbeddedPermissionRequestDescriptor::New(); |
| } |
| geolocation_permission_context_->RequestPermission( |
| std::move(request_data), |
| base::BindOnce(&GeolocationPermissionContextTests::PermissionResponse, |
| base::Unretained(this), id)); |
| content::RunAllTasksUntilIdle(); |
| } |
| |
| blink::mojom::PermissionStatus |
| GeolocationPermissionContextTests::GetPermissionStatus( |
| const blink::mojom::PermissionDescriptorPtr& permission_descriptor, |
| const GURL& requesting_origin) { |
| return browser_context() |
| ->GetPermissionController() |
| ->GetPermissionResultForOriginWithoutContext( |
| permission_descriptor, url::Origin::Create(requesting_origin)) |
| .status; |
| } |
| |
| blink::mojom::PermissionStatus |
| GeolocationPermissionContextTests::GetPermissionStatus( |
| blink::PermissionType permission, |
| const GURL& requesting_origin) { |
| return GetPermissionStatus( |
| content::PermissionDescriptorUtil:: |
| CreatePermissionDescriptorForPermissionType(permission), |
| requesting_origin); |
| } |
| |
| void GeolocationPermissionContextTests::PermissionResponse( |
| const PermissionRequestID& id, |
| content::PermissionResult permission_result) { |
| LOG(ERROR) << "GeolocationPermissionContextTests::PermissionResponse " |
| << id.ToString() << " " << permission_result.status; |
| responses_[id.global_render_frame_host_id().child_id] = |
| std::make_pair(id.request_local_id_for_testing(), |
| permission_result.status == PermissionStatus::GRANTED); |
| } |
| |
| void GeolocationPermissionContextTests::OnPermissionChanged( |
| const ContentSettingsPattern& primary_pattern, |
| const ContentSettingsPattern& secondary_pattern, |
| ContentSettingsTypeSet content_type_set) { |
| EXPECT_TRUE(primary_pattern.IsValid()); |
| EXPECT_TRUE(secondary_pattern.IsValid()); |
| EXPECT_EQ(*expected_primary_pattern_, primary_pattern); |
| EXPECT_EQ(*expected_secondary_pattern_, secondary_pattern); |
| EXPECT_EQ(content_type_set.GetType(), ContentSettingsType::GEOLOCATION); |
| num_permission_updates_++; |
| } |
| |
| void GeolocationPermissionContextTests::CheckPermissionMessageSent( |
| int request_id, |
| bool allowed) { |
| CheckPermissionMessageSentInternal(process(), request_id, allowed); |
| } |
| |
| void GeolocationPermissionContextTests::CheckPermissionMessageSentForTab( |
| int tab, |
| int request_id, |
| bool allowed) { |
| CheckPermissionMessageSentInternal( |
| static_cast<MockRenderProcessHost*>( |
| extra_tabs_[tab]->GetPrimaryMainFrame()->GetProcess()), |
| request_id, allowed); |
| } |
| |
| void GeolocationPermissionContextTests::CheckPermissionMessageSentInternal( |
| MockRenderProcessHost* process, |
| int request_id, |
| bool allowed) { |
| ASSERT_EQ(responses_.count(process->GetDeprecatedID()), 1U); |
| EXPECT_EQ(PermissionRequestID::RequestLocalId(request_id), |
| responses_[process->GetDeprecatedID()].first); |
| EXPECT_EQ(allowed, responses_[process->GetDeprecatedID()].second); |
| responses_.erase(process->GetDeprecatedID()); |
| } |
| |
| void GeolocationPermissionContextTests::AddNewTab(const GURL& url) { |
| std::unique_ptr<content::WebContents> new_tab = CreateTestWebContents(); |
| content::NavigationSimulator::NavigateAndCommitFromBrowser(new_tab.get(), |
| url); |
| SetupRequestManager(new_tab.get()); |
| |
| extra_tabs_.push_back(std::move(new_tab)); |
| } |
| |
| void GeolocationPermissionContextTests::CheckTabContentsState( |
| const GURL& requesting_frame, |
| ContentSetting expected_content_setting) { |
| auto* content_settings = |
| content_settings::PageSpecificContentSettings::GetForFrame( |
| web_contents()->GetPrimaryMainFrame()); |
| EXPECT_TRUE( |
| expected_content_setting == CONTENT_SETTING_BLOCK |
| ? content_settings->IsContentBlocked(ContentSettingsType::GEOLOCATION) |
| : content_settings->IsContentAllowed( |
| ContentSettingsType::GEOLOCATION)); |
| } |
| |
| std::unique_ptr<content::BrowserContext> |
| GeolocationPermissionContextTests::CreateBrowserContext() { |
| std::unique_ptr<content::TestBrowserContext> test_browser_contest = |
| std::make_unique<content::TestBrowserContext>(); |
| test_browser_contest->SetPermissionControllerDelegate( |
| permissions::GetPermissionControllerDelegate(test_browser_contest.get())); |
| return test_browser_contest; |
| } |
| |
| void GeolocationPermissionContextTests::SetUp() { |
| RenderViewHostTestHarness::SetUp(); |
| |
| content_settings::PageSpecificContentSettings::CreateForWebContents( |
| web_contents(), |
| std::make_unique< |
| content_settings::TestPageSpecificContentSettingsDelegate>( |
| /*prefs=*/nullptr, |
| PermissionsClient::Get()->GetSettingsMap(browser_context()))); |
| |
| auto delegate = std::make_unique<TestGeolocationPermissionContextDelegate>( |
| browser_context()); |
| delegate_ = delegate.get(); |
| |
| #if BUILDFLAG(IS_ANDROID) |
| auto context = std::make_unique<GeolocationPermissionContextAndroid>( |
| browser_context(), std::move(delegate), /*is_regular_profile=*/false, |
| std::make_unique<MockLocationSettings>()); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/true); |
| MockLocationSettings::SetCanPromptForAndroidPermission(true); |
| MockLocationSettings::SetLocationSettingsDialogStatus(false /* enabled */, |
| GRANTED); |
| MockLocationSettings::ClearHasShownLocationSettingsDialog(); |
| #elif BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| auto fake_geolocation_system_permission_manager = |
| std::make_unique<device::FakeGeolocationSystemPermissionManager>(); |
| fake_geolocation_system_permission_manager_ = |
| fake_geolocation_system_permission_manager.get(); |
| fake_geolocation_system_permission_manager->SetSystemPermission( |
| device::LocationSystemPermissionStatus::kAllowed); |
| device::FakeGeolocationSystemPermissionManager::SetInstance( |
| std::move(fake_geolocation_system_permission_manager)); |
| auto context = std::make_unique<GeolocationPermissionContextSystem>( |
| browser_context(), std::move(delegate)); |
| #else |
| auto context = std::make_unique<GeolocationPermissionContext>( |
| browser_context(), std::move(delegate)); |
| #endif |
| SetupRequestManager(web_contents()); |
| |
| geolocation_permission_context_ = context.get(); |
| |
| PermissionManager* permission_manager = static_cast<PermissionManager*>( |
| browser_context()->GetPermissionControllerDelegate()); |
| #if BUILDFLAG(IS_ANDROID) |
| permission_manager->PermissionContextsForTesting() |
| [base::FeatureList::IsEnabled( |
| content_settings::features::kApproximateGeolocationPermission) |
| ? ContentSettingsType::GEOLOCATION_WITH_OPTIONS |
| : ContentSettingsType::GEOLOCATION] = std::move(context); |
| #else |
| permission_manager |
| ->PermissionContextsForTesting()[ContentSettingsType::GEOLOCATION] = |
| std::move(context); |
| #endif |
| } |
| |
| void GeolocationPermissionContextTests::TearDown() { |
| mock_permission_prompt_factories_.clear(); |
| extra_tabs_.clear(); |
| DeleteContents(); |
| RenderViewHostTestHarness::TearDown(); |
| } |
| |
| void GeolocationPermissionContextTests::SetupRequestManager( |
| content::WebContents* web_contents) { |
| // Create PermissionRequestManager. |
| PermissionRequestManager::CreateForWebContents(web_contents); |
| PermissionRequestManager* permission_request_manager = |
| PermissionRequestManager::FromWebContents(web_contents); |
| |
| // Create a MockPermissionPromptFactory for the PermissionRequestManager. |
| mock_permission_prompt_factories_.push_back( |
| std::make_unique<MockPermissionPromptFactory>( |
| permission_request_manager)); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| |
| bool GeolocationPermissionContextTests::RequestPermissionIsLSDShown( |
| const GURL& origin) { |
| NavigateAndCommit(origin); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::ClearHasShownLocationSettingsDialog(); |
| RequestGeolocationPermission(RequestID(0), origin, true); |
| |
| return MockLocationSettings::HasShownLocationSettingsDialog(); |
| } |
| |
| bool GeolocationPermissionContextTests:: |
| RequestPermissionIsLSDShownWithPermissionPrompt(const GURL& origin) { |
| NavigateAndCommit(origin); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::ClearHasShownLocationSettingsDialog(); |
| RequestGeolocationPermission(RequestID(0), origin, true); |
| |
| EXPECT_TRUE(HasActivePrompt()); |
| AcceptPrompt(); |
| |
| return MockLocationSettings::HasShownLocationSettingsDialog(); |
| } |
| |
| void GeolocationPermissionContextTests::AddDayOffsetForTesting(int days) { |
| GeolocationPermissionContextAndroid::AddDayOffsetForTesting(days); |
| } |
| #endif |
| |
| void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted() { |
| GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted( |
| web_contents()); |
| } |
| |
| void GeolocationPermissionContextTests::RequestManagerDocumentLoadCompleted( |
| content::WebContents* web_contents) { |
| PermissionRequestManager::FromWebContents(web_contents) |
| ->DocumentOnLoadCompletedInPrimaryMainFrame(); |
| } |
| |
| ContentSetting GeolocationPermissionContextTests::GetGeolocationContentSetting( |
| GURL frame_0, |
| GURL frame_1) { |
| return PermissionsClient::Get() |
| ->GetSettingsMap(browser_context()) |
| ->GetContentSetting(frame_0, frame_1, ContentSettingsType::GEOLOCATION); |
| } |
| |
| void GeolocationPermissionContextTests::SetGeolocationContentSetting( |
| GURL frame_0, |
| GURL frame_1, |
| ContentSetting content_setting) { |
| return PermissionsClient::Get() |
| ->GetSettingsMap(browser_context()) |
| ->SetContentSettingDefaultScope( |
| frame_0, frame_1, ContentSettingsType::GEOLOCATION, content_setting); |
| } |
| |
| bool GeolocationPermissionContextTests::HasActivePrompt() { |
| return HasActivePrompt(web_contents()); |
| } |
| |
| bool GeolocationPermissionContextTests::HasActivePrompt( |
| content::WebContents* web_contents) { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents); |
| return manager->IsRequestInProgress(); |
| } |
| |
| void GeolocationPermissionContextTests::AcceptPrompt() { |
| return AcceptPrompt(web_contents()); |
| } |
| |
| void GeolocationPermissionContextTests::AcceptPrompt( |
| content::WebContents* web_contents) { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents); |
| manager->Accept(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void GeolocationPermissionContextTests::AcceptPromptThisTime() { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents()); |
| manager->AcceptThisTime(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void GeolocationPermissionContextTests::DenyPrompt() { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents()); |
| manager->Deny(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| void GeolocationPermissionContextTests::ClosePrompt() { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents()); |
| manager->Dismiss(); |
| base::RunLoop().RunUntilIdle(); |
| } |
| |
| std::u16string GeolocationPermissionContextTests::GetPromptText() { |
| PermissionRequestManager* manager = |
| PermissionRequestManager::FromWebContents(web_contents()); |
| auto& request = manager->Requests().front(); |
| #if BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) |
| return request |
| ->GetDialogAnnotatedMessageText( |
| /*embedding_origin=*/request->requesting_origin()) |
| .text; |
| #else |
| return base::ASCIIToUTF16(request->requesting_origin().spec()) + |
| request->GetMessageTextFragment(); |
| #endif // BUILDFLAG(IS_ANDROID) || BUILDFLAG(IS_IOS) |
| } |
| |
| // Tests ---------------------------------------------------------------------- |
| |
| TEST_F(GeolocationPermissionContextTests, SinglePermissionPrompt) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, |
| SinglePermissionPromptFailsOnInsecureOrigin) { |
| GURL requesting_frame("http://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_FALSE(HasActivePrompt()); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| // Tests concerning Android location settings permission |
| TEST_F(GeolocationPermissionContextTests, GeolocationEnabledDisabled) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| base::HistogramTester histograms; |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/true); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| EXPECT_TRUE(HasActivePrompt()); |
| histograms.ExpectTotalCount("Permissions.Action.Geolocation", 0); |
| |
| content::NavigationSimulator::Reload(web_contents()); |
| histograms.ExpectUniqueSample("Permissions.Action.Geolocation", |
| static_cast<int>(PermissionAction::IGNORED), 1); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| MockLocationSettings::SetCanPromptForAndroidPermission(false); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| histograms.ExpectUniqueSample("Permissions.Action.Geolocation", |
| static_cast<int>(PermissionAction::IGNORED), 1); |
| EXPECT_FALSE(HasActivePrompt()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, AndroidEnabledCanPromptAndAccept) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| base::HistogramTester histograms; |
| AcceptPrompt(); |
| histograms.ExpectUniqueSample("Permissions.Action.Geolocation", |
| static_cast<int>(PermissionAction::GRANTED), 1); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, |
| AndroidEnabledCanPromptAndAcceptThisTime) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| base::HistogramTester histograms; |
| AcceptPromptThisTime(); |
| |
| histograms.ExpectUniqueSample( |
| "Permissions.Action.Geolocation", |
| static_cast<int>(PermissionAction::GRANTED_ONCE), 1); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, AndroidEnabledCantPrompt) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| MockLocationSettings::SetCanPromptForAndroidPermission(false); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| EXPECT_FALSE(HasActivePrompt()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SystemLocationOffLSDDisabled) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| EXPECT_FALSE(HasActivePrompt()); |
| EXPECT_FALSE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SystemLocationOnNoLSD) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| AcceptPrompt(); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| EXPECT_FALSE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SystemLocationOffLSDAccept) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| GRANTED); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| AcceptPrompt(); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| EXPECT_TRUE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SystemLocationOffLSDReject) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| ASSERT_TRUE(HasActivePrompt()); |
| AcceptPrompt(); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_BLOCK); |
| CheckPermissionMessageSent(0, false); |
| EXPECT_TRUE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, LSDBackOffDifferentSites) { |
| GURL requesting_frame_1("https://www.example.com/geolocation"); |
| GURL requesting_frame_2("https://www.example-2.com/geolocation"); |
| GURL requesting_frame_dse("https://www.dse.com/geolocation"); |
| |
| delegate_->SetDSEOriginForTesting(url::Origin::Create(requesting_frame_dse)); |
| |
| // Set all origin geolocation permissions to ALLOW. |
| SetGeolocationContentSetting(requesting_frame_1, requesting_frame_1, |
| CONTENT_SETTING_ALLOW); |
| SetGeolocationContentSetting(requesting_frame_2, requesting_frame_2, |
| CONTENT_SETTING_ALLOW); |
| SetGeolocationContentSetting(requesting_frame_dse, requesting_frame_dse, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| |
| // Now permission requests should trigger the LSD, but the LSD will be |
| // denied, putting the requesting origins into backoff. Check that the |
| // two non-DSE origins share the same backoff, which is distinct to |
| // the DSE origin. First, cancel a LSD prompt on the first non-DSE |
| // origin to go into backoff. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame_1)); |
| |
| // Now check that the LSD is prevented on this origin. |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame_1)); |
| |
| // Now ask on the other non-DSE origin and check backoff prevented the |
| // prompt. |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame_2)); |
| |
| // Now request on the DSE and check that the LSD is shown, as the |
| // non-DSE backoff should not apply. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame_dse)); |
| |
| // Now check that the DSE is in backoff. |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame_dse)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, LSDBackOffTiming) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| |
| // First, cancel a LSD prompt on the first non-DSE origin to go into |
| // backoff. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check the LSD is prevented in 6 days time. |
| AddDayOffsetForTesting(6); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check it is shown in one more days time, but then not straight |
| // after.. |
| AddDayOffsetForTesting(1); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check that it isn't shown 29 days after that. |
| AddDayOffsetForTesting(29); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check it is shown in one more days time, but then not straight |
| // after.. |
| AddDayOffsetForTesting(1); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check that it isn't shown 89 days after that. |
| AddDayOffsetForTesting(89); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check it is shown in one more days time, but then not straight |
| // after.. |
| AddDayOffsetForTesting(1); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check that it isn't shown 89 days after that. |
| AddDayOffsetForTesting(89); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check it is shown in one more days time, but then not straight |
| // after.. |
| AddDayOffsetForTesting(1); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, LSDBackOffPermissionStatus) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| const auto geolocation_permission_descriptor = content:: |
| PermissionDescriptorUtil::CreatePermissionDescriptorForPermissionType( |
| blink::PermissionType::GEOLOCATION); |
| |
| // The permission status should reflect that the LSD will be shown. |
| ASSERT_EQ( |
| PermissionStatus::ASK, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Now that the LSD is in backoff, the permission status should |
| // reflect it. |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| ASSERT_EQ( |
| PermissionStatus::DENIED, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, LSDBackOffAskPromptsDespiteBackOff) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| |
| // First, cancel a LSD prompt on the first non-DSE origin to go into |
| // backoff. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Set the content setting back to ASK. The permission status should |
| // be prompt, and the LSD prompt should now be shown. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ASK); |
| ASSERT_EQ(PermissionStatus::ASK, |
| GetPermissionStatus(content::PermissionDescriptorUtil:: |
| CreatePermissionDescriptorForPermissionType( |
| blink::PermissionType::GEOLOCATION), |
| requesting_frame)); |
| EXPECT_TRUE( |
| RequestPermissionIsLSDShownWithPermissionPrompt(requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, |
| LSDBackOffAcceptPermissionResetsBackOff) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| |
| // First, get into the highest backoff state. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(7); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(30); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(90); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Now accept a permissions prompt. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ASK); |
| EXPECT_TRUE( |
| RequestPermissionIsLSDShownWithPermissionPrompt(requesting_frame)); |
| |
| // Denying the LSD stops the content setting from being stored, so |
| // explicitly set it to ALLOW. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // And check that back in the lowest backoff state. |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(7); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, LSDBackOffAcceptLSDResetsBackOff) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| |
| // Turn off system location but allow the LSD to be shown, and denied. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| |
| // First, get into the highest backoff state. |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(7); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(30); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Now accept the LSD. |
| AddDayOffsetForTesting(90); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| GRANTED); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| |
| // Check that not in backoff, and that at the lowest backoff state. |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| EXPECT_FALSE(RequestPermissionIsLSDShown(requesting_frame)); |
| AddDayOffsetForTesting(7); |
| EXPECT_TRUE(RequestPermissionIsLSDShown(requesting_frame)); |
| } |
| |
| // Test that LSD won't be shown if there is an embedded permission |
| // element in progress that will trigger LSD when finished. |
| TEST_F(GeolocationPermissionContextTests, |
| SystemLocationDelayedUntilPepcRequestResolved) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| MockLocationSettings::SetCanPromptForAndroidPermission(true); |
| |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true, |
| /*embedded_permission_element_initiated=*/true); |
| |
| ASSERT_TRUE(HasActivePrompt()); |
| ASSERT_FALSE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| |
| RequestGeolocationPermission(RequestID(1), requesting_frame, true); |
| |
| ASSERT_FALSE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| ASSERT_TRUE(HasActivePrompt()); |
| |
| // Simulate a PEPC request which will also result in location |
| // permission being granted. |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/true); |
| AcceptPrompt(); |
| content::RunAllTasksUntilIdle(); |
| |
| ASSERT_FALSE(MockLocationSettings::HasShownLocationSettingsDialog()); |
| CheckPermissionMessageSent(1, true); |
| } |
| |
| #endif // BUILDFLAG(IS_ANDROID) |
| |
| TEST_F(GeolocationPermissionContextTests, HashIsIgnored) { |
| GURL url_a("https://www.example.com/geolocation#a"); |
| GURL url_b("https://www.example.com/geolocation#b"); |
| |
| // Navigate to the first url. |
| NavigateAndCommit(url_a); |
| RequestManagerDocumentLoadCompleted(); |
| |
| // Check permission is requested. |
| ASSERT_FALSE(HasActivePrompt()); |
| const bool user_gesture = true; |
| RequestGeolocationPermission(RequestID(0), url_a, user_gesture); |
| ASSERT_TRUE(HasActivePrompt()); |
| |
| // Change the hash, we'll still be on the same page. |
| NavigateAndCommit(url_b); |
| RequestManagerDocumentLoadCompleted(); |
| |
| // Accept. |
| AcceptPrompt(); |
| CheckTabContentsState(url_a, CONTENT_SETTING_ALLOW); |
| CheckTabContentsState(url_b, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, DISABLED_PermissionForFileScheme) { |
| // TODO(felt): The bubble is rejecting file:// permission requests. |
| // Fix and enable this test. crbug.com/444047 |
| GURL requesting_frame("file://example/geolocation.html"); |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| |
| // Check permission is requested. |
| ASSERT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| EXPECT_TRUE(HasActivePrompt()); |
| |
| // Accept the frame. |
| AcceptPrompt(); |
| CheckTabContentsState(requesting_frame, CONTENT_SETTING_ALLOW); |
| CheckPermissionMessageSent(0, true); |
| |
| // Make sure the setting is not stored. |
| EXPECT_EQ(CONTENT_SETTING_ASK, |
| GetGeolocationContentSetting(requesting_frame, requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, CancelGeolocationPermissionRequest) { |
| GURL frame_0("https://www.example.com/geolocation"); |
| EXPECT_EQ(CONTENT_SETTING_ASK, |
| GetGeolocationContentSetting(frame_0, frame_0)); |
| |
| NavigateAndCommit(frame_0); |
| RequestManagerDocumentLoadCompleted(); |
| |
| ASSERT_FALSE(HasActivePrompt()); |
| |
| RequestGeolocationPermission(RequestID(0), frame_0, true); |
| |
| ASSERT_TRUE(HasActivePrompt()); |
| std::u16string text_0 = GetPromptText(); |
| ASSERT_FALSE(text_0.empty()); |
| |
| // Simulate the frame going away; the request should be removed. |
| ClosePrompt(); |
| |
| // Ensure permission isn't persisted. |
| EXPECT_EQ(CONTENT_SETTING_ASK, |
| GetGeolocationContentSetting(frame_0, frame_0)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, InvalidURL) { |
| // Navigate to the first url. |
| GURL invalid_embedder("about:blank"); |
| GURL requesting_frame; |
| NavigateAndCommit(invalid_embedder); |
| RequestManagerDocumentLoadCompleted(); |
| |
| // Nothing should be displayed. |
| EXPECT_FALSE(HasActivePrompt()); |
| RequestGeolocationPermission(RequestID(0), requesting_frame, true); |
| EXPECT_FALSE(HasActivePrompt()); |
| CheckPermissionMessageSent(0, false); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SameOriginMultipleTabs) { |
| GURL url_a("https://www.example.com/geolocation"); |
| GURL url_b("https://www.example-2.com/geolocation"); |
| NavigateAndCommit(url_a); // Tab A0 |
| AddNewTab(url_b); // Tab B (extra_tabs_[0]) |
| AddNewTab(url_a); // Tab A1 (extra_tabs_[1]) |
| RequestManagerDocumentLoadCompleted(); |
| RequestManagerDocumentLoadCompleted(extra_tabs_[0].get()); |
| RequestManagerDocumentLoadCompleted(extra_tabs_[1].get()); |
| |
| // Request permission in all three tabs. |
| RequestGeolocationPermission(RequestID(0), url_a, true); |
| RequestGeolocationPermission(RequestIDForTab(0, 0), url_b, true); |
| RequestGeolocationPermission(RequestIDForTab(1, 0), url_a, true); |
| ASSERT_TRUE(HasActivePrompt()); // For A0. |
| ASSERT_TRUE(HasActivePrompt(extra_tabs_[0].get())); |
| ASSERT_TRUE(HasActivePrompt(extra_tabs_[1].get())); |
| |
| // Accept the permission in tab A0. |
| AcceptPrompt(); |
| CheckPermissionMessageSent(0, true); |
| // Because they're the same origin, this should cause tab A1's prompt |
| // to disappear, but it doesn't: crbug.com/443013. |
| // TODO(felt): Update this test when the bubble's behavior is changed. |
| // Either way, tab B should still have a pending permission request. |
| ASSERT_TRUE(HasActivePrompt(extra_tabs_[0].get())); |
| ASSERT_TRUE(HasActivePrompt(extra_tabs_[1].get())); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, TabDestroyed) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| EXPECT_EQ(CONTENT_SETTING_ASK, |
| GetGeolocationContentSetting(requesting_frame, requesting_frame)); |
| |
| NavigateAndCommit(requesting_frame); |
| RequestManagerDocumentLoadCompleted(); |
| |
| // Request permission for two frames. |
| RequestGeolocationPermission(RequestID(0), requesting_frame, false); |
| |
| ASSERT_TRUE(HasActivePrompt()); |
| EXPECT_EQ(CONTENT_SETTING_ASK, |
| GetGeolocationContentSetting(requesting_frame, requesting_frame)); |
| } |
| |
| #if BUILDFLAG(IS_ANDROID) |
| TEST_F(GeolocationPermissionContextTests, GeolocationStatusAndroidDisabled) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| const auto geolocation_permission_descriptor = content:: |
| PermissionDescriptorUtil::CreatePermissionDescriptorForPermissionType( |
| blink::PermissionType::GEOLOCATION); |
| |
| // With the Android permission off, but location allowed for a domain, |
| // the permission status should be ASK. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/false, |
| /*has_android_fine_location_permission=*/false, |
| /*is_system_location_setting_enabled=*/true); |
| ASSERT_EQ( |
| PermissionStatus::ASK, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| |
| // With the Android permission off, and location blocked for a domain, |
| // the permission status should still be BLOCK. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_BLOCK); |
| ASSERT_EQ( |
| PermissionStatus::DENIED, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| |
| // With the Android permission off, and location prompt for a domain, |
| // the permission status should still be ASK. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ASK); |
| ASSERT_EQ( |
| PermissionStatus::ASK, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, GeolocationStatusSystemDisabled) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| |
| // With the system permission off, but location allowed for a domain, |
| // the permission status should be reflect whether the LSD can be |
| // shown. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| MockLocationSettings::SetLocationStatus( |
| /*has_android_coarse_location_permission=*/true, |
| /*has_android_fine_location_permission=*/true, |
| /*is_system_location_setting_enabled=*/false); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| DENIED); |
| const auto geolocation_permission_descriptor = content:: |
| PermissionDescriptorUtil::CreatePermissionDescriptorForPermissionType( |
| blink::PermissionType::GEOLOCATION); |
| |
| ASSERT_EQ( |
| PermissionStatus::ASK, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| |
| MockLocationSettings::SetLocationSettingsDialogStatus(false /* enabled */, |
| GRANTED); |
| ASSERT_EQ( |
| PermissionStatus::DENIED, |
| GetPermissionStatus(geolocation_permission_descriptor, requesting_frame)); |
| |
| // The result should be the same if the location permission is ASK. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ASK); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| GRANTED); |
| ASSERT_EQ(PermissionStatus::ASK, |
| GetPermissionStatus(blink::PermissionType::GEOLOCATION, |
| requesting_frame)); |
| |
| MockLocationSettings::SetLocationSettingsDialogStatus(false /* enabled */, |
| GRANTED); |
| ASSERT_EQ(PermissionStatus::DENIED, |
| GetPermissionStatus(blink::PermissionType::GEOLOCATION, |
| requesting_frame)); |
| |
| // With the Android permission off, and location blocked for a domain, |
| // the permission status should still be BLOCK. |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_BLOCK); |
| MockLocationSettings::SetLocationSettingsDialogStatus(true /* enabled */, |
| GRANTED); |
| ASSERT_EQ(PermissionStatus::DENIED, |
| GetPermissionStatus(blink::PermissionType::GEOLOCATION, |
| requesting_frame)); |
| } |
| |
| struct PermissionStateTestEntry { |
| bool has_coarse_location; |
| bool has_fine_location; |
| int bucket; |
| } kPermissionStateTestEntries[] = { |
| {/*has_coarse_location=*/false, /*has_fine_location=*/false, |
| /*bucket=*/0}, |
| {/*has_coarse_location=*/true, /*has_fine_location=*/false, |
| /*bucket=*/1}, |
| {/*has_coarse_location=*/false, /*has_fine_location=*/true, |
| /*bucket=*/2}, |
| {/*has_coarse_location=*/true, /*has_fine_location=*/true, |
| /*bucket=*/2}, |
| }; |
| |
| class GeolocationAndroidPermissionRegularProfileTest |
| : public content::RenderViewHostTestHarness, |
| public testing::WithParamInterface<PermissionStateTestEntry> {}; |
| |
| TEST_P(GeolocationAndroidPermissionRegularProfileTest, Histogram) { |
| const auto& [has_coarse_location, has_fine_location, bucket] = GetParam(); |
| MockLocationSettings::SetLocationStatus( |
| has_coarse_location, has_fine_location, |
| /*is_system_location_setting_enabled=*/true); |
| base::HistogramTester histogram_tester; |
| GeolocationPermissionContextAndroid context( |
| browser_context(), /*delegate=*/nullptr, |
| /*is_regular_profile=*/true, std::make_unique<MockLocationSettings>()); |
| histogram_tester.ExpectUniqueSample( |
| "Geolocation.Android.LocationPermissionState", bucket, |
| /*expected_bucket_count=*/1); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| GeolocationAndroidPermissionRegularProfileTests, |
| GeolocationAndroidPermissionRegularProfileTest, |
| testing::ValuesIn(kPermissionStateTestEntries), |
| [](const testing::TestParamInfo<PermissionStateTestEntry>& info) { |
| return base::StringPrintf("Location%sFineLocation%s", |
| info.param.has_coarse_location ? "On" : "Off", |
| info.param.has_fine_location ? "On" : "Off"); |
| }); |
| |
| using GeolocationAndroidPermissionIrregularProfileTest = |
| content::RenderViewHostTestHarness; |
| |
| TEST_F(GeolocationAndroidPermissionIrregularProfileTest, DoesNotRecord) { |
| base::HistogramTester histogram_tester; |
| GeolocationPermissionContextAndroid context( |
| browser_context(), /*delegate=*/nullptr, |
| /*is_regular_profile=*/false, std::make_unique<MockLocationSettings>()); |
| histogram_tester.ExpectTotalCount( |
| "Geolocation.Android.LocationPermissionState", |
| /*expected_count=*/0); |
| } |
| #endif // BUILDFLAG(IS_ANDROID) |
| |
| #if BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| TEST_F(GeolocationPermissionContextTests, |
| AllSystemAndSitePermissionCombinations) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| |
| const struct { |
| const LocationSystemPermissionStatus system_permission; |
| const ContentSetting site_permission; |
| const PermissionStatus expected_effective_site_permission; |
| } kTestCases[] = { |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kDenied), |
| ContentSetting(CONTENT_SETTING_ASK), PermissionStatus::ASK}, |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kDenied), |
| ContentSetting(CONTENT_SETTING_BLOCK), PermissionStatus::DENIED}, |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kDenied), |
| ContentSetting(CONTENT_SETTING_ALLOW), PermissionStatus::DENIED}, |
| {LocationSystemPermissionStatus( |
| LocationSystemPermissionStatus::kNotDetermined), |
| ContentSetting(CONTENT_SETTING_ASK), PermissionStatus::ASK}, |
| {LocationSystemPermissionStatus( |
| LocationSystemPermissionStatus::kNotDetermined), |
| ContentSetting(CONTENT_SETTING_BLOCK), PermissionStatus::DENIED}, |
| {LocationSystemPermissionStatus( |
| LocationSystemPermissionStatus::kNotDetermined), |
| ContentSetting(CONTENT_SETTING_ALLOW), PermissionStatus::ASK}, |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kAllowed), |
| ContentSetting(CONTENT_SETTING_ASK), PermissionStatus::ASK}, |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kAllowed), |
| ContentSetting(CONTENT_SETTING_BLOCK), PermissionStatus::DENIED}, |
| {LocationSystemPermissionStatus(LocationSystemPermissionStatus::kAllowed), |
| ContentSetting(CONTENT_SETTING_ALLOW), PermissionStatus::GRANTED}, |
| }; |
| |
| for (auto test_case : kTestCases) { |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| test_case.site_permission); |
| fake_geolocation_system_permission_manager_->SetSystemPermission( |
| test_case.system_permission); |
| base::RunLoop().RunUntilIdle(); |
| ASSERT_EQ(test_case.expected_effective_site_permission, |
| GetPermissionStatus(blink::PermissionType::GEOLOCATION, |
| requesting_frame)); |
| } |
| } |
| |
| TEST_F(GeolocationPermissionContextTests, SystemPermissionUpdates) { |
| GURL requesting_frame("https://www.example.com/geolocation"); |
| ContentSettingsPattern primary_pattern = |
| ContentSettingsPattern::FromURLNoWildcard(requesting_frame); |
| ContentSettingsPattern secondary_pattern = ContentSettingsPattern::Wildcard(); |
| |
| geolocation_permission_context_->AddObserver(this); |
| expected_primary_pattern_ = &primary_pattern; |
| expected_secondary_pattern_ = &secondary_pattern; |
| SetGeolocationContentSetting(requesting_frame, requesting_frame, |
| CONTENT_SETTING_ALLOW); |
| ASSERT_EQ(1, num_permission_updates_); |
| primary_pattern = ContentSettingsPattern::Wildcard(); |
| fake_geolocation_system_permission_manager_->SetSystemPermission( |
| LocationSystemPermissionStatus::kDenied); |
| fake_geolocation_system_permission_manager_->SetSystemPermission( |
| LocationSystemPermissionStatus::kAllowed); |
| base::RunLoop().RunUntilIdle(); |
| ASSERT_EQ(3, num_permission_updates_); |
| geolocation_permission_context_->RemoveObserver(this); |
| } |
| #endif // BUILDFLAG(OS_LEVEL_GEOLOCATION_PERMISSION_SUPPORTED) |
| |
| } // namespace permissions |