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