| // Copyright 2021 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 "base/base_paths.h" |
| #include "base/command_line.h" |
| #include "base/files/file_enumerator.h" |
| #include "base/files/file_util.h" |
| #include "base/functional/bind.h" |
| #include "base/path_service.h" |
| #include "base/test/bind.h" |
| #include "base/test/scoped_feature_list.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "content/browser/lock_screen/lock_screen_service_impl.h" |
| #include "content/browser/lock_screen/lock_screen_storage_impl.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/common/content_features.h" |
| #include "content/public/test/browser_test.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/content_browser_test.h" |
| #include "content/public/test/content_browser_test_utils.h" |
| #include "content/shell/browser/shell.h" |
| #include "mojo/public/cpp/bindings/remote.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "services/service_manager/public/cpp/interface_provider.h" |
| #include "third_party/blink/public/mojom/lock_screen/lock_screen.mojom.h" |
| |
| namespace content { |
| |
| class LockScreenServiceImplBrowserTest : public ContentBrowserTest { |
| public: |
| LockScreenServiceImplBrowserTest() { |
| feature_list_.InitAndEnableFeature(features::kWebLockScreenApi); |
| } |
| |
| LockScreenServiceImplBrowserTest(const LockScreenServiceImplBrowserTest&) = |
| delete; |
| LockScreenServiceImplBrowserTest& operator=( |
| const LockScreenServiceImplBrowserTest&) = delete; |
| |
| ~LockScreenServiceImplBrowserTest() override = default; |
| |
| base::FilePath GetStoragePath() { |
| base::FilePath path; |
| EXPECT_TRUE(base::PathService::Get(base::DIR_TEMP, &path)); |
| path = path.AppendASCII("web_lock_screen_api_data"); |
| path = path.AppendASCII("test-user"); |
| return path; |
| } |
| |
| void SetUpOnMainThread() override { |
| ContentBrowserTest::SetUpOnMainThread(); |
| EXPECT_TRUE(base::DeletePathRecursively(GetStoragePath())); |
| LockScreenStorageImpl::GetInstance()->InitForTesting( |
| shell()->web_contents()->GetBrowserContext(), GetStoragePath()); |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| content::SetupCrossSiteRedirector(embedded_test_server()); |
| ASSERT_TRUE(embedded_test_server()->Start()); |
| GURL url = embedded_test_server()->GetURL("/lock_screen/simple.html"); |
| lock_screen_service_ = NavigateAndCreateService(url); |
| } |
| |
| void TearDownOnMainThread() override { |
| ContentBrowserTest::TearDownOnMainThread(); |
| } |
| |
| mojo::Remote<blink::mojom::LockScreenService> NavigateAndCreateService( |
| const GURL& url) { |
| Shell* shell = CreateBrowser(); |
| EXPECT_TRUE(NavigateToURL(shell, url)); |
| RenderFrameHost* rfh = shell->web_contents()->GetPrimaryMainFrame(); |
| mojo::Remote<blink::mojom::LockScreenService> service; |
| LockScreenServiceImpl::Create(rfh, service.BindNewPipeAndPassReceiver()); |
| return service; |
| } |
| |
| blink::mojom::LockScreenService* service() { |
| return lock_screen_service_.get(); |
| } |
| |
| blink::mojom::LockScreenServiceStatus AwaitSetData( |
| blink::mojom::LockScreenService* service, |
| const std::string& key, |
| const std::string& data) { |
| base::RunLoop run_loop; |
| blink::mojom::LockScreenServiceStatus result; |
| service->SetData(key, data, |
| base::BindLambdaForTesting( |
| [&](blink::mojom::LockScreenServiceStatus status) { |
| result = status; |
| run_loop.Quit(); |
| })); |
| run_loop.Run(); |
| return result; |
| } |
| |
| std::vector<std::string> AwaitGetKeys( |
| blink::mojom::LockScreenService* service) { |
| base::RunLoop run_loop; |
| std::vector<std::string> result; |
| service->GetKeys( |
| base::BindLambdaForTesting([&](const std::vector<std::string>& keys) { |
| result = keys; |
| run_loop.Quit(); |
| })); |
| run_loop.Run(); |
| return result; |
| } |
| |
| private: |
| base::test::ScopedFeatureList feature_list_; |
| mojo::Remote<blink::mojom::LockScreenService> lock_screen_service_; |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(LockScreenServiceImplBrowserTest, |
| CorrectDirectoryCreated) { |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| base::FilePath expected_dir = GetStoragePath(); |
| EXPECT_FALSE(base::PathExists(expected_dir)); |
| // TODO(crbug.com/40204655): Consider testing write failure case. |
| ASSERT_EQ(blink::mojom::LockScreenServiceStatus::kSuccess, |
| AwaitSetData(service(), "key1", "data1")); |
| ASSERT_TRUE(base::PathExists(expected_dir)); |
| |
| base::FileEnumerator e(expected_dir, false, |
| base::FileEnumerator::DIRECTORIES); |
| std::vector<base::FilePath> directories; |
| for (base::FilePath name = e.Next(); !name.empty(); name = e.Next()) { |
| directories.push_back(name); |
| } |
| ASSERT_EQ(1u, directories.size()); |
| EXPECT_EQ(64u, directories[0].BaseName().MaybeAsASCII().size()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LockScreenServiceImplBrowserTest, SetDataOpaqueOrigin) { |
| auto service = NavigateAndCreateService(GURL("about:blank")); |
| ASSERT_EQ(blink::mojom::LockScreenServiceStatus::kNotAllowedFromContext, |
| AwaitSetData(service.get(), "key1", "data1")); |
| ASSERT_EQ(blink::mojom::LockScreenServiceStatus::kNotAllowedFromContext, |
| AwaitSetData(service.get(), "key2", "data2")); |
| |
| std::vector<std::string> result = AwaitGetKeys(service.get()); |
| ASSERT_EQ(0u, result.size()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LockScreenServiceImplBrowserTest, GetKeys) { |
| std::vector<std::string> result = AwaitGetKeys(service()); |
| ASSERT_EQ(0u, result.size()); |
| |
| AwaitSetData(service(), "key1", "data1"); |
| AwaitSetData(service(), "key2", "data2"); |
| result = AwaitGetKeys(service()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| |
| AwaitSetData(service(), "key2", "data3"); |
| result = AwaitGetKeys(service()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LockScreenServiceImplBrowserTest, |
| DataNotSharedBetweenDifferentOrigins) { |
| GURL url_a = |
| embedded_test_server()->GetURL("a.com", "/lock_screen/simple.html"); |
| GURL url_b = |
| embedded_test_server()->GetURL("b.com", "/lock_screen/simple.html"); |
| auto service_a = NavigateAndCreateService(url_a); |
| auto service_b = NavigateAndCreateService(url_b); |
| |
| AwaitSetData(service_a.get(), "key1", "a"); |
| AwaitSetData(service_a.get(), "key2", "a"); |
| std::vector<std::string> result = AwaitGetKeys(service_a.get()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| |
| AwaitSetData(service_b.get(), "key1", "b"); |
| AwaitSetData(service_b.get(), "key3", "b"); |
| result = AwaitGetKeys(service_b.get()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key3", result[1]); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LockScreenServiceImplBrowserTest, |
| DataSharedBetweenSameOrigins) { |
| GURL url_a = embedded_test_server()->GetURL("/lock_screen/simple.html"); |
| GURL url_b = embedded_test_server()->GetURL("/lock_screen/simple.html?abcd"); |
| auto service_a = NavigateAndCreateService(url_a); |
| auto service_b = NavigateAndCreateService(url_b); |
| |
| AwaitSetData(service_a.get(), "key1", "a"); |
| AwaitSetData(service_a.get(), "key2", "a"); |
| std::vector<std::string> result = AwaitGetKeys(service_a.get()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| |
| result = AwaitGetKeys(service_b.get()); |
| ASSERT_EQ(2u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| |
| AwaitSetData(service_b.get(), "key1", "b"); |
| AwaitSetData(service_b.get(), "key3", "b"); |
| result = AwaitGetKeys(service_a.get()); |
| ASSERT_EQ(3u, result.size()); |
| EXPECT_EQ("key1", result[0]); |
| EXPECT_EQ("key2", result[1]); |
| EXPECT_EQ("key3", result[2]); |
| } |
| |
| } // namespace content |