1 // Copyright 2019 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "content/browser/file_system_access/native_file_system_handle_base.h"
6 
7 #include "base/files/scoped_temp_dir.h"
8 #include "base/test/bind.h"
9 #include "base/test/gmock_callback_support.h"
10 #include "base/test/task_environment.h"
11 #include "content/browser/file_system_access/mock_native_file_system_permission_grant.h"
12 #include "content/public/test/browser_task_environment.h"
13 #include "storage/browser/blob/blob_storage_context.h"
14 #include "storage/browser/test/test_file_system_context.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16 
17 namespace content {
18 
19 using base::test::RunOnceCallback;
20 using blink::mojom::PermissionStatus;
21 using storage::FileSystemURL;
22 using UserActivationState =
23     NativeFileSystemPermissionGrant::UserActivationState;
24 
25 class TestNativeFileSystemHandle : public NativeFileSystemHandleBase {
26  public:
TestNativeFileSystemHandle(NativeFileSystemManagerImpl * manager,const BindingContext & context,const storage::FileSystemURL & url,const SharedHandleState & handle_state)27   TestNativeFileSystemHandle(NativeFileSystemManagerImpl* manager,
28                              const BindingContext& context,
29                              const storage::FileSystemURL& url,
30                              const SharedHandleState& handle_state)
31       : NativeFileSystemHandleBase(manager, context, url, handle_state) {}
32 
33  private:
AsWeakPtr()34   base::WeakPtr<NativeFileSystemHandleBase> AsWeakPtr() override {
35     return weak_factory_.GetWeakPtr();
36   }
37   base::WeakPtrFactory<TestNativeFileSystemHandle> weak_factory_{this};
38 };
39 
40 class NativeFileSystemHandleBaseTest : public testing::Test {
41  public:
NativeFileSystemHandleBaseTest()42   NativeFileSystemHandleBaseTest()
43       : task_environment_(base::test::TaskEnvironment::MainThreadType::IO) {}
44 
SetUp()45   void SetUp() override {
46     ASSERT_TRUE(dir_.CreateUniqueTempDir());
47     file_system_context_ = storage::CreateFileSystemContextForTesting(
48         /*quota_manager_proxy=*/nullptr, dir_.GetPath());
49 
50     chrome_blob_context_ = base::MakeRefCounted<ChromeBlobStorageContext>();
51     chrome_blob_context_->InitializeOnIOThread(base::FilePath(),
52                                                base::FilePath(), nullptr);
53 
54     manager_ = base::MakeRefCounted<NativeFileSystemManagerImpl>(
55         file_system_context_, chrome_blob_context_,
56         /*permission_context=*/nullptr,
57         /*off_the_record=*/false);
58   }
59 
60  protected:
61   const GURL kTestURL = GURL("https://example.com/test");
62   const url::Origin kTestOrigin = url::Origin::Create(kTestURL);
63   BrowserTaskEnvironment task_environment_;
64 
65   base::ScopedTempDir dir_;
66   scoped_refptr<storage::FileSystemContext> file_system_context_;
67   scoped_refptr<ChromeBlobStorageContext> chrome_blob_context_;
68 
69   scoped_refptr<MockNativeFileSystemPermissionGrant> read_grant_ =
70       base::MakeRefCounted<
71           testing::StrictMock<MockNativeFileSystemPermissionGrant>>();
72   scoped_refptr<MockNativeFileSystemPermissionGrant> write_grant_ =
73       base::MakeRefCounted<
74           testing::StrictMock<MockNativeFileSystemPermissionGrant>>();
75 
76   scoped_refptr<NativeFileSystemManagerImpl> manager_;
77 
78   NativeFileSystemManagerImpl::SharedHandleState handle_state_ = {read_grant_,
79                                                                   write_grant_,
80                                                                   {}};
81 };
82 
TEST_F(NativeFileSystemHandleBaseTest,GetReadPermissionStatus)83 TEST_F(NativeFileSystemHandleBaseTest, GetReadPermissionStatus) {
84   auto url =
85       FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest,
86                                    base::FilePath::FromUTF8Unsafe("/test"));
87   TestNativeFileSystemHandle handle(
88       manager_.get(),
89       NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL,
90                                                   /*worker_process_id=*/1),
91       url, handle_state_);
92 
93   EXPECT_CALL(*read_grant_, GetStatus())
94       .WillOnce(testing::Return(PermissionStatus::ASK));
95   EXPECT_EQ(PermissionStatus::ASK, handle.GetReadPermissionStatus());
96 
97   EXPECT_CALL(*read_grant_, GetStatus())
98       .WillOnce(testing::Return(PermissionStatus::GRANTED));
99   EXPECT_EQ(PermissionStatus::GRANTED, handle.GetReadPermissionStatus());
100 }
101 
TEST_F(NativeFileSystemHandleBaseTest,GetWritePermissionStatus_ReadStatusNotGranted)102 TEST_F(NativeFileSystemHandleBaseTest,
103        GetWritePermissionStatus_ReadStatusNotGranted) {
104   auto url =
105       FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest,
106                                    base::FilePath::FromUTF8Unsafe("/test"));
107   TestNativeFileSystemHandle handle(
108       manager_.get(),
109       NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL,
110                                                   /*worker_process_id=*/1),
111       url, handle_state_);
112 
113   EXPECT_CALL(*read_grant_, GetStatus())
114       .WillOnce(testing::Return(PermissionStatus::ASK));
115   EXPECT_EQ(PermissionStatus::ASK, handle.GetWritePermissionStatus());
116 
117   EXPECT_CALL(*read_grant_, GetStatus())
118       .WillOnce(testing::Return(PermissionStatus::DENIED));
119   EXPECT_EQ(PermissionStatus::DENIED, handle.GetWritePermissionStatus());
120 }
121 
TEST_F(NativeFileSystemHandleBaseTest,GetWritePermissionStatus_ReadStatusGranted)122 TEST_F(NativeFileSystemHandleBaseTest,
123        GetWritePermissionStatus_ReadStatusGranted) {
124   auto url =
125       FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest,
126                                    base::FilePath::FromUTF8Unsafe("/test"));
127   TestNativeFileSystemHandle handle(
128       manager_.get(),
129       NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL,
130                                                   /*worker_process_id=*/1),
131       url, handle_state_);
132 
133   EXPECT_CALL(*read_grant_, GetStatus())
134       .WillOnce(testing::Return(PermissionStatus::GRANTED));
135   EXPECT_CALL(*write_grant_, GetStatus())
136       .WillOnce(testing::Return(PermissionStatus::ASK));
137   EXPECT_EQ(PermissionStatus::ASK, handle.GetWritePermissionStatus());
138 }
139 
TEST_F(NativeFileSystemHandleBaseTest,RequestWritePermission_AlreadyGranted)140 TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission_AlreadyGranted) {
141   auto url =
142       FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest,
143                                    base::FilePath::FromUTF8Unsafe("/test"));
144   TestNativeFileSystemHandle handle(
145       manager_.get(),
146       NativeFileSystemManagerImpl::BindingContext(kTestOrigin, kTestURL,
147                                                   /*worker_process_id=*/1),
148       url, handle_state_);
149 
150   EXPECT_CALL(*read_grant_, GetStatus())
151       .WillOnce(testing::Return(PermissionStatus::GRANTED));
152   EXPECT_CALL(*write_grant_, GetStatus())
153       .WillOnce(testing::Return(PermissionStatus::GRANTED));
154 
155   base::RunLoop loop;
156   handle.DoRequestPermission(
157       /*writable=*/true,
158       base::BindLambdaForTesting(
159           [&](blink::mojom::NativeFileSystemErrorPtr error,
160               PermissionStatus result) {
161             EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, error->status);
162             EXPECT_EQ(PermissionStatus::GRANTED, result);
163             loop.Quit();
164           }));
165   loop.Run();
166 }
167 
TEST_F(NativeFileSystemHandleBaseTest,RequestWritePermission)168 TEST_F(NativeFileSystemHandleBaseTest, RequestWritePermission) {
169   const int kProcessId = 1;
170   const int kFrameRoutingId = 2;
171   const GlobalFrameRoutingId kFrameId(kProcessId, kFrameRoutingId);
172 
173   auto url =
174       FileSystemURL::CreateForTest(kTestOrigin, storage::kFileSystemTypeTest,
175                                    base::FilePath::FromUTF8Unsafe("/test"));
176   TestNativeFileSystemHandle handle(manager_.get(),
177                                     NativeFileSystemManagerImpl::BindingContext(
178                                         kTestOrigin, kTestURL, kFrameId),
179                                     url, handle_state_);
180 
181   EXPECT_CALL(*read_grant_, GetStatus())
182       .WillRepeatedly(testing::Return(PermissionStatus::GRANTED));
183   {
184     testing::InSequence sequence;
185     EXPECT_CALL(*write_grant_, GetStatus())
186         .WillOnce(testing::Return(PermissionStatus::ASK));
187     EXPECT_CALL(*write_grant_,
188                 RequestPermission_(kFrameId, UserActivationState::kRequired,
189                                    testing::_))
190         .WillOnce(
191             RunOnceCallback<2>(NativeFileSystemPermissionGrant::
192                                    PermissionRequestOutcome::kUserGranted));
193     EXPECT_CALL(*write_grant_, GetStatus())
194         .WillOnce(testing::Return(PermissionStatus::GRANTED));
195   }
196 
197   base::RunLoop loop;
198   handle.DoRequestPermission(
199       /*writable=*/true,
200       base::BindLambdaForTesting(
201           [&](blink::mojom::NativeFileSystemErrorPtr error,
202               PermissionStatus result) {
203             EXPECT_EQ(blink::mojom::NativeFileSystemStatus::kOk, error->status);
204             EXPECT_EQ(PermissionStatus::GRANTED, result);
205             loop.Quit();
206           }));
207   loop.Run();
208 }
209 
210 }  // namespace content
211