| // Copyright 2020 The Chromium Authors |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <memory> |
| #include <string> |
| #include <tuple> |
| #include <utility> |
| |
| #include "base/memory/raw_ptr.h" |
| #include "base/notimplemented.h" |
| #include "base/test/bind.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/test/test_future.h" |
| #include "base/test/test_timeouts.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/browsing_data/chrome_browsing_data_model_delegate.h" |
| #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate.h" |
| #include "chrome/browser/browsing_data/chrome_browsing_data_remover_delegate_factory.h" |
| #include "chrome/browser/device_api/device_attribute_api.h" |
| #include "chrome/browser/device_api/device_service_impl.h" |
| #include "chrome/browser/ui/web_applications/test/isolated_web_app_test_utils.h" |
| #include "chrome/browser/web_applications/isolated_web_apps/isolated_web_app_url_info.h" |
| #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_builder.h" |
| #include "chrome/browser/web_applications/isolated_web_apps/test/isolated_web_app_test.h" |
| #include "chrome/browser/web_applications/isolated_web_apps/test/iwa_test_server_configurator.h" |
| #include "chrome/browser/web_applications/isolated_web_apps/test/policy_generator.h" |
| #include "chrome/browser/web_applications/policy/web_app_policy_constants.h" |
| #include "chrome/browser/web_applications/test/fake_web_contents_manager.h" |
| #include "chrome/browser/web_applications/test/web_app_install_test_utils.h" |
| #include "chrome/browser/web_applications/test/web_app_test.h" |
| #include "chrome/browser/web_applications/test/web_app_test_observers.h" |
| #include "chrome/browser/web_applications/web_app_command_scheduler.h" |
| #include "chrome/browser/web_applications/web_app_helpers.h" |
| #include "chrome/browser/web_applications/web_app_provider.h" |
| #include "chrome/common/pref_names.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/chrome_render_view_host_test_harness.h" |
| #include "chrome/test/base/testing_profile.h" |
| #include "components/account_id/account_id.h" |
| #include "components/content_settings/core/common/pref_names.h" |
| #include "components/permissions/features.h" |
| #include "components/permissions/test/permission_test_util.h" |
| #include "components/prefs/scoped_user_pref_update.h" |
| #include "components/profile_metrics/browser_profile_type.h" |
| #include "components/sync_preferences/testing_pref_service_syncable.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/test/browser_task_environment.h" |
| #include "content/public/test/navigation_simulator.h" |
| #include "content/public/test/web_contents_tester.h" |
| #include "mojo/public/cpp/test_support/fake_message_dispatch_context.h" |
| #include "mojo/public/cpp/test_support/test_utils.h" |
| #include "net/base/features.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "third_party/blink/public/common/features_generated.h" |
| #include "url/gurl.h" |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| #include "base/test/scoped_command_line.h" |
| #include "chrome/browser/ash/app_mode/web_app/kiosk_web_app_manager.h" |
| #include "chrome/browser/ash/login/users/fake_chrome_user_manager.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "components/user_manager/scoped_user_manager.h" |
| #include "components/user_manager/test_helper.h" |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| namespace { |
| |
| constexpr char kDefaultAppInstallUrl[] = "https://example.com/install"; |
| constexpr char kTrustedUrl[] = "https://example.com/sample"; |
| constexpr char kUntrustedUrl[] = "https://non-example.com/sample"; |
| constexpr char kUserEmail[] = "user-email@example.com"; |
| constexpr char kNotAffiliatedErrorMessage[] = |
| "This web API is not allowed if the current profile is not affiliated."; |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| constexpr char kKioskAppInstallUrl[] = "https://kiosk.com/install"; |
| constexpr char kKioskAppUrl[] = "https://kiosk.com/sample"; |
| constexpr char kInvalidKioskAppUrl[] = "https://invalid-kiosk.com/sample"; |
| constexpr char kNoDeviceAttributesPermissionErrorMessage[] = |
| "The current origin cannot use this web API because it was not granted the " |
| "'device-attributes' permission."; |
| constexpr char kPermissionsPolicyMojoErrorMessage[] = |
| "Permissions policy blocks access to Device Attributes."; |
| #endif |
| |
| } // namespace |
| |
| namespace { |
| |
| using Result = blink::mojom::DeviceAttributeResult; |
| |
| constexpr char kAnnotatedAssetId[] = "annotated_asset_id"; |
| constexpr char kAnnotatedLocation[] = "annotated_location"; |
| constexpr char kDirectoryApiId[] = "directory_api_id"; |
| constexpr char kHostname[] = "hostname"; |
| constexpr char kSerialNumber[] = "serial_number"; |
| |
| class FakeDeviceAttributeApi : public DeviceAttributeApi { |
| public: |
| FakeDeviceAttributeApi() = default; |
| ~FakeDeviceAttributeApi() override = default; |
| |
| // This method forwards calls to DeviceAttributesApiImpl to the test the |
| // actual error reported by the service. |
| void ReportNotAllowedError( |
| base::OnceCallback<void(blink::mojom::DeviceAttributeResultPtr)> callback) |
| override { |
| device_attributes_api_.ReportNotAllowedError(std::move(callback)); |
| } |
| |
| // This method forwards calls to DeviceAttributesApiImpl to the test the |
| // actual error reported by the service. |
| void ReportNotAffiliatedError( |
| base::OnceCallback<void(blink::mojom::DeviceAttributeResultPtr)> callback) |
| override { |
| device_attributes_api_.ReportNotAffiliatedError(std::move(callback)); |
| } |
| |
| void GetDirectoryId(blink::mojom::DeviceAPIService::GetDirectoryIdCallback |
| callback) override { |
| std::move(callback).Run(Result::NewAttribute(kDirectoryApiId)); |
| } |
| |
| void GetHostname( |
| blink::mojom::DeviceAPIService::GetHostnameCallback callback) override { |
| std::move(callback).Run(Result::NewAttribute(kHostname)); |
| } |
| |
| void GetSerialNumber(blink::mojom::DeviceAPIService::GetSerialNumberCallback |
| callback) override { |
| std::move(callback).Run(Result::NewAttribute(kSerialNumber)); |
| } |
| |
| void GetAnnotatedAssetId( |
| blink::mojom::DeviceAPIService::GetAnnotatedAssetIdCallback callback) |
| override { |
| std::move(callback).Run(Result::NewAttribute(kAnnotatedAssetId)); |
| } |
| |
| void GetAnnotatedLocation( |
| blink::mojom::DeviceAPIService::GetAnnotatedLocationCallback callback) |
| override { |
| std::move(callback).Run(Result::NewAttribute(kAnnotatedLocation)); |
| } |
| |
| private: |
| DeviceAttributeApiImpl device_attributes_api_; |
| }; |
| } // namespace |
| |
| class DeviceAPIServiceTest { |
| public: |
| void InstallTrustedApps(Profile* profile) { |
| app_id_ = web_app::test::InstallDummyWebApp( |
| profile, "Policy installed app", GURL(kDefaultAppInstallUrl), |
| webapps::WebappInstallSource::EXTERNAL_POLICY); |
| } |
| |
| void TryCreatingService( |
| const GURL& url, |
| std::unique_ptr<DeviceAttributeApi> device_attribute_api, |
| content::WebContents* web_contents) { |
| // Isolated Web Apps require Cross Origin Isolation headers to be included |
| // in the response. |
| if (url.SchemeIs(chrome::kIsolatedAppScheme)) { |
| web_app::SimulateIsolatedWebAppNavigation(web_contents, url); |
| } else { |
| content::NavigationSimulator::NavigateAndCommitFromBrowser(web_contents, |
| url); |
| } |
| |
| DeviceServiceImpl::CreateForTest(web_contents->GetPrimaryMainFrame(), |
| remote()->BindNewPipeAndPassReceiver(), |
| std::move(device_attribute_api)); |
| } |
| |
| const webapps::AppId& app_id() const { return *app_id_; } |
| |
| mojo::Remote<blink::mojom::DeviceAPIService>* remote() { return &remote_; } |
| |
| private: |
| std::optional<webapps::AppId> app_id_; |
| mojo::Remote<blink::mojom::DeviceAPIService> remote_; |
| }; |
| |
| namespace { |
| void VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| blink::mojom::DeviceAPIService* service, |
| const std::string& expected_error_message) { |
| base::test::TestFuture<blink::mojom::DeviceAttributeResultPtr> future; |
| |
| service->GetDirectoryId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_error_message(), expected_error_message); |
| |
| service->GetHostname(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_error_message(), expected_error_message); |
| |
| service->GetSerialNumber(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_error_message(), expected_error_message); |
| |
| service->GetAnnotatedAssetId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_error_message(), expected_error_message); |
| |
| service->GetAnnotatedLocation(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_error_message(), expected_error_message); |
| } |
| } // namespace |
| |
| class DeviceAPIServiceWebAppTest : public DeviceAPIServiceTest, |
| public WebAppTest { |
| public: |
| DeviceAPIServiceWebAppTest() |
| : WebAppTest(WebAppTest::WithTestUrlLoaderFactory()) { |
| account_id_ = AccountId::FromUserEmail(kUserEmail); |
| } |
| |
| void SetUp() override { |
| WebAppTest::SetUp(); |
| web_app::test::AwaitStartWebAppProviderAndSubsystems(profile()); |
| InstallTrustedApps(); |
| profile()->SetPermissionControllerDelegate( |
| permissions::GetPermissionControllerDelegate(profile())); |
| #if BUILDFLAG(IS_CHROMEOS) |
| SetAllowedOrigin(); |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| } |
| |
| void InstallTrustedApps() { |
| DeviceAPIServiceTest::InstallTrustedApps(profile()); |
| } |
| |
| void UninstallAllApps() { web_app::test::UninstallAllWebApps(profile()); } |
| |
| webapps::AppId UserInstallWebApp() { |
| auto app_info = web_app::WebAppInstallInfo::CreateWithStartUrlForTesting( |
| GURL(kDefaultAppInstallUrl)); |
| |
| return web_app::test::InstallWebApp( |
| profile(), std::move(app_info), |
| /*overwrite_existing_manifest_fields=*/false, |
| webapps::WebappInstallSource::EXTERNAL_DEFAULT); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| void SetAllowedOrigin() { |
| base::Value::List allowed_origins; |
| allowed_origins.Append(kTrustedUrl); |
| allowed_origins.Append(kKioskAppInstallUrl); |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDeviceAttributesAllowedForOrigins, |
| std::move(allowed_origins)); |
| } |
| #endif // BUILDFLAG(IS_CHROMEOS) |
| |
| void TryCreatingService( |
| const GURL& url, |
| std::unique_ptr<DeviceAttributeApi> device_attribute_api) { |
| DeviceAPIServiceTest::TryCreatingService( |
| url, std::move(device_attribute_api), web_contents()); |
| } |
| |
| void VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| const std::string& expected_error_message) { |
| ::VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| remote()->get(), expected_error_message); |
| } |
| |
| const AccountId& account_id() const { return account_id_; } |
| |
| web_app::WebAppProvider* provider() { |
| return web_app::WebAppProvider::GetForTest(profile()); |
| } |
| |
| void TearDown() override { |
| provider()->Shutdown(); |
| WebAppTest::TearDown(); |
| } |
| |
| void EnableFeature(const base::Feature& param) { |
| feature_list_.InitAndEnableFeature(param); |
| } |
| |
| void DisableFeature(const base::Feature& feature) { |
| feature_list_.InitAndDisableFeature(feature); |
| } |
| |
| protected: |
| base::test::ScopedFeatureList feature_list_; |
| |
| private: |
| AccountId account_id_; |
| }; |
| |
| TEST_F(DeviceAPIServiceWebAppTest, ConnectsForTrustedApps) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled in the Incognito mode. |
| TEST_F(DeviceAPIServiceWebAppTest, DoesNotConnectForIncognitoProfile) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| profile_metrics::SetBrowserProfileType( |
| profile(), profile_metrics::BrowserProfileType::kIncognito); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, DoesNotConnectForUntrustedApps) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kUntrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, DisconnectWhenTrustRevoked) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| UninstallAllApps(); |
| remote()->FlushForTesting(); |
| |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, MultiOriginDisconnectWhenTrustRevoked) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| webapps::AppId app_id = UserInstallWebApp(); |
| |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| UninstallAllApps(); |
| remote()->FlushForTesting(); |
| |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, ReportErrorForDefaultUser) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNotAffiliatedErrorMessage); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, |
| DoesNotConnectForTrustedAppsWithFeatureFlagEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, |
| DoesNotConnectForIncognitoProfileWithFeatureFlagEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| profile_metrics::SetBrowserProfileType( |
| profile(), profile_metrics::BrowserProfileType::kIncognito); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWebAppTest, |
| DoesNotConnectForUntrustedAppsWithFeatureFlagEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| TryCreatingService(GURL(kUntrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| #if BUILDFLAG(IS_CHROMEOS) |
| |
| class DeviceAPIServiceIwaTest |
| : public DeviceAPIServiceTest, |
| public web_app::IsolatedWebAppTest, |
| public ::testing::WithParamInterface<std::tuple<bool, bool, bool, bool>> { |
| public: |
| void SetUp() override { |
| web_app::IsolatedWebAppTest::SetUp(); |
| web_app::test::AwaitStartWebAppProviderAndSubsystems(profile()); |
| profile()->SetPermissionControllerDelegate( |
| permissions::GetPermissionControllerDelegate(profile())); |
| rvh_test_enabler_ = std::make_unique<content::RenderViewHostTestEnabler>(); |
| web_contents_ = content::WebContentsTester::CreateTestWebContents( |
| profile(), /*instance=*/nullptr); |
| } |
| |
| void TearDown() override { |
| web_contents_.reset(); |
| rvh_test_enabler_.reset(); |
| web_app::IsolatedWebAppTest::TearDown(); |
| } |
| |
| void SetAllowedOrigin(const std::string& origin) { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDeviceAttributesAllowedForOrigins, |
| base::Value::List().Append(origin)); |
| } |
| |
| void SetBlockedOrigin(const std::string& origin) { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDeviceAttributesBlockedForOrigins, |
| base::Value::List().Append(origin)); |
| } |
| |
| void SetEnterprisePoliciesForOrigin(const std::string& origin) { |
| if (IsBlockPolicySet()) { |
| SetBlockedOrigin(origin); |
| } |
| if (IsAllowPolicySet()) { |
| SetAllowedOrigin(origin); |
| } |
| } |
| |
| web_app::IsolatedWebAppUrlInfo InstallTrustedIWA() { |
| return InstallIWA(/*trusted=*/true); |
| } |
| |
| web_app::IsolatedWebAppUrlInfo InstallUntrustedIWA() { |
| return InstallIWA(/*trusted=*/false); |
| } |
| |
| void ForceUninstall(const web_app::IsolatedWebAppUrlInfo& url_info) { |
| base::RunLoop run_loop; |
| auto* browsing_data_remover = profile()->GetBrowsingDataRemover(); |
| browsing_data_remover->SetWouldCompleteCallbackForTesting( |
| base::BindLambdaForTesting([&](base::OnceClosure callback) { |
| if (browsing_data_remover->GetPendingTaskCountForTesting() == 1) { |
| run_loop.Quit(); |
| } |
| std::move(callback).Run(); |
| })); |
| |
| base::test::TestFuture<webapps::UninstallResultCode> future; |
| provider().scheduler().RemoveInstallManagementMaybeUninstall( |
| url_info.app_id(), web_app::WebAppManagement::Type::kIwaPolicy, |
| webapps::WebappUninstallSource::kIwaEnterprisePolicy, |
| future.GetCallback()); |
| auto code = future.Get(); |
| ASSERT_EQ(code, webapps::UninstallResultCode::kAppRemoved); |
| run_loop.Run(); |
| } |
| |
| void TryCreatingService( |
| const GURL& url, |
| std::unique_ptr<DeviceAttributeApi> device_attribute_api) { |
| DeviceAPIServiceTest::TryCreatingService( |
| url, std::move(device_attribute_api), web_contents_.get()); |
| } |
| |
| void InitWebContents() {} |
| |
| void EnableFeature(const base::Feature& param) { |
| feature_list_.InitAndEnableFeature(param); |
| } |
| |
| void DisableFeature(const base::Feature& feature) { |
| feature_list_.InitAndDisableFeature(feature); |
| } |
| |
| void SetDeviceAttributesPermissionPolicyFeatureFlag() { |
| if (IsDeviceAttributesPermissionPolicyFeatureFlagEnabled()) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| } else { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| } |
| } |
| |
| bool IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() { |
| return std::get<0>(GetParam()); |
| } |
| bool IsAllowPolicySet() { return std::get<1>(GetParam()); } |
| bool IsBlockPolicySet() { return std::get<2>(GetParam()); } |
| bool IsPermissionsPolicyGranted() { return std::get<3>(GetParam()); } |
| |
| private: |
| web_app::IsolatedWebAppUrlInfo InstallIWA(bool trusted) { |
| auto manifest_builder = web_app::ManifestBuilder(); |
| if (IsPermissionsPolicyGranted()) { |
| manifest_builder.AddPermissionsPolicy( |
| network::mojom::PermissionsPolicyFeature::kDeviceAttributes, true, |
| {}); |
| } |
| const std::unique_ptr<web_app::ScopedBundledIsolatedWebApp> bundle = |
| web_app::IsolatedWebAppBuilder(manifest_builder).BuildBundle(); |
| bundle->TrustSigningKey(); |
| if (trusted) { |
| return bundle |
| ->InstallWithSource( |
| profile(), |
| &web_app::IsolatedWebAppInstallSource::FromExternalPolicy) |
| .value(); |
| } else { |
| return bundle->InstallChecked(profile()); |
| } |
| } |
| |
| std::unique_ptr<content::RenderViewHostTestEnabler> rvh_test_enabler_; |
| std::unique_ptr<content::WebContents> web_contents_; |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| TEST_P(DeviceAPIServiceIwaTest, CheckTrustedApps) { |
| mojo::FakeMessageDispatchContext fake_dispatch_context; |
| mojo::test::BadMessageObserver bad_message_observer; |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| |
| auto url_info = InstallTrustedIWA(); |
| bool should_connect = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() |
| : true; |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| if (should_connect) { |
| ASSERT_TRUE(remote()->is_connected()); |
| } else { |
| ASSERT_FALSE(remote()->is_connected()); |
| EXPECT_EQ(bad_message_observer.WaitForBadMessage(), |
| "Permissions policy blocks access to Device Attributes."); |
| } |
| } |
| |
| TEST_P(DeviceAPIServiceIwaTest, CheckUntrustedApps) { |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| auto url_info = InstallUntrustedIWA(); |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_P(DeviceAPIServiceIwaTest, CheckTrustRevoked) { |
| mojo::FakeMessageDispatchContext fake_dispatch_context; |
| mojo::test::BadMessageObserver bad_message_observer; |
| |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| auto url_info = InstallTrustedIWA(); |
| bool should_connect = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() |
| : true; |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| if (should_connect) { |
| ForceUninstall(url_info); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } else { |
| ASSERT_FALSE(remote()->is_connected()); |
| EXPECT_EQ(bad_message_observer.WaitForBadMessage(), |
| kPermissionsPolicyMojoErrorMessage); |
| } |
| } |
| |
| TEST_P(DeviceAPIServiceIwaTest, CheckErrorForDefaultUser) { |
| mojo::FakeMessageDispatchContext fake_dispatch_context; |
| mojo::test::BadMessageObserver bad_message_observer; |
| |
| bool should_connect = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() |
| : true; |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| auto url_info = InstallTrustedIWA(); |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| if (should_connect) { |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| remote()->get(), kNotAffiliatedErrorMessage); |
| ASSERT_TRUE(remote()->is_connected()); |
| } else { |
| ASSERT_FALSE(remote()->is_connected()); |
| EXPECT_EQ(bad_message_observer.WaitForBadMessage(), |
| kPermissionsPolicyMojoErrorMessage); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| DeviceAPIServiceIwaTest, |
| ::testing::Combine( |
| ::testing::Bool(), // kDeviceAttributesPermissionPolicy feature flag |
| ::testing::Bool(), // allow policy |
| ::testing::Bool(), // block policy |
| ::testing::Bool() // permissions policy |
| ), |
| [](const ::testing::TestParamInfo<std::tuple<bool, bool, bool, bool>>& |
| info) { |
| return base::StringPrintf( |
| "FeatureFlag%s_AllowPolicy%s_BlockPolicy%s_PermissionsPolicy%s", |
| std::get<0>(info.param) ? "Enabled" : "Disabled", |
| std::get<1>(info.param) ? "Set" : "Unset", |
| std::get<2>(info.param) ? "Set" : "Unset", |
| std::get<3>(info.param) ? "Granted" : "Denied"); |
| }); |
| |
| class DeviceAPIServiceParamTest |
| : public DeviceAPIServiceWebAppTest, |
| public testing::WithParamInterface<std::pair<std::string, bool>> { |
| public: |
| void SetAllowedOriginFromParam() { SetAllowedOrigin(GetParamOrigin()); } |
| |
| void SetAllowedOrigin(const std::string& origin) { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDeviceAttributesAllowedForOrigins, |
| base::Value::List().Append(origin)); |
| } |
| |
| void AllowOriginsByDefault() { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDefaultDeviceAttributesSetting, |
| base::Value(kAllowSetting)); |
| } |
| |
| void BlockOriginsByDefault() { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDefaultDeviceAttributesSetting, |
| base::Value(kBlockSetting)); |
| } |
| |
| void EnableFeatureAndAllowlistOrigin(const base::Feature& param, |
| const std::string& origin) { |
| base::FieldTrialParams feature_params; |
| feature_params[permissions::feature_params:: |
| kWebKioskBrowserPermissionsAllowlist.name] = origin; |
| feature_list_.InitAndEnableFeatureWithParameters(param, feature_params); |
| } |
| |
| void InitWithFeatures( |
| const std::vector<base::test::FeatureRef>& enabled_features, |
| const std::vector<base::test::FeatureRef>& disabled_features) { |
| feature_list_.InitWithFeatures(enabled_features, disabled_features); |
| } |
| |
| void InitWithFeaturesAndParameters( |
| const std::vector<base::test::FeatureRefAndParams>& enabled_features, |
| const std::vector<base::test::FeatureRef>& disabled_features) { |
| feature_list_.InitWithFeaturesAndParameters(enabled_features, |
| disabled_features); |
| } |
| |
| void SetKioskBrowserPermissionsAllowedForOrigins(const std::string& origin) { |
| profile()->GetPrefs()->SetList( |
| prefs::kKioskBrowserPermissionsAllowedForOrigins, |
| base::Value::List().Append(std::move(origin))); |
| } |
| |
| void VerifyCanAccessForAllDeviceAttributesAPIs() { |
| base::test::TestFuture<blink::mojom::DeviceAttributeResultPtr> future; |
| |
| remote()->get()->GetDirectoryId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kDirectoryApiId); |
| |
| remote()->get()->GetHostname(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kHostname); |
| |
| remote()->get()->GetSerialNumber(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kSerialNumber); |
| |
| remote()->get()->GetAnnotatedAssetId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kAnnotatedAssetId); |
| |
| remote()->get()->GetAnnotatedLocation(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kAnnotatedLocation); |
| } |
| |
| const std::string& GetParamOrigin() { return GetParam().first; } |
| |
| bool ExpectApiAvailable() { return GetParam().second; } |
| |
| private: |
| static constexpr int32_t kAllowSetting = 1; |
| static constexpr int32_t kBlockSetting = 2; |
| }; |
| |
| class DeviceAPIServiceRegularUserTest : public DeviceAPIServiceParamTest { |
| public: |
| void LoginRegularUser(bool is_affiliated) { |
| const user_manager::User* user = |
| fake_user_manager()->AddUserWithAffiliation(account_id(), |
| is_affiliated); |
| fake_user_manager()->UserLoggedIn( |
| user->GetAccountId(), |
| user_manager::TestHelper::GetFakeUsernameHash(user->GetAccountId())); |
| } |
| |
| ash::FakeChromeUserManager* fake_user_manager() const { |
| return static_cast<ash::FakeChromeUserManager*>( |
| user_manager::UserManager::Get()); |
| } |
| |
| void RemoveAllowedOrigin() { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDeviceAttributesAllowedForOrigins, base::Value::List()); |
| } |
| |
| void TearDown() override { |
| provider()->Shutdown(); |
| DeviceAPIServiceParamTest::TearDown(); |
| } |
| }; |
| |
| TEST_F(DeviceAPIServiceRegularUserTest, ReportErrorForUnaffiliatedUser) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginRegularUser(false); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNotAffiliatedErrorMessage); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceRegularUserTest, ReportErrorForDisallowedOrigin) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginRegularUser(true); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| RemoveAllowedOrigin(); |
| |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNoDeviceAttributesPermissionErrorMessage); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| TEST_P(DeviceAPIServiceRegularUserTest, TestPolicyOriginPatterns) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| SetAllowedOriginFromParam(); |
| LoginRegularUser(true); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| |
| if (ExpectApiAvailable()) { |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } else { |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNoDeviceAttributesPermissionErrorMessage); |
| } |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceRegularUserTest, |
| DoesNotConnectForUnaffiliatedUserWithFeatureFlag) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginRegularUser(false); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceRegularUserTest, |
| DoesNotConnectForAffiliatedUserWithFeatureFlag) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginRegularUser(true); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| DeviceAPIServiceRegularUserTest, |
| testing::ValuesIn( |
| {std::pair<std::string, bool>("*", false), |
| std::pair<std::string, bool>(".example.com", false), |
| std::pair<std::string, bool>("example.", false), |
| std::pair<std::string, bool>("file://example*", false), |
| std::pair<std::string, bool>("invalid-example.com", false), |
| std::pair<std::string, bool>(kTrustedUrl, true), |
| std::pair<std::string, bool>("https://example.com", true), |
| std::pair<std::string, bool>("https://example.com/sample", true), |
| std::pair<std::string, bool>("example.com", true), |
| std::pair<std::string, bool>("*://example.com:*/", true), |
| std::pair<std::string, bool>("[*.]example.com", true)})); |
| |
| class DeviceAPIServiceRegularUserIwaTest : public DeviceAPIServiceIwaTest { |
| public: |
| DeviceAPIServiceRegularUserIwaTest() { |
| account_id_ = AccountId::FromUserEmail(kUserEmail); |
| } |
| |
| void LoginRegularUser(bool is_affiliated) { |
| const user_manager::User* user = |
| fake_user_manager()->AddUserWithAffiliation(account_id(), |
| is_affiliated); |
| fake_user_manager()->UserLoggedIn( |
| user->GetAccountId(), |
| user_manager::TestHelper::GetFakeUsernameHash(user->GetAccountId())); |
| } |
| |
| ash::FakeChromeUserManager* fake_user_manager() const { |
| return static_cast<ash::FakeChromeUserManager*>( |
| user_manager::UserManager::Get()); |
| } |
| const AccountId& account_id() const { return account_id_; } |
| |
| void AllowOriginsByDefault() { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDefaultDeviceAttributesSetting, |
| base::Value(kAllowSetting)); |
| } |
| |
| void BlockOriginsByDefault() { |
| profile()->GetTestingPrefService()->SetManagedPref( |
| prefs::kManagedDefaultDeviceAttributesSetting, |
| base::Value(kBlockSetting)); |
| } |
| |
| void VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| const std::string& expected_error_message) { |
| ::VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| remote()->get(), expected_error_message); |
| } |
| |
| void VerifyCanAccessForAllDeviceAttributesAPIs() { |
| base::test::TestFuture<blink::mojom::DeviceAttributeResultPtr> future; |
| |
| remote()->get()->GetDirectoryId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kDirectoryApiId); |
| |
| remote()->get()->GetHostname(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kHostname); |
| |
| remote()->get()->GetSerialNumber(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kSerialNumber); |
| |
| remote()->get()->GetAnnotatedAssetId(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kAnnotatedAssetId); |
| |
| remote()->get()->GetAnnotatedLocation(future.GetCallback()); |
| EXPECT_EQ(future.Take()->get_attribute(), kAnnotatedLocation); |
| } |
| |
| private: |
| static constexpr int32_t kAllowSetting = 1; |
| static constexpr int32_t kBlockSetting = 2; |
| AccountId account_id_; |
| }; |
| |
| TEST_P(DeviceAPIServiceRegularUserIwaTest, |
| CheckTrustedAppsForUnaffiliatedUser) { |
| mojo::FakeMessageDispatchContext fake_dispatch_context; |
| mojo::test::BadMessageObserver bad_message_observer; |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| |
| LoginRegularUser(false); |
| auto url_info = InstallTrustedIWA(); |
| SetEnterprisePoliciesForOrigin(url_info.origin().Serialize()); |
| bool should_connect = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() |
| : true; |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| if (should_connect) { |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNotAffiliatedErrorMessage); |
| } else { |
| ASSERT_FALSE(remote()->is_connected()); |
| EXPECT_EQ(bad_message_observer.WaitForBadMessage(), |
| kPermissionsPolicyMojoErrorMessage); |
| } |
| } |
| |
| TEST_P(DeviceAPIServiceRegularUserIwaTest, CheckTrustedAppsForAffiliatedUser) { |
| mojo::FakeMessageDispatchContext fake_dispatch_context; |
| mojo::test::BadMessageObserver bad_message_observer; |
| SetDeviceAttributesPermissionPolicyFeatureFlag(); |
| |
| LoginRegularUser(true); |
| auto url_info = InstallTrustedIWA(); |
| SetEnterprisePoliciesForOrigin(url_info.origin().Serialize()); |
| bool should_connect = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() |
| : true; |
| bool should_work = IsDeviceAttributesPermissionPolicyFeatureFlagEnabled() |
| ? IsPermissionsPolicyGranted() && !IsBlockPolicySet() |
| : IsAllowPolicySet(); |
| TryCreatingService(url_info.origin().GetURL(), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| if (should_connect) { |
| ASSERT_TRUE(remote()->is_connected()); |
| if (should_work) { |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } else { |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNoDeviceAttributesPermissionErrorMessage); |
| } |
| } else { |
| ASSERT_FALSE(remote()->is_connected()); |
| EXPECT_EQ(bad_message_observer.WaitForBadMessage(), |
| kPermissionsPolicyMojoErrorMessage); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| DeviceAPIServiceRegularUserIwaTest, |
| ::testing::Combine( |
| ::testing::Bool(), // kDeviceAttributesPermissionPolicy feature flag |
| ::testing::Bool(), // allow policy |
| ::testing::Bool(), // block policy |
| ::testing::Bool() // permissions policy |
| ), |
| [](const ::testing::TestParamInfo<std::tuple<bool, bool, bool, bool>>& |
| info) { |
| return base::StringPrintf( |
| "FeatureFlag%s_AllowPolicy%s_BlockPolicy%s_PermissionsPolicy%s", |
| std::get<0>(info.param) ? "Enabled" : "Disabled", |
| std::get<1>(info.param) ? "Set" : "Unset", |
| std::get<2>(info.param) ? "Set" : "Unset", |
| std::get<3>(info.param) ? "Granted" : "Denied"); |
| }); |
| |
| class DeviceAPIServiceWithKioskUserTest : public DeviceAPIServiceParamTest { |
| public: |
| DeviceAPIServiceWithKioskUserTest() { |
| fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>()); |
| } |
| |
| void SetUp() override { |
| DeviceAPIServiceParamTest::SetUp(); |
| command_line_.GetProcessCommandLine()->AppendSwitch( |
| switches::kForceAppMode); |
| app_manager_ = std::make_unique<ash::KioskWebAppManager>(); |
| } |
| |
| void TearDown() override { |
| app_manager_.reset(); |
| DeviceAPIServiceParamTest::TearDown(); |
| } |
| |
| void LoginKioskUser() { |
| app_manager()->AddAppForTesting(account_id(), GURL(kKioskAppInstallUrl)); |
| fake_user_manager()->AddKioskWebAppUser(account_id()); |
| fake_user_manager()->LoginUser(account_id()); |
| } |
| |
| ash::FakeChromeUserManager* fake_user_manager() const { |
| return fake_user_manager_.Get(); |
| } |
| |
| ash::KioskWebAppManager* app_manager() const { return app_manager_.get(); } |
| |
| private: |
| user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> |
| fake_user_manager_; |
| std::unique_ptr<ash::KioskWebAppManager> app_manager_; |
| base::test::ScopedCommandLine command_line_; |
| }; |
| |
| // The service should be enabled if the current origin is same as the origin of |
| // Kiosk app. |
| TEST_F(DeviceAPIServiceWithKioskUserTest, ConnectsForKioskOrigin) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled if the current origin is different from the |
| // origin of Kiosk app. |
| TEST_F(DeviceAPIServiceWithKioskUserTest, DoesNotConnectForInvalidOrigin) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kInvalidKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled if the current origin is different from the |
| // origin of Kiosk app, even if it is trusted (force-installed). |
| TEST_F(DeviceAPIServiceWithKioskUserTest, |
| DoesNotConnectForNonKioskTrustedOrigin) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| // The service should be enabled if the current origin is same as the origin of |
| // Kiosk app. |
| TEST_F(DeviceAPIServiceWithKioskUserTest, |
| ConnectsForKioskOriginWithFeatureEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_TRUE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled if the current origin is different from the |
| // origin of Kiosk app. |
| TEST_F(DeviceAPIServiceWithKioskUserTest, |
| DoesNotConnectForInvalidOriginWithFeatureEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kInvalidKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled if the current origin is different from the |
| // origin of Kiosk app, even if it is trusted (force-installed). |
| TEST_F(DeviceAPIServiceWithKioskUserTest, |
| DoesNotConnectForNonKioskTrustedOriginWithFeatureEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| class DeviceAPIServiceWithChromeAppKioskUserTest |
| : public DeviceAPIServiceTest, |
| public ChromeRenderViewHostTestHarness { |
| public: |
| DeviceAPIServiceWithChromeAppKioskUserTest() |
| : account_id_(AccountId::FromUserEmail(kUserEmail)) { |
| fake_user_manager_.Reset(std::make_unique<ash::FakeChromeUserManager>()); |
| } |
| |
| void LoginChromeAppKioskUser() { |
| fake_user_manager()->AddKioskChromeAppUser(account_id()); |
| fake_user_manager()->LoginUser(account_id()); |
| } |
| |
| const AccountId& account_id() const { return account_id_; } |
| |
| ash::FakeChromeUserManager* fake_user_manager() const { |
| return fake_user_manager_.Get(); |
| } |
| |
| void TryCreatingService( |
| const GURL& url, |
| std::unique_ptr<DeviceAttributeApi> device_attribute_api) { |
| DeviceAPIServiceTest::TryCreatingService( |
| url, std::move(device_attribute_api), web_contents()); |
| } |
| |
| void EnableFeature(const base::Feature& param) { |
| feature_list_.InitAndEnableFeature(param); |
| } |
| |
| void DisableFeature(const base::Feature& feature) { |
| feature_list_.InitAndDisableFeature(feature); |
| } |
| |
| private: |
| AccountId account_id_; |
| std::unique_ptr<user_manager::ScopedUserManager> scoped_user_manager_; |
| user_manager::TypedScopedUserManager<ash::FakeChromeUserManager> |
| fake_user_manager_; |
| base::test::ScopedFeatureList feature_list_; |
| }; |
| |
| // The service should be disabled if a non-PWA kiosk user is logged in. |
| TEST_F(DeviceAPIServiceWithChromeAppKioskUserTest, |
| DoesNotConnectForChromeAppKioskSession) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginChromeAppKioskUser(); |
| |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| // The service should be disabled if a non-PWA kiosk user is logged in. |
| TEST_F(DeviceAPIServiceWithChromeAppKioskUserTest, |
| DoesNotConnectForChromeAppKioskSessionWithFeatureFlagEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| LoginChromeAppKioskUser(); |
| |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<DeviceAttributeApiImpl>()); |
| remote()->FlushForTesting(); |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| class DeviceAPIServiceWithKioskUserTestForOrigins |
| : public DeviceAPIServiceWithKioskUserTest {}; |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestTrustedKioskOriginsWhenEnabledByFeature) { |
| base::FieldTrialParams feature_params; |
| feature_params |
| [permissions::feature_params::kWebKioskBrowserPermissionsAllowlist.name] = |
| kTrustedUrl; |
| InitWithFeaturesAndParameters( |
| /*enabled_features=*/{{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| feature_params}}, |
| /*disabled_features=*/{ |
| blink::features::kDeviceAttributesPermissionPolicy}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestUntrustedKioskOriginsWhenEnabledByFeature) { |
| base::FieldTrialParams feature_params; |
| feature_params |
| [permissions::feature_params::kWebKioskBrowserPermissionsAllowlist.name] = |
| kTrustedUrl; |
| InitWithFeaturesAndParameters( |
| /*enabled_features=*/{{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| feature_params}}, |
| /*disabled_features=*/{ |
| blink::features::kDeviceAttributesPermissionPolicy}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kUntrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestTrustedKioskOriginWhenMultipleOriginPrefIsSet) { |
| InitWithFeatures( |
| /*enabled_features=*/{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions}, |
| /*disabled_features=*/{ |
| blink::features::kDeviceAttributesPermissionPolicy}); |
| SetKioskBrowserPermissionsAllowedForOrigins(kTrustedUrl); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestKioskInstallOriginWhenMultipleOriginPrefIsNotSet) { |
| InitWithFeatures( |
| /*enabled_features=*/{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions}, |
| /*disabled_features=*/{ |
| blink::features::kDeviceAttributesPermissionPolicy}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppInstallUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for install origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestMultipleOriginPolicyWhenFeatureIsDisabled) { |
| InitWithFeatures( |
| /*enabled_features=*/{}, /*disabled_features=*/{ |
| blink::features::kDeviceAttributesPermissionPolicy, |
| permissions::features::kAllowMultipleOriginsForWebKioskPermissions}); |
| SetKioskBrowserPermissionsAllowedForOrigins(kTrustedUrl); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check that the service is not able to connect when the feature is disabled. |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_P(DeviceAPIServiceWithKioskUserTestForOrigins, TestPolicyOriginPatterns) { |
| DisableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| BlockOriginsByDefault(); |
| SetAllowedOriginFromParam(); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| |
| remote()->FlushForTesting(); |
| |
| ASSERT_TRUE(remote()->is_connected()); |
| |
| if (ExpectApiAvailable()) { |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } else { |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNoDeviceAttributesPermissionErrorMessage); |
| } |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestTrustedKioskOriginsWhenEnabledByFeatureWithDAPPFeatureEnabled) { |
| base::FieldTrialParams feature_params; |
| feature_params |
| [permissions::feature_params::kWebKioskBrowserPermissionsAllowlist.name] = |
| kTrustedUrl; |
| InitWithFeaturesAndParameters( |
| /*enabled_features=*/{{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| feature_params}, |
| {blink::features::kDeviceAttributesPermissionPolicy, |
| {}}}, |
| /*disabled_features=*/{}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestUntrustedKioskOriginsWhenEnabledByFeatureWithDAPPFeatureEnabled) { |
| base::FieldTrialParams feature_params; |
| feature_params |
| [permissions::feature_params::kWebKioskBrowserPermissionsAllowlist.name] = |
| kTrustedUrl; |
| InitWithFeaturesAndParameters( |
| /*enabled_features=*/{{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| feature_params}, |
| {blink::features::kDeviceAttributesPermissionPolicy, |
| {}}}, |
| /*disabled_features=*/{}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kUntrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_F( |
| DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestTrustedKioskOriginWhenMultipleOriginPrefIsSetWithDAPPFeatureEnabled) { |
| InitWithFeatures( |
| /*enabled_features=*/{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| blink::features::kDeviceAttributesPermissionPolicy}, |
| /*disabled_features=*/{}); |
| SetKioskBrowserPermissionsAllowedForOrigins(kTrustedUrl); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for a different allowed origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F( |
| DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestKioskInstallOriginWhenMultipleOriginPrefIsNotSetWithDAPPFeatureEnabled) { |
| InitWithFeatures( |
| /*enabled_features=*/{permissions::features:: |
| kAllowMultipleOriginsForWebKioskPermissions, |
| blink::features::kDeviceAttributesPermissionPolicy}, |
| /*disabled_features=*/{}); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppInstallUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check whether the service connects for install origin. |
| ASSERT_TRUE(remote()->is_connected()); |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } |
| |
| TEST_F(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestMultipleOriginPolicyWhenFeatureIsDisabledWithDAPPFeatureEnabled) { |
| InitWithFeatures( |
| /*enabled_features=*/{blink::features::kDeviceAttributesPermissionPolicy}, |
| /*disabled_features=*/{ |
| permissions::features::kAllowMultipleOriginsForWebKioskPermissions}); |
| SetKioskBrowserPermissionsAllowedForOrigins(kTrustedUrl); |
| |
| LoginKioskUser(); |
| TryCreatingService(GURL(kTrustedUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| remote()->FlushForTesting(); |
| |
| // Check that the service is not able to connect when the feature is disabled. |
| ASSERT_FALSE(remote()->is_connected()); |
| } |
| |
| TEST_P(DeviceAPIServiceWithKioskUserTestForOrigins, |
| TestPolicyOriginPatternsWithDAPPFeatureEnabled) { |
| EnableFeature(blink::features::kDeviceAttributesPermissionPolicy); |
| BlockOriginsByDefault(); |
| SetAllowedOriginFromParam(); |
| LoginKioskUser(); |
| TryCreatingService(GURL(kKioskAppUrl), |
| std::make_unique<FakeDeviceAttributeApi>()); |
| |
| remote()->FlushForTesting(); |
| |
| ASSERT_TRUE(remote()->is_connected()); |
| |
| if (ExpectApiAvailable()) { |
| VerifyCanAccessForAllDeviceAttributesAPIs(); |
| } else { |
| VerifyErrorMessageResultForAllDeviceAttributesAPIs( |
| kNoDeviceAttributesPermissionErrorMessage); |
| } |
| } |
| |
| INSTANTIATE_TEST_SUITE_P( |
| All, |
| DeviceAPIServiceWithKioskUserTestForOrigins, |
| testing::ValuesIn({std::pair<std::string, bool>("*", false), |
| std::pair<std::string, bool>("*.kiosk.com", false), |
| std::pair<std::string, bool>("*kiosk.com", false), |
| std::pair<std::string, bool>("kiosk.", false), |
| std::pair<std::string, bool>(kInvalidKioskAppUrl, false), |
| std::pair<std::string, bool>(kKioskAppUrl, true), |
| std::pair<std::string, bool>("https://kiosk.com", true), |
| std::pair<std::string, bool>("https://kiosk.com/sample", |
| true), |
| std::pair<std::string, bool>("kiosk.com", true), |
| std::pair<std::string, bool>("*://kiosk.com:*/", true), |
| std::pair<std::string, bool>("[*.]kiosk.com", true)})); |
| #endif // BUILDFLAG(IS_CHROMEOS) |