1 // Copyright 2018 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 "base/files/file_util.h"
6 #include "base/files/scoped_temp_dir.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "base/test/gmock_callback_support.h"
9 #include "base/test/scoped_feature_list.h"
10 #include "base/threading/thread_restrictions.h"
11 #include "content/browser/native_file_system/file_system_chooser_test_helpers.h"
12 #include "content/browser/native_file_system/mock_native_file_system_permission_context.h"
13 #include "content/browser/native_file_system/native_file_system_manager_impl.h"
14 #include "content/browser/web_contents/web_contents_impl.h"
15 #include "content/public/browser/browser_context.h"
16 #include "content/public/browser/render_process_host.h"
17 #include "content/public/browser/storage_partition.h"
18 #include "content/public/common/content_switches.h"
19 #include "content/public/test/back_forward_cache_util.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "content/public/test/content_browser_test.h"
22 #include "content/public/test/content_browser_test_utils.h"
23 #include "content/shell/browser/shell.h"
24 #include "net/test/embedded_test_server/embedded_test_server.h"
25 #include "third_party/blink/public/common/features.h"
26 #include "third_party/blink/public/mojom/frame/fullscreen.mojom.h"
27 #include "ui/shell_dialogs/select_file_dialog.h"
28 #include "ui/shell_dialogs/select_file_dialog_factory.h"
29 #include "ui/shell_dialogs/select_file_policy.h"
30
31 namespace content {
32
33 using base::test::RunOnceCallback;
34 using blink::mojom::PermissionStatus;
35 using SensitiveDirectoryResult =
36 NativeFileSystemPermissionContext::SensitiveDirectoryResult;
37
38 // This browser test implements end-to-end tests for the chooseFileSystemEntry
39 // API.
40 class FileSystemChooserBrowserTest : public ContentBrowserTest {
41 public:
SetUp()42 void SetUp() override {
43 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
44 scoped_feature_list_.InitAndEnableFeature(
45 blink::features::kNativeFileSystemAPI);
46
47 ASSERT_TRUE(embedded_test_server()->Start());
48
49 ContentBrowserTest::SetUp();
50 }
51
SetUpCommandLine(base::CommandLine * command_line)52 void SetUpCommandLine(base::CommandLine* command_line) override {
53 // Enable experimental web platform features to enable write access.
54 command_line->AppendSwitch(
55 switches::kEnableExperimentalWebPlatformFeatures);
56 }
57
TearDown()58 void TearDown() override {
59 ContentBrowserTest::TearDown();
60 ASSERT_TRUE(temp_dir_.Delete());
61 ui::SelectFileDialog::SetFactory(nullptr);
62 }
63
IsFullscreen()64 bool IsFullscreen() {
65 WebContents* web_contents = shell()->web_contents();
66 return web_contents->IsFullscreenForCurrentTab();
67 }
68
EnterFullscreen(GURL url)69 void EnterFullscreen(GURL url) {
70 WebContentsImpl* web_contents_impl =
71 static_cast<WebContentsImpl*>(shell()->web_contents());
72 web_contents_impl->EnterFullscreenMode(url,
73 blink::mojom::FullscreenOptions());
74 }
75
CreateTestFile(const std::string & contents)76 base::FilePath CreateTestFile(const std::string& contents) {
77 base::ScopedAllowBlockingForTesting allow_blocking;
78 base::FilePath result;
79 EXPECT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.GetPath(), &result));
80 EXPECT_EQ(int{contents.size()},
81 base::WriteFile(result, contents.data(), contents.size()));
82 return result;
83 }
84
CreateTestDir()85 base::FilePath CreateTestDir() {
86 base::ScopedAllowBlockingForTesting allow_blocking;
87 base::FilePath result;
88 EXPECT_TRUE(base::CreateTemporaryDirInDir(
89 temp_dir_.GetPath(), FILE_PATH_LITERAL("test"), &result));
90 return result;
91 }
92
93 private:
94 base::test::ScopedFeatureList scoped_feature_list_;
95 base::ScopedTempDir temp_dir_;
96 };
97
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,CancelDialog)98 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, CancelDialog) {
99 ui::SelectFileDialog::SetFactory(new CancellingSelectFileDialogFactory);
100 ASSERT_TRUE(
101 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
102 auto result = EvalJs(shell(), "self.chooseFileSystemEntries()");
103 EXPECT_TRUE(result.error.find("aborted") != std::string::npos)
104 << result.error;
105 }
106
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,OpenFile)107 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenFile) {
108 const std::string file_contents = "hello world!";
109 const base::FilePath test_file = CreateTestFile(file_contents);
110 SelectFileDialogParams dialog_params;
111 ui::SelectFileDialog::SetFactory(
112 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
113 ASSERT_TRUE(
114 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
115 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
116 EvalJs(shell(),
117 "(async () => {"
118 " let e = await self.chooseFileSystemEntries();"
119 " self.selected_entry = e;"
120 " return e.name; })()"));
121 EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_FILE, dialog_params.type);
122 EXPECT_EQ(shell()->web_contents()->GetTopLevelNativeWindow(),
123 dialog_params.owning_window);
124 EXPECT_EQ(
125 file_contents,
126 EvalJs(shell(),
127 "(async () => { const file = await self.selected_entry.getFile(); "
128 "return await file.text(); })()"));
129 }
130
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,FullscreenOpenFile)131 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenOpenFile) {
132 const std::string file_contents = "hello world!";
133 const base::FilePath test_file = CreateTestFile(file_contents);
134 SelectFileDialogParams dialog_params;
135 ui::SelectFileDialog::SetFactory(
136 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
137 ASSERT_TRUE(
138 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
139 EnterFullscreen(embedded_test_server()->GetURL("/title1.html"));
140 EXPECT_TRUE(IsFullscreen());
141 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
142 EvalJs(shell(),
143 "(async () => {"
144 " let e = await self.chooseFileSystemEntries();"
145 " self.selected_entry = e;"
146 " return e.name; })()"));
147 EXPECT_FALSE(IsFullscreen());
148 }
149
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,SaveFile_NonExistingFile)150 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, SaveFile_NonExistingFile) {
151 const std::string file_contents = "file contents to write";
152 const base::FilePath test_file = CreateTestFile("");
153 {
154 // Delete file, since SaveFile should be able to deal with non-existing
155 // files.
156 base::ScopedAllowBlockingForTesting allow_blocking;
157 ASSERT_TRUE(base::DeleteFile(test_file, false));
158 }
159 SelectFileDialogParams dialog_params;
160 ui::SelectFileDialog::SetFactory(
161 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
162 ASSERT_TRUE(
163 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
164 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
165 EvalJs(shell(),
166 "(async () => {"
167 " let e = await self.chooseFileSystemEntries("
168 " {type: 'save-file'});"
169 " self.entry = e;"
170 " return e.name; })()"));
171 EXPECT_EQ(ui::SelectFileDialog::SELECT_SAVEAS_FILE, dialog_params.type);
172 EXPECT_EQ(int{file_contents.size()},
173 EvalJs(shell(),
174 JsReplace("(async () => {"
175 " const w = await self.entry.createWritable();"
176 " await w.write(new Blob([$1]));"
177 " await w.close();"
178 " return (await self.entry.getFile()).size; })()",
179 file_contents)));
180 {
181 base::ScopedAllowBlockingForTesting allow_blocking;
182 std::string read_contents;
183 EXPECT_TRUE(base::ReadFileToString(test_file, &read_contents));
184 EXPECT_EQ(file_contents, read_contents);
185 }
186 }
187
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,SaveFile_TruncatesExistingFile)188 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
189 SaveFile_TruncatesExistingFile) {
190 const base::FilePath test_file = CreateTestFile("Hello World");
191
192 SelectFileDialogParams dialog_params;
193 ui::SelectFileDialog::SetFactory(
194 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
195 ASSERT_TRUE(
196 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
197 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
198 EvalJs(shell(),
199 "(async () => {"
200 " let e = await self.chooseFileSystemEntries("
201 " {type: 'save-file'});"
202 " self.entry = e;"
203 " return e.name; })()"));
204 EXPECT_EQ(ui::SelectFileDialog::SELECT_SAVEAS_FILE, dialog_params.type);
205 EXPECT_EQ("",
206 EvalJs(shell(),
207 "(async () => { const file = await self.entry.getFile(); "
208 "return await file.text(); })()"));
209 }
210
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,SaveFile_BlockedPermission)211 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
212 SaveFile_BlockedPermission) {
213 const base::FilePath test_file = CreateTestFile("Save File");
214 SelectFileDialogParams dialog_params;
215 ui::SelectFileDialog::SetFactory(
216 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
217
218 testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context;
219 static_cast<NativeFileSystemManagerImpl*>(
220 BrowserContext::GetStoragePartition(
221 shell()->web_contents()->GetBrowserContext(),
222 shell()->web_contents()->GetSiteInstance())
223 ->GetNativeFileSystemEntryFactory())
224 ->SetPermissionContextForTesting(&permission_context);
225
226 EXPECT_CALL(permission_context,
227 CanObtainWritePermission(url::Origin::Create(
228 embedded_test_server()->GetURL("/title1.html"))))
229 .WillOnce(testing::Return(false));
230
231 ASSERT_TRUE(
232 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
233 auto result =
234 EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})");
235 EXPECT_TRUE(result.error.find("not allowed") != std::string::npos)
236 << result.error;
237 EXPECT_EQ(ui::SelectFileDialog::SELECT_NONE, dialog_params.type);
238 }
239
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,FullscreenSaveFile)240 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenSaveFile) {
241 const base::FilePath test_file = CreateTestFile("Hello World");
242
243 SelectFileDialogParams dialog_params;
244 ui::SelectFileDialog::SetFactory(
245 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
246 ASSERT_TRUE(
247 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
248 EnterFullscreen(embedded_test_server()->GetURL("/title1.html"));
249 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
250 EvalJs(shell(),
251 "(async () => {"
252 " let e = await self.chooseFileSystemEntries("
253 " {type: 'save-file'});"
254 " self.entry = e;"
255 " return e.name; })()"));
256 EXPECT_FALSE(IsFullscreen());
257 }
258
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,OpenMultipleFiles)259 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenMultipleFiles) {
260 const base::FilePath test_file1 = CreateTestFile("file1");
261 const base::FilePath test_file2 = CreateTestFile("file2");
262 SelectFileDialogParams dialog_params;
263 ui::SelectFileDialog::SetFactory(new FakeSelectFileDialogFactory(
264 {test_file1, test_file2}, &dialog_params));
265 ASSERT_TRUE(
266 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
267 EXPECT_EQ(ListValueOf(test_file1.BaseName().AsUTF8Unsafe(),
268 test_file2.BaseName().AsUTF8Unsafe()),
269 EvalJs(shell(),
270 "(async () => {"
271 " let e = await self.chooseFileSystemEntries("
272 " {multiple: true});"
273 " return e.map(x => x.name); })()"));
274 EXPECT_EQ(ui::SelectFileDialog::SELECT_OPEN_MULTI_FILE, dialog_params.type);
275 }
276
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,FullscreenOpenMultipleFiles)277 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
278 FullscreenOpenMultipleFiles) {
279 const base::FilePath test_file1 = CreateTestFile("file1");
280 const base::FilePath test_file2 = CreateTestFile("file2");
281 SelectFileDialogParams dialog_params;
282 ui::SelectFileDialog::SetFactory(new FakeSelectFileDialogFactory(
283 {test_file1, test_file2}, &dialog_params));
284 ASSERT_TRUE(
285 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
286 EnterFullscreen(embedded_test_server()->GetURL("/title1.html"));
287 EXPECT_EQ(ListValueOf(test_file1.BaseName().AsUTF8Unsafe(),
288 test_file2.BaseName().AsUTF8Unsafe()),
289 EvalJs(shell(),
290 "(async () => {"
291 " let e = await self.chooseFileSystemEntries("
292 " {multiple: true});"
293 " return e.map(x => x.name); })()"));
294 EXPECT_FALSE(IsFullscreen());
295 }
296
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,OpenDirectory)297 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory) {
298 base::FilePath test_dir = CreateTestDir();
299 SelectFileDialogParams dialog_params;
300 ui::SelectFileDialog::SetFactory(
301 new FakeSelectFileDialogFactory({test_dir}, &dialog_params));
302 ASSERT_TRUE(
303 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
304 EXPECT_EQ(test_dir.BaseName().AsUTF8Unsafe(),
305 EvalJs(shell(),
306 "(async () => {"
307 " let e = await self.chooseFileSystemEntries("
308 " {type: 'open-directory'});"
309 " self.selected_entry = e;"
310 " return e.name; })()"));
311 EXPECT_EQ(ui::SelectFileDialog::SELECT_FOLDER, dialog_params.type);
312 }
313
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,FullscreenOpenDirectory)314 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, FullscreenOpenDirectory) {
315 base::FilePath test_dir = CreateTestDir();
316 SelectFileDialogParams dialog_params;
317 ui::SelectFileDialog::SetFactory(
318 new FakeSelectFileDialogFactory({test_dir}, &dialog_params));
319 ASSERT_TRUE(
320 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
321 EnterFullscreen(embedded_test_server()->GetURL("/title1.html"));
322 EXPECT_EQ(test_dir.BaseName().AsUTF8Unsafe(),
323 EvalJs(shell(),
324 "(async () => {"
325 " let e = await self.chooseFileSystemEntries("
326 " {type: 'open-directory'});"
327 " self.selected_entry = e;"
328 " return e.name; })()"));
329 EXPECT_FALSE(IsFullscreen());
330 }
331
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,OpenDirectory_DenyAccess)332 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, OpenDirectory_DenyAccess) {
333 base::FilePath test_dir = CreateTestDir();
334 SelectFileDialogParams dialog_params;
335 ui::SelectFileDialog::SetFactory(
336 new FakeSelectFileDialogFactory({test_dir}, &dialog_params));
337
338 testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context;
339 static_cast<NativeFileSystemManagerImpl*>(
340 BrowserContext::GetStoragePartition(
341 shell()->web_contents()->GetBrowserContext(),
342 shell()->web_contents()->GetSiteInstance())
343 ->GetNativeFileSystemEntryFactory())
344 ->SetPermissionContextForTesting(&permission_context);
345
346 EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_(
347 testing::_, testing::_, testing::_,
348 testing::_, testing::_, testing::_))
349 .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAllowed));
350
351 EXPECT_CALL(
352 permission_context,
353 ConfirmDirectoryReadAccess_(
354 url::Origin::Create(embedded_test_server()->GetURL("/title1.html")),
355 test_dir,
356 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
357 shell()->web_contents()->GetMainFrame()->GetRoutingID(), testing::_))
358 .WillOnce(RunOnceCallback<4>(PermissionStatus::DENIED));
359
360 ASSERT_TRUE(
361 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
362 auto result =
363 EvalJs(shell(), "self.chooseFileSystemEntries({type: 'open-directory'})");
364 EXPECT_TRUE(result.error.find("aborted") != std::string::npos)
365 << result.error;
366 }
367
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,SaveFile_SensitiveDirectory_ExistingFile)368 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
369 SaveFile_SensitiveDirectory_ExistingFile) {
370 const std::string file_contents = "Hello World";
371 const base::FilePath test_file = CreateTestFile(file_contents);
372
373 SelectFileDialogParams dialog_params;
374 ui::SelectFileDialog::SetFactory(
375 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
376
377 testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context;
378 static_cast<NativeFileSystemManagerImpl*>(
379 BrowserContext::GetStoragePartition(
380 shell()->web_contents()->GetBrowserContext(),
381 shell()->web_contents()->GetSiteInstance())
382 ->GetNativeFileSystemEntryFactory())
383 ->SetPermissionContextForTesting(&permission_context);
384
385 EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_(
386 testing::_, testing::_, testing::_,
387 testing::_, testing::_, testing::_))
388 .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort));
389
390 EXPECT_CALL(permission_context,
391 CanObtainWritePermission(url::Origin::Create(
392 embedded_test_server()->GetURL("/title1.html"))))
393 .WillOnce(testing::Return(true));
394
395 ASSERT_TRUE(
396 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
397 auto result =
398 EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})");
399 EXPECT_TRUE(result.error.find("aborted") != std::string::npos)
400 << result.error;
401
402 {
403 // File should still exist, and be unmodified.
404 base::ScopedAllowBlockingForTesting allow_blocking;
405 std::string read_contents;
406 EXPECT_TRUE(base::ReadFileToString(test_file, &read_contents));
407 EXPECT_EQ(file_contents, read_contents);
408 }
409 }
410
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,SaveFile_SensitiveDirectory_NonExistingFile)411 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
412 SaveFile_SensitiveDirectory_NonExistingFile) {
413 const base::FilePath test_file = CreateTestFile("");
414 {
415 // Delete file, since SaveFile should be able to deal with non-existing
416 // files.
417 base::ScopedAllowBlockingForTesting allow_blocking;
418 ASSERT_TRUE(base::DeleteFile(test_file, false));
419 }
420
421 SelectFileDialogParams dialog_params;
422 ui::SelectFileDialog::SetFactory(
423 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
424
425 testing::StrictMock<MockNativeFileSystemPermissionContext> permission_context;
426 static_cast<NativeFileSystemManagerImpl*>(
427 BrowserContext::GetStoragePartition(
428 shell()->web_contents()->GetBrowserContext(),
429 shell()->web_contents()->GetSiteInstance())
430 ->GetNativeFileSystemEntryFactory())
431 ->SetPermissionContextForTesting(&permission_context);
432
433 EXPECT_CALL(permission_context, ConfirmSensitiveDirectoryAccess_(
434 testing::_, testing::_, testing::_,
435 testing::_, testing::_, testing::_))
436 .WillOnce(RunOnceCallback<5>(SensitiveDirectoryResult::kAbort));
437
438 EXPECT_CALL(permission_context,
439 CanObtainWritePermission(url::Origin::Create(
440 embedded_test_server()->GetURL("/title1.html"))))
441 .WillOnce(testing::Return(true));
442
443 ASSERT_TRUE(
444 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
445 auto result =
446 EvalJs(shell(), "self.chooseFileSystemEntries({type: 'save-file'})");
447 EXPECT_TRUE(result.error.find("aborted") != std::string::npos)
448 << result.error;
449
450 {
451 // File should not have been created.
452 base::ScopedAllowBlockingForTesting allow_blocking;
453 EXPECT_FALSE(base::PathExists(test_file));
454 }
455 }
456
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,AcceptsOptions)457 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest, AcceptsOptions) {
458 SelectFileDialogParams dialog_params;
459 ui::SelectFileDialog::SetFactory(
460 new CancellingSelectFileDialogFactory(&dialog_params));
461 ASSERT_TRUE(
462 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
463 auto result = EvalJs(shell(),
464 "self.chooseFileSystemEntries({accepts: ["
465 " {description: 'no-extensions'},"
466 " {description: 'foo', extensions: ['txt', 'Js']},"
467 " {mimeTypes: ['image/jpeg']}"
468 "]})");
469 EXPECT_TRUE(result.error.find("aborted") != std::string::npos)
470 << result.error;
471
472 ASSERT_TRUE(dialog_params.file_types);
473 EXPECT_TRUE(dialog_params.file_types->include_all_files);
474 ASSERT_EQ(2u, dialog_params.file_types->extensions.size());
475 ASSERT_EQ(2u, dialog_params.file_types->extensions[0].size());
476 EXPECT_EQ(FILE_PATH_LITERAL("Js"),
477 dialog_params.file_types->extensions[0][0]);
478 EXPECT_EQ(FILE_PATH_LITERAL("txt"),
479 dialog_params.file_types->extensions[0][1]);
480 EXPECT_TRUE(base::Contains(dialog_params.file_types->extensions[1],
481 FILE_PATH_LITERAL("jpg")));
482 EXPECT_TRUE(base::Contains(dialog_params.file_types->extensions[1],
483 FILE_PATH_LITERAL("jpeg")));
484
485 ASSERT_EQ(2u,
486 dialog_params.file_types->extension_description_overrides.size());
487 EXPECT_EQ(base::ASCIIToUTF16("foo"),
488 dialog_params.file_types->extension_description_overrides[0]);
489 EXPECT_EQ(base::ASCIIToUTF16(""),
490 dialog_params.file_types->extension_description_overrides[1]);
491 }
492
IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,NativeFileSystemUsageDisablesBackForwardCache)493 IN_PROC_BROWSER_TEST_F(FileSystemChooserBrowserTest,
494 NativeFileSystemUsageDisablesBackForwardCache) {
495 BackForwardCacheDisabledTester tester;
496
497 const base::FilePath test_file = CreateTestFile("file contents");
498 SelectFileDialogParams dialog_params;
499 ui::SelectFileDialog::SetFactory(
500 new FakeSelectFileDialogFactory({test_file}, &dialog_params));
501 ASSERT_TRUE(
502 NavigateToURL(shell(), embedded_test_server()->GetURL("/title1.html")));
503 EXPECT_EQ(test_file.BaseName().AsUTF8Unsafe(),
504 EvalJs(shell(),
505 "(async () => {"
506 " let e = await self.chooseFileSystemEntries();"
507 " self.selected_entry = e;"
508 " return e.name; })()"));
509 EXPECT_TRUE(tester.IsDisabledForFrameWithReason(
510 shell()->web_contents()->GetMainFrame()->GetProcess()->GetID(),
511 shell()->web_contents()->GetMainFrame()->GetRoutingID(),
512 "NativeFileSystem"));
513 }
514
515 } // namespace content
516