1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/file_select_helper.h"
13 #include "base/command_line.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/memory/raw_ptr.h"
18 #include "base/path_service.h"
19 #include "base/process/launch.h"
20 #include "build/build_config.h"
21 #include "chrome/common/chrome_paths.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "content/public/browser/file_select_listener.h"
24 #include "content/public/test/browser_task_environment.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "ui/shell_dialogs/selected_file_info.h"
28 using blink::mojom::FileChooserParams;
30 #if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
33 // A listener that remembers the list of files chosen. The |files| argument
34 // to the ctor must outlive the listener.
35 class TestFileSelectListener : public content::FileSelectListener {
37 explicit TestFileSelectListener(
38 std::vector<blink::mojom::FileChooserFileInfoPtr>* files)
42 ~TestFileSelectListener() override = default;
43 // content::FileSelectListener overrides.
44 void FileSelected(std::vector<blink::mojom::FileChooserFileInfoPtr> files,
45 const base::FilePath& base_dir,
46 blink::mojom::FileChooserParams::Mode mode) override {
47 *files_ = std::move(files);
49 void FileSelectionCanceled() override {}
51 raw_ptr<std::vector<blink::mojom::FileChooserFileInfoPtr>> files_;
54 // Fill in the arguments to be passed to the ContentAnalysisCompletionCallback()
55 // method based on a list of paths and the desired result for each path.
56 // This function simulates a path either passing the deep scan (status of true)
57 // or failing (status of false).
58 void PrepareContentAnalysisCompletionCallbackArgs(
59 std::vector<base::FilePath> paths,
60 std::vector<bool> status,
61 std::vector<blink::mojom::FileChooserFileInfoPtr>* orig_files,
62 enterprise_connectors::ContentAnalysisDelegate::Data* data,
63 enterprise_connectors::ContentAnalysisDelegate::Result* result) {
64 DCHECK_EQ(status.size(), paths.size());
67 for (auto& path : paths) {
68 orig_files->push_back(blink::mojom::FileChooserFileInfo::NewNativeFile(
69 blink::mojom::NativeFileInfo::New(path,
70 path.BaseName().AsUTF16Unsafe())));
74 data->paths = std::move(paths);
75 result->paths_results = std::move(status);
79 #endif // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
81 class FileSelectHelperTest : public testing::Test {
83 FileSelectHelperTest() {}
85 FileSelectHelperTest(const FileSelectHelperTest&) = delete;
86 FileSelectHelperTest& operator=(const FileSelectHelperTest&) = delete;
89 void SetUp() override {
90 ASSERT_TRUE(base::PathService::Get(chrome::DIR_TEST_DATA, &data_dir_));
91 data_dir_ = data_dir_.AppendASCII("file_select_helper");
92 ASSERT_TRUE(base::PathExists(data_dir_));
95 // The path to input data used in tests.
96 base::FilePath data_dir_;
99 TEST_F(FileSelectHelperTest, IsAcceptTypeValid) {
100 EXPECT_TRUE(FileSelectHelper::IsAcceptTypeValid("a/b"));
101 EXPECT_TRUE(FileSelectHelper::IsAcceptTypeValid("abc/def"));
102 EXPECT_TRUE(FileSelectHelper::IsAcceptTypeValid("abc/*"));
103 EXPECT_TRUE(FileSelectHelper::IsAcceptTypeValid(".a"));
104 EXPECT_TRUE(FileSelectHelper::IsAcceptTypeValid(".abc"));
106 EXPECT_FALSE(FileSelectHelper::IsAcceptTypeValid("."));
107 EXPECT_FALSE(FileSelectHelper::IsAcceptTypeValid("/"));
108 EXPECT_FALSE(FileSelectHelper::IsAcceptTypeValid("ABC/*"));
109 EXPECT_FALSE(FileSelectHelper::IsAcceptTypeValid("abc/def "));
112 #if BUILDFLAG(IS_MAC)
113 TEST_F(FileSelectHelperTest, ZipPackage) {
115 const char app_name[] = "CalculatorFake.app";
116 base::FilePath src = data_dir_.Append(app_name);
117 base::FilePath dest = FileSelectHelper::ZipPackage(src);
118 ASSERT_FALSE(dest.empty());
119 ASSERT_TRUE(base::PathExists(dest));
121 base::ScopedTempDir temp_dir;
122 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
124 // Unzip the package into a temporary directory.
125 base::CommandLine cl(base::FilePath("/usr/bin/unzip"));
126 cl.AppendArg(dest.value().c_str());
128 cl.AppendArg(temp_dir.GetPath().value().c_str());
130 EXPECT_TRUE(base::GetAppOutput(cl, &output));
132 // Verify that several key files haven't changed.
133 const char* files_to_verify[] = {"Contents/Info.plist",
134 "Contents/MacOS/Calculator",
135 "Contents/_CodeSignature/CodeResources"};
136 size_t file_count = std::size(files_to_verify);
137 for (size_t i = 0; i < file_count; i++) {
138 const char* relative_path = files_to_verify[i];
139 base::FilePath orig_file = src.Append(relative_path);
140 base::FilePath final_file =
141 temp_dir.GetPath().Append(app_name).Append(relative_path);
142 EXPECT_TRUE(base::ContentsEqual(orig_file, final_file));
145 #endif // BUILDFLAG(IS_MAC)
147 TEST_F(FileSelectHelperTest, GetSanitizedFileName) {
148 // The empty path should be preserved.
149 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("")),
150 FileSelectHelper::GetSanitizedFileName(base::FilePath()));
152 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("ascii.txt")),
153 FileSelectHelper::GetSanitizedFileName(
154 base::FilePath(FILE_PATH_LITERAL("ascii.txt"))));
155 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("trailing-spaces_")),
156 FileSelectHelper::GetSanitizedFileName(
157 base::FilePath(FILE_PATH_LITERAL("trailing-spaces "))));
158 EXPECT_EQ(base::FilePath(FILE_PATH_LITERAL("path_components_in_name")),
159 FileSelectHelper::GetSanitizedFileName(
160 base::FilePath(FILE_PATH_LITERAL("path/components/in/name"))));
162 #if BUILDFLAG(IS_WIN)
163 // Invalid UTF-16. However, note that on Windows, the invalid UTF-16 will pass
164 // through without error.
165 base::FilePath::CharType kBadName[] = {0xd801, 0xdc37, 0xdc17, 0};
168 base::FilePath::CharType kBadName[] = {'\xe3', '\x81', '\x81',
169 '\x81', '\x82', '\0'};
171 base::FilePath bad_filename(kBadName);
172 ASSERT_FALSE(bad_filename.empty());
173 // The only thing we are testing is that if the source filename was non-empty,
174 // the resulting filename is also not empty. Invalid encoded filenames can
175 // cause conversions to fail. Such failures shouldn't cause the resulting
176 // filename to disappear.
177 EXPECT_FALSE(FileSelectHelper::GetSanitizedFileName(bad_filename).empty());
180 TEST_F(FileSelectHelperTest, LastSelectedDirectory) {
181 content::BrowserTaskEnvironment task_environment;
182 TestingProfile profile;
183 scoped_refptr<FileSelectHelper> file_select_helper =
184 new FileSelectHelper(&profile);
187 void* params = nullptr;
189 const base::FilePath dir_path_1 = data_dir_.AppendASCII("dir1");
190 const base::FilePath dir_path_2 = data_dir_.AppendASCII("dir2");
191 const base::FilePath file_path_1 = dir_path_1.AppendASCII("file1.txt");
192 const base::FilePath file_path_2 = dir_path_1.AppendASCII("file2.txt");
193 const base::FilePath file_path_3 = dir_path_2.AppendASCII("file3.txt");
194 std::vector<base::FilePath> files; // Both in dir1.
195 files.push_back(file_path_1);
196 files.push_back(file_path_2);
197 std::vector<base::FilePath> dirs;
198 dirs.push_back(dir_path_1);
199 dirs.push_back(dir_path_2);
201 // Modes where the parent of the selection is remembered.
202 const std::vector<FileChooserParams::Mode> modes = {
203 FileChooserParams::Mode::kOpen, FileChooserParams::Mode::kOpenMultiple,
204 FileChooserParams::Mode::kSave,
207 for (const auto& mode : modes) {
208 file_select_helper->dialog_mode_ = mode;
210 file_select_helper->AddRef(); // Normally called by RunFileChooser().
211 file_select_helper->FileSelected(file_path_1, index, params);
212 EXPECT_EQ(dir_path_1, profile.last_selected_directory());
214 file_select_helper->AddRef(); // Normally called by RunFileChooser().
215 file_select_helper->FileSelected(file_path_2, index, params);
216 EXPECT_EQ(dir_path_1, profile.last_selected_directory());
218 file_select_helper->AddRef(); // Normally called by RunFileChooser().
219 file_select_helper->FileSelected(file_path_3, index, params);
220 EXPECT_EQ(dir_path_2, profile.last_selected_directory());
222 file_select_helper->AddRef(); // Normally called by RunFileChooser().
223 file_select_helper->MultiFilesSelected(files, params);
224 EXPECT_EQ(dir_path_1, profile.last_selected_directory());
227 // Type where the selected folder itself is remembered.
228 file_select_helper->dialog_mode_ = FileChooserParams::Mode::kUploadFolder;
230 file_select_helper->AddRef(); // Normally called by RunFileChooser().
231 file_select_helper->FileSelected(dir_path_1, index, params);
232 EXPECT_EQ(dir_path_1, profile.last_selected_directory());
234 file_select_helper->AddRef(); // Normally called by RunFileChooser().
235 file_select_helper->FileSelected(dir_path_2, index, params);
236 EXPECT_EQ(dir_path_2, profile.last_selected_directory());
238 file_select_helper->AddRef(); // Normally called by RunFileChooser().
239 file_select_helper->MultiFilesSelected(dirs, params);
240 EXPECT_EQ(dir_path_1, profile.last_selected_directory());
243 // The following tests depend on the enterprise cloud content analysis feature
245 #if BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)
247 TEST_F(FileSelectHelperTest, ContentAnalysisCompletionCallback_NoFiles) {
248 content::BrowserTaskEnvironment task_environment;
249 TestingProfile profile;
250 scoped_refptr<FileSelectHelper> file_select_helper =
251 new FileSelectHelper(&profile);
253 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
254 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
255 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
256 file_select_helper->DontAbortOnMissingWebContentsForTesting();
258 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
259 enterprise_connectors::ContentAnalysisDelegate::Data data;
260 enterprise_connectors::ContentAnalysisDelegate::Result result;
261 file_select_helper->AddRef(); // Normally called by RunFileChooser().
262 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
265 EXPECT_EQ(0u, files.size());
268 TEST_F(FileSelectHelperTest, ContentAnalysisCompletionCallback_OneOKFile) {
269 content::BrowserTaskEnvironment task_environment;
270 TestingProfile profile;
271 scoped_refptr<FileSelectHelper> file_select_helper =
272 new FileSelectHelper(&profile);
274 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
275 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
276 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
277 file_select_helper->DontAbortOnMissingWebContentsForTesting();
279 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
280 enterprise_connectors::ContentAnalysisDelegate::Data data;
281 enterprise_connectors::ContentAnalysisDelegate::Result result;
282 PrepareContentAnalysisCompletionCallbackArgs(
283 {data_dir_.AppendASCII("foo.doc")}, {true}, &orig_files, &data, &result);
285 file_select_helper->AddRef(); // Normally called by RunFileChooser().
286 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
289 EXPECT_EQ(1u, files.size());
292 TEST_F(FileSelectHelperTest, ContentAnalysisCompletionCallback_TwoOKFiles) {
293 content::BrowserTaskEnvironment task_environment;
294 TestingProfile profile;
295 scoped_refptr<FileSelectHelper> file_select_helper =
296 new FileSelectHelper(&profile);
298 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
299 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
300 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
301 file_select_helper->DontAbortOnMissingWebContentsForTesting();
303 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
304 enterprise_connectors::ContentAnalysisDelegate::Data data;
305 enterprise_connectors::ContentAnalysisDelegate::Result result;
306 PrepareContentAnalysisCompletionCallbackArgs(
307 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
308 {true, true}, &orig_files, &data, &result);
310 file_select_helper->AddRef(); // Normally called by RunFileChooser().
311 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
314 EXPECT_EQ(2u, files.size());
317 TEST_F(FileSelectHelperTest, ContentAnalysisCompletionCallback_TwoBadFiles) {
318 content::BrowserTaskEnvironment task_environment;
319 TestingProfile profile;
320 scoped_refptr<FileSelectHelper> file_select_helper =
321 new FileSelectHelper(&profile);
323 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
324 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
325 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
326 file_select_helper->DontAbortOnMissingWebContentsForTesting();
328 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
329 enterprise_connectors::ContentAnalysisDelegate::Data data;
330 enterprise_connectors::ContentAnalysisDelegate::Result result;
331 PrepareContentAnalysisCompletionCallbackArgs(
332 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
333 {false, false}, &orig_files, &data, &result);
335 file_select_helper->AddRef(); // Normally called by RunFileChooser().
336 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
339 EXPECT_EQ(0u, files.size());
342 TEST_F(FileSelectHelperTest, ContentAnalysisCompletionCallback_OKBadFiles) {
343 content::BrowserTaskEnvironment task_environment;
344 TestingProfile profile;
345 scoped_refptr<FileSelectHelper> file_select_helper =
346 new FileSelectHelper(&profile);
348 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
349 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
350 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
351 file_select_helper->DontAbortOnMissingWebContentsForTesting();
353 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
354 enterprise_connectors::ContentAnalysisDelegate::Data data;
355 enterprise_connectors::ContentAnalysisDelegate::Result result;
356 PrepareContentAnalysisCompletionCallbackArgs(
357 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
358 {false, true}, &orig_files, &data, &result);
360 file_select_helper->AddRef(); // Normally called by RunFileChooser().
361 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
364 ASSERT_EQ(1u, files.size());
365 EXPECT_EQ(data_dir_.AppendASCII("bar.doc"),
366 files[0]->get_native_file()->file_path);
369 TEST_F(FileSelectHelperTest,
370 ContentAnalysisCompletionCallback_SystemFilesSkipped) {
371 content::BrowserTaskEnvironment task_environment;
372 TestingProfile profile;
373 scoped_refptr<FileSelectHelper> file_select_helper =
374 new FileSelectHelper(&profile);
376 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
377 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
378 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
379 file_select_helper->DontAbortOnMissingWebContentsForTesting();
381 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
382 enterprise_connectors::ContentAnalysisDelegate::Data data;
383 enterprise_connectors::ContentAnalysisDelegate::Result result;
385 for (int i = 0; i < 5; ++i) {
386 orig_files.push_back(blink::mojom::FileChooserFileInfo::NewFileSystem(
387 blink::mojom::FileSystemFileInfo::New()));
390 file_select_helper->AddRef(); // Normally called by RunFileChooser().
391 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
394 ASSERT_EQ(5u, files.size());
395 for (int i = 0; i < 5; ++i)
396 EXPECT_TRUE(files[i]->is_file_system());
399 TEST_F(FileSelectHelperTest,
400 ContentAnalysisCompletionCallback_SystemOKBadFiles) {
401 content::BrowserTaskEnvironment task_environment;
402 TestingProfile profile;
403 scoped_refptr<FileSelectHelper> file_select_helper =
404 new FileSelectHelper(&profile);
406 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
407 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
408 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
409 file_select_helper->DontAbortOnMissingWebContentsForTesting();
411 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
412 enterprise_connectors::ContentAnalysisDelegate::Data data;
413 enterprise_connectors::ContentAnalysisDelegate::Result result;
415 // Add 1 non-native file at the start and end of the files list, which should
417 orig_files.push_back(blink::mojom::FileChooserFileInfo::NewFileSystem(
418 blink::mojom::FileSystemFileInfo::New()));
419 PrepareContentAnalysisCompletionCallbackArgs(
420 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
421 {false, true}, &orig_files, &data, &result);
422 orig_files.push_back(blink::mojom::FileChooserFileInfo::NewFileSystem(
423 blink::mojom::FileSystemFileInfo::New()));
425 file_select_helper->AddRef(); // Normally called by RunFileChooser().
426 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
429 ASSERT_EQ(3u, files.size());
430 EXPECT_TRUE(files[0]->is_file_system());
431 EXPECT_TRUE(files[1]->is_native_file());
432 EXPECT_EQ(data_dir_.AppendASCII("bar.doc"),
433 files[1]->get_native_file()->file_path);
434 EXPECT_TRUE(files[2]->is_file_system());
437 TEST_F(FileSelectHelperTest,
438 ContentAnalysisCompletionCallback_FolderUpload_OK) {
439 content::BrowserTaskEnvironment task_environment;
440 TestingProfile profile;
441 scoped_refptr<FileSelectHelper> file_select_helper =
442 new FileSelectHelper(&profile);
444 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
445 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
446 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
447 file_select_helper->DontAbortOnMissingWebContentsForTesting();
449 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
450 enterprise_connectors::ContentAnalysisDelegate::Data data;
451 enterprise_connectors::ContentAnalysisDelegate::Result result;
453 // Set the dialog type to folder upload to test folder handling logic.
454 file_select_helper->dialog_type_ = ui::SelectFileDialog::SELECT_UPLOAD_FOLDER;
455 PrepareContentAnalysisCompletionCallbackArgs(
456 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
457 {true, true}, &orig_files, &data, &result);
459 // Calling the content analysis completion callback would normally
460 // release `file_select_helper`, so we add a reference and validate that
461 // it goes down to 1 after the call.
462 file_select_helper->AddRef();
463 EXPECT_FALSE(file_select_helper->HasOneRef());
464 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
467 EXPECT_TRUE(file_select_helper->HasOneRef());
468 EXPECT_EQ(2u, files.size());
471 TEST_F(FileSelectHelperTest,
472 ContentAnalysisCompletionCallback_FolderUpload_Bad) {
473 content::BrowserTaskEnvironment task_environment;
474 TestingProfile profile;
475 scoped_refptr<FileSelectHelper> file_select_helper =
476 new FileSelectHelper(&profile);
478 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
479 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
480 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
481 file_select_helper->DontAbortOnMissingWebContentsForTesting();
483 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
484 enterprise_connectors::ContentAnalysisDelegate::Data data;
485 enterprise_connectors::ContentAnalysisDelegate::Result result;
487 // Set the dialog type to folder upload to test folder handling logic.
488 file_select_helper->dialog_type_ = ui::SelectFileDialog::SELECT_UPLOAD_FOLDER;
489 PrepareContentAnalysisCompletionCallbackArgs(
490 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
491 {false, false}, &orig_files, &data, &result);
493 // Calling the content analysis completion callback would normally
494 // release `file_select_helper`, so we add a reference and validate that
495 // it goes down to 1 after the call.
496 file_select_helper->AddRef();
497 EXPECT_FALSE(file_select_helper->HasOneRef());
498 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
500 EXPECT_TRUE(file_select_helper->HasOneRef());
501 EXPECT_EQ(0u, files.size());
504 TEST_F(FileSelectHelperTest,
505 ContentAnalysisCompletionCallback_FolderUpload_OKBad) {
506 content::BrowserTaskEnvironment task_environment;
507 TestingProfile profile;
508 scoped_refptr<FileSelectHelper> file_select_helper =
509 new FileSelectHelper(&profile);
511 std::vector<blink::mojom::FileChooserFileInfoPtr> files;
512 auto listener = base::MakeRefCounted<TestFileSelectListener>(&files);
513 file_select_helper->SetFileSelectListenerForTesting(std::move(listener));
514 file_select_helper->DontAbortOnMissingWebContentsForTesting();
516 std::vector<blink::mojom::FileChooserFileInfoPtr> orig_files;
517 enterprise_connectors::ContentAnalysisDelegate::Data data;
518 enterprise_connectors::ContentAnalysisDelegate::Result result;
520 // Set the dialog type to folder upload to test folder handling logic.
521 file_select_helper->dialog_type_ = ui::SelectFileDialog::SELECT_UPLOAD_FOLDER;
522 PrepareContentAnalysisCompletionCallbackArgs(
523 {data_dir_.AppendASCII("foo.doc"), data_dir_.AppendASCII("bar.doc")},
524 {true, false}, &orig_files, &data, &result);
526 // Calling the content analysis completion callback would normally
527 // release `file_select_helper`, so we add a reference and validate that
528 // it goes down to 1 after the call.
529 file_select_helper->AddRef();
530 EXPECT_FALSE(file_select_helper->HasOneRef());
531 file_select_helper->ContentAnalysisCompletionCallback(std::move(orig_files),
534 EXPECT_TRUE(file_select_helper->HasOneRef());
535 // Files should be cleared.
536 EXPECT_EQ(0u, files.size());
539 TEST_F(FileSelectHelperTest, GetFileTypesFromAcceptType) {
540 content::BrowserTaskEnvironment task_environment;
541 TestingProfile profile;
542 scoped_refptr<FileSelectHelper> file_select_helper =
543 new FileSelectHelper(&profile);
545 std::vector<std::u16string> accept_types{
546 // normal file extension
548 // file extension with some chinese
550 // file extension with fire emoji
554 // non-ascii mime type which should be ignored
557 std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> file_type_info =
558 file_select_helper->GetFileTypesFromAcceptType(accept_types);
560 std::vector<std::vector<base::FilePath::StringType>> expected_extensions{
561 std::vector<base::FilePath::StringType>{
562 #if BUILDFLAG(IS_WIN)
563 L"mp4", L"斤拷锟", L"🔥", L"png"}};
565 "mp4", "斤拷锟", "🔥", "png"}};
567 ASSERT_EQ(expected_extensions, file_type_info->extensions);
570 // This test depends on platform-specific mappings from mime types to file
571 // extensions in PlatformMimeUtil. It would seem that Linux does not offer a way
572 // to get extensions, and our Windows implementation still needs to be updated.
573 #if BUILDFLAG(IS_MAC)
574 TEST_F(FileSelectHelperTest, MultipleFileExtensionsForMime) {
575 content::BrowserTaskEnvironment task_environment;
576 TestingProfile profile;
577 scoped_refptr<FileSelectHelper> file_select_helper =
578 new FileSelectHelper(&profile);
580 std::vector<std::u16string> accept_types{u"application/vnd.ms-powerpoint"};
581 std::unique_ptr<ui::SelectFileDialog::FileTypeInfo> file_type_info =
582 file_select_helper->GetFileTypesFromAcceptType(accept_types);
584 std::vector<base::FilePath::StringType> expected_extensions {
585 #if BUILDFLAG(IS_WIN)
586 L"ppt", L"pot", L"pps"
592 std::sort(expected_extensions.begin(), expected_extensions.end());
594 ASSERT_EQ(file_type_info->extensions.size(), 1u);
595 std::vector<base::FilePath::StringType> actual_extensions =
596 file_type_info->extensions[0];
597 std::sort(actual_extensions.begin(), actual_extensions.end());
599 EXPECT_EQ(expected_extensions, actual_extensions);
603 #endif // BUILDFLAG(ENTERPRISE_CLOUD_CONTENT_ANALYSIS)