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