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 "chrome/common/extensions/manifest_tests/extension_manifest_test.h" 6 7 #include "base/file_util.h" 8 #include "base/files/file_path.h" 9 #include "base/json/json_file_value_serializer.h" 10 #include "base/path_service.h" 11 #include "base/values.h" 12 #include "chrome/common/chrome_paths.h" 13 #include "chrome/common/extensions/extension_l10n_util.h" 14 #include "ui/base/l10n/l10n_util.h" 15 16 using extensions::Extension; 17 18 namespace { 19 20 // If filename is a relative path, LoadManifestFile will treat it relative to 21 // the appropriate test directory. 22 base::DictionaryValue* LoadManifestFile(const base::FilePath& filename_path, 23 std::string* error) { 24 base::FilePath extension_path; 25 base::FilePath manifest_path; 26 27 PathService::Get(chrome::DIR_TEST_DATA, &manifest_path); 28 manifest_path = manifest_path.Append(filename_path); 29 extension_path = manifest_path.DirName(); 30 31 EXPECT_TRUE(base::PathExists(manifest_path)) << 32 "Couldn't find " << manifest_path.value(); 33 34 JSONFileValueSerializer serializer(manifest_path); 35 base::DictionaryValue* manifest = 36 static_cast<base::DictionaryValue*>(serializer.Deserialize(NULL, error)); 37 38 // Most unit tests don't need localization, and they'll fail if we try to 39 // localize them, since their manifests don't have a default_locale key. 40 // Only localize manifests that indicate they want to be localized. 41 // Calling LocalizeExtension at this point mirrors 42 // extension_file_util::LoadExtension. 43 if (manifest && 44 filename_path.value().find(FILE_PATH_LITERAL("localized")) != 45 std::string::npos) 46 extension_l10n_util::LocalizeExtension(extension_path, manifest, error); 47 48 return manifest; 49 } 50 51 } // namespace 52 53 ExtensionManifestTest::ExtensionManifestTest() 54 : enable_apps_(true), 55 // UNKNOWN == trunk. 56 current_channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {} 57 58 // Helper class that simplifies creating methods that take either a filename 59 // to a manifest or the manifest itself. 60 ExtensionManifestTest::Manifest::Manifest(const char* name) 61 : name_(name), manifest_(NULL) { 62 } 63 64 ExtensionManifestTest::Manifest::Manifest(base::DictionaryValue* manifest, 65 const char* name) 66 : name_(name), manifest_(manifest) { 67 CHECK(manifest_) << "Manifest NULL"; 68 } 69 70 ExtensionManifestTest::Manifest::Manifest(const Manifest& m) { 71 NOTREACHED(); 72 } 73 74 ExtensionManifestTest::Manifest::~Manifest() { 75 } 76 77 base::DictionaryValue* ExtensionManifestTest::Manifest::GetManifest( 78 char const* test_data_dir, std::string* error) const { 79 if (manifest_) 80 return manifest_; 81 82 base::FilePath filename_path; 83 filename_path = filename_path.AppendASCII("extensions") 84 .AppendASCII(test_data_dir) 85 .AppendASCII(name_); 86 manifest_ = LoadManifestFile(filename_path, error); 87 manifest_holder_.reset(manifest_); 88 return manifest_; 89 } 90 91 char const* ExtensionManifestTest::test_data_dir() { 92 return "manifest_tests"; 93 } 94 95 scoped_ptr<base::DictionaryValue> ExtensionManifestTest::LoadManifest( 96 char const* manifest_name, std::string* error) { 97 base::FilePath filename_path; 98 filename_path = filename_path.AppendASCII("extensions") 99 .AppendASCII(test_data_dir()) 100 .AppendASCII(manifest_name); 101 return make_scoped_ptr(LoadManifestFile(filename_path, error)); 102 } 103 104 scoped_refptr<Extension> ExtensionManifestTest::LoadExtension( 105 const Manifest& manifest, 106 std::string* error, 107 extensions::Manifest::Location location, 108 int flags) { 109 base::DictionaryValue* value = manifest.GetManifest(test_data_dir(), error); 110 if (!value) 111 return NULL; 112 base::FilePath path; 113 PathService::Get(chrome::DIR_TEST_DATA, &path); 114 path = path.AppendASCII("extensions").AppendASCII(test_data_dir()); 115 return Extension::Create(path.DirName(), location, *value, flags, error); 116 } 117 118 scoped_refptr<Extension> ExtensionManifestTest::LoadAndExpectSuccess( 119 const Manifest& manifest, 120 extensions::Manifest::Location location, 121 int flags) { 122 std::string error; 123 scoped_refptr<Extension> extension = 124 LoadExtension(manifest, &error, location, flags); 125 EXPECT_TRUE(extension.get()) << manifest.name(); 126 EXPECT_EQ("", error) << manifest.name(); 127 return extension; 128 } 129 130 scoped_refptr<Extension> ExtensionManifestTest::LoadAndExpectSuccess( 131 char const* manifest_name, 132 extensions::Manifest::Location location, 133 int flags) { 134 return LoadAndExpectSuccess(Manifest(manifest_name), location, flags); 135 } 136 137 scoped_refptr<Extension> ExtensionManifestTest::LoadAndExpectWarning( 138 const Manifest& manifest, 139 const std::string& expected_warning, 140 extensions::Manifest::Location location, 141 int flags) { 142 std::string error; 143 scoped_refptr<Extension> extension = 144 LoadExtension(manifest, &error, location, flags); 145 EXPECT_TRUE(extension.get()) << manifest.name(); 146 EXPECT_EQ("", error) << manifest.name(); 147 EXPECT_EQ(1u, extension->install_warnings().size()); 148 EXPECT_EQ(expected_warning, extension->install_warnings()[0].message); 149 return extension; 150 } 151 152 scoped_refptr<Extension> ExtensionManifestTest::LoadAndExpectWarning( 153 char const* manifest_name, 154 const std::string& expected_warning, 155 extensions::Manifest::Location location, 156 int flags) { 157 return LoadAndExpectWarning( 158 Manifest(manifest_name), expected_warning, location, flags); 159 } 160 161 void ExtensionManifestTest::VerifyExpectedError( 162 Extension* extension, 163 const std::string& name, 164 const std::string& error, 165 const std::string& expected_error) { 166 EXPECT_FALSE(extension) << 167 "Expected failure loading extension '" << name << 168 "', but didn't get one."; 169 EXPECT_TRUE(MatchPattern(error, expected_error)) << name << 170 " expected '" << expected_error << "' but got '" << error << "'"; 171 } 172 173 void ExtensionManifestTest::LoadAndExpectError( 174 const Manifest& manifest, 175 const std::string& expected_error, 176 extensions::Manifest::Location location, 177 int flags) { 178 std::string error; 179 scoped_refptr<Extension> extension( 180 LoadExtension(manifest, &error, location, flags)); 181 VerifyExpectedError(extension.get(), manifest.name(), error, 182 expected_error); 183 } 184 185 void ExtensionManifestTest::LoadAndExpectError( 186 char const* manifest_name, 187 const std::string& expected_error, 188 extensions::Manifest::Location location, 189 int flags) { 190 return LoadAndExpectError( 191 Manifest(manifest_name), expected_error, location, flags); 192 } 193 194 void ExtensionManifestTest::AddPattern(extensions::URLPatternSet* extent, 195 const std::string& pattern) { 196 int schemes = URLPattern::SCHEME_ALL; 197 extent->AddPattern(URLPattern(schemes, pattern)); 198 } 199 200 ExtensionManifestTest::Testcase::Testcase( 201 std::string manifest_filename, 202 std::string expected_error, 203 extensions::Manifest::Location location, 204 int flags) 205 : manifest_filename_(manifest_filename), 206 expected_error_(expected_error), 207 location_(location), flags_(flags) { 208 } 209 210 ExtensionManifestTest::Testcase::Testcase(std::string manifest_filename, 211 std::string expected_error) 212 : manifest_filename_(manifest_filename), 213 expected_error_(expected_error), 214 location_(extensions::Manifest::INTERNAL), 215 flags_(Extension::NO_FLAGS) { 216 } 217 218 ExtensionManifestTest::Testcase::Testcase(std::string manifest_filename) 219 : manifest_filename_(manifest_filename), 220 location_(extensions::Manifest::INTERNAL), 221 flags_(Extension::NO_FLAGS) {} 222 223 ExtensionManifestTest::Testcase::Testcase( 224 std::string manifest_filename, 225 extensions::Manifest::Location location, 226 int flags) 227 : manifest_filename_(manifest_filename), 228 location_(location), 229 flags_(flags) {} 230 231 void ExtensionManifestTest::RunTestcases(const Testcase* testcases, 232 size_t num_testcases, 233 ExpectType type) { 234 for (size_t i = 0; i < num_testcases; ++i) 235 RunTestcase(testcases[i], type); 236 } 237 238 void ExtensionManifestTest::RunTestcase(const Testcase& testcase, 239 ExpectType type) { 240 switch (type) { 241 case EXPECT_TYPE_ERROR: 242 LoadAndExpectError(testcase.manifest_filename_.c_str(), 243 testcase.expected_error_, 244 testcase.location_, 245 testcase.flags_); 246 break; 247 case EXPECT_TYPE_WARNING: 248 LoadAndExpectWarning(testcase.manifest_filename_.c_str(), 249 testcase.expected_error_, 250 testcase.location_, 251 testcase.flags_); 252 break; 253 case EXPECT_TYPE_SUCCESS: 254 LoadAndExpectSuccess(testcase.manifest_filename_.c_str(), 255 testcase.location_, 256 testcase.flags_); 257 break; 258 } 259 } 260