1// Copyright (c) 2012 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_path.h" 6#include "base/strings/string_split.h" 7#include "base/strings/utf_string_conversions.h" 8#include "chrome/browser/extensions/api/file_system/file_system_api.h" 9#include "testing/gtest/include/gtest/gtest.h" 10#include "ui/shell_dialogs/select_file_dialog.h" 11 12using extensions::FileSystemChooseEntryFunction; 13using extensions::api::file_system::AcceptOption; 14 15namespace { 16 17void CheckExtensions(const std::vector<base::FilePath::StringType>& expected, 18 std::vector<base::FilePath::StringType>& actual) { 19 EXPECT_EQ(expected.size(), actual.size()); 20 if (expected.size() != actual.size()) 21 return; 22 23 for (size_t i = 0; i < expected.size(); ++i) { 24 EXPECT_EQ(expected[i], actual[i]); 25 } 26} 27 28AcceptOption* BuildAcceptOption(std::string description, 29 std::string mime_types, 30 std::string extensions) { 31 AcceptOption* option = new AcceptOption(); 32 33 if (!description.empty()) 34 option->description.reset(new std::string(description)); 35 36 if (!mime_types.empty()) { 37 option->mime_types.reset(new std::vector<std::string>()); 38 base::SplitString(mime_types, ',', option->mime_types.get()); 39 } 40 41 if (!extensions.empty()) { 42 option->extensions.reset(new std::vector<std::string>()); 43 base::SplitString(extensions, ',', option->extensions.get()); 44 } 45 46 return option; 47} 48 49#if defined(OS_WIN) 50#define ToStringType UTF8ToWide 51#else 52#define ToStringType 53#endif 54 55} // namespace 56 57class FileSystemApiUnitTest : public testing::Test { 58}; 59 60TEST_F(FileSystemApiUnitTest, FileSystemChooseEntryFunctionFileTypeInfoTest) { 61 // AcceptsAllTypes is ignored when no other extensions are available. 62 ui::SelectFileDialog::FileTypeInfo file_type_info; 63 bool acceptsAllTypes = false; 64 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 65 base::FilePath::StringType(), NULL, &acceptsAllTypes); 66 EXPECT_TRUE(file_type_info.include_all_files); 67 EXPECT_TRUE(file_type_info.extensions.empty()); 68 69 // Test grouping of multiple types. 70 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 71 std::vector<linked_ptr<AcceptOption> > options; 72 options.push_back(linked_ptr<AcceptOption>(BuildAcceptOption( 73 std::string(), "application/x-chrome-extension", "jso"))); 74 acceptsAllTypes = false; 75 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 76 base::FilePath::StringType(), &options, &acceptsAllTypes); 77 EXPECT_FALSE(file_type_info.include_all_files); 78 ASSERT_EQ(file_type_info.extensions.size(), (size_t) 1); 79 EXPECT_TRUE(file_type_info.extension_description_overrides[0].empty()) << 80 "No override must be specified for boring accept types"; 81 // Note here (and below) that the expectedTypes are sorted, because we use a 82 // set internally to generate the output: thus, the output is sorted. 83 std::vector<base::FilePath::StringType> expectedTypes; 84 expectedTypes.push_back(ToStringType("crx")); 85 expectedTypes.push_back(ToStringType("jso")); 86 CheckExtensions(expectedTypes, file_type_info.extensions[0]); 87 88 // Test that not satisfying the extension will force all types. 89 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 90 options.clear(); 91 options.push_back(linked_ptr<AcceptOption>( 92 BuildAcceptOption(std::string(), std::string(), "unrelated"))); 93 acceptsAllTypes = false; 94 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 95 ToStringType(".jso"), &options, &acceptsAllTypes); 96 EXPECT_TRUE(file_type_info.include_all_files); 97 98 // Test multiple list entries, all containing their own types. 99 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 100 options.clear(); 101 options.push_back(linked_ptr<AcceptOption>( 102 BuildAcceptOption(std::string(), std::string(), "jso,js"))); 103 options.push_back(linked_ptr<AcceptOption>( 104 BuildAcceptOption(std::string(), std::string(), "cpp,cc"))); 105 acceptsAllTypes = false; 106 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 107 base::FilePath::StringType(), &options, &acceptsAllTypes); 108 ASSERT_EQ(file_type_info.extensions.size(), options.size()); 109 110 expectedTypes.clear(); 111 expectedTypes.push_back(ToStringType("js")); 112 expectedTypes.push_back(ToStringType("jso")); 113 CheckExtensions(expectedTypes, file_type_info.extensions[0]); 114 115 expectedTypes.clear(); 116 expectedTypes.push_back(ToStringType("cc")); 117 expectedTypes.push_back(ToStringType("cpp")); 118 CheckExtensions(expectedTypes, file_type_info.extensions[1]); 119 120 // Test accept type that causes description override. 121 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 122 options.clear(); 123 options.push_back(linked_ptr<AcceptOption>( 124 BuildAcceptOption(std::string(), "image/*", "html"))); 125 acceptsAllTypes = false; 126 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 127 base::FilePath::StringType(), &options, &acceptsAllTypes); 128 ASSERT_EQ(file_type_info.extension_description_overrides.size(), (size_t) 1); 129 EXPECT_FALSE(file_type_info.extension_description_overrides[0].empty()) << 130 "Accept type \"image/*\" must generate description override"; 131 132 // Test multiple accept types that cause description override causes us to 133 // still present the default. 134 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 135 options.clear(); 136 options.push_back(linked_ptr<AcceptOption>(BuildAcceptOption( 137 std::string(), "image/*,audio/*,video/*", std::string()))); 138 acceptsAllTypes = false; 139 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 140 base::FilePath::StringType(), &options, &acceptsAllTypes); 141 ASSERT_EQ(file_type_info.extension_description_overrides.size(), (size_t) 1); 142 EXPECT_TRUE(file_type_info.extension_description_overrides[0].empty()); 143 144 // Test explicit description override. 145 file_type_info = ui::SelectFileDialog::FileTypeInfo(); 146 options.clear(); 147 options.push_back(linked_ptr<AcceptOption>( 148 BuildAcceptOption("File Types 101", "image/jpeg", std::string()))); 149 acceptsAllTypes = false; 150 FileSystemChooseEntryFunction::BuildFileTypeInfo(&file_type_info, 151 base::FilePath::StringType(), &options, &acceptsAllTypes); 152 EXPECT_EQ(file_type_info.extension_description_overrides[0], 153 UTF8ToUTF16("File Types 101")); 154} 155 156TEST_F(FileSystemApiUnitTest, FileSystemChooseEntryFunctionSuggestionTest) { 157 std::string opt_name; 158 base::FilePath suggested_name; 159 base::FilePath::StringType suggested_extension; 160 161 opt_name = std::string("normal_path.txt"); 162 FileSystemChooseEntryFunction::BuildSuggestion(&opt_name, &suggested_name, 163 &suggested_extension); 164 EXPECT_FALSE(suggested_name.IsAbsolute()); 165 EXPECT_EQ(suggested_name.MaybeAsASCII(), "normal_path.txt"); 166 EXPECT_EQ(suggested_extension, ToStringType("txt")); 167 168 // We should provide just the basename, i.e., "path". 169 opt_name = std::string("/a/bad/path"); 170 FileSystemChooseEntryFunction::BuildSuggestion(&opt_name, &suggested_name, 171 &suggested_extension); 172 EXPECT_FALSE(suggested_name.IsAbsolute()); 173 EXPECT_EQ(suggested_name.MaybeAsASCII(), "path"); 174 EXPECT_TRUE(suggested_extension.empty()); 175 176#if !defined(OS_WIN) 177 // TODO(thorogood): Fix this test on Windows. 178 // Filter out absolute paths with no basename. 179 opt_name = std::string("/"); 180 FileSystemChooseEntryFunction::BuildSuggestion(&opt_name, &suggested_name, 181 &suggested_extension); 182 EXPECT_FALSE(suggested_name.IsAbsolute()); 183 EXPECT_TRUE(suggested_name.MaybeAsASCII().empty()); 184 EXPECT_TRUE(suggested_extension.empty()); 185#endif 186} 187