manifest_test.cc 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333
  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. #include "extensions/common/manifest_test.h"
  5. #include <utility>
  6. #include "base/files/file_path.h"
  7. #include "base/files/file_util.h"
  8. #include "base/json/json_file_value_serializer.h"
  9. #include "base/path_service.h"
  10. #include "base/strings/pattern.h"
  11. #include "base/strings/string_piece.h"
  12. #include "base/strings/string_util.h"
  13. #include "base/strings/stringprintf.h"
  14. #include "base/strings/utf_string_conversions.h"
  15. #include "base/values.h"
  16. #include "extensions/common/extension_l10n_util.h"
  17. #include "extensions/common/extension_paths.h"
  18. #include "extensions/common/manifest_constants.h"
  19. #include "testing/gmock/include/gmock/gmock.h"
  20. #include "ui/base/l10n/l10n_util.h"
  21. using extensions::mojom::ManifestLocation;
  22. namespace extensions {
  23. namespace {
  24. std::string GetNameFromManifest(const base::Value& manifest) {
  25. if (!manifest.is_dict())
  26. return std::string();
  27. const std::string* name = manifest.FindStringKey(manifest_keys::kName);
  28. return name ? *name : std::string();
  29. }
  30. // |manifest_path| is an absolute path to a manifest file.
  31. base::Value LoadManifestFile(const base::FilePath& manifest_path,
  32. std::string* error) {
  33. base::FilePath extension_path = manifest_path.DirName();
  34. EXPECT_TRUE(base::PathExists(manifest_path)) <<
  35. "Couldn't find " << manifest_path.value();
  36. JSONFileValueDeserializer deserializer(manifest_path);
  37. std::unique_ptr<base::Value> manifest =
  38. deserializer.Deserialize(nullptr, error);
  39. if (!manifest || !manifest->is_dict())
  40. return base::Value();
  41. // Most unit tests don't need localization, and they'll fail if we try to
  42. // localize them, since their manifests don't have a default_locale key.
  43. // Only localize manifests that indicate they want to be localized.
  44. // Calling LocalizeExtension at this point mirrors file_util::LoadExtension.
  45. if (manifest_path.value().find(FILE_PATH_LITERAL("localized")) !=
  46. std::string::npos) {
  47. base::DictionaryValue* manifest_dictionary = nullptr;
  48. manifest->GetAsDictionary(&manifest_dictionary);
  49. extension_l10n_util::LocalizeExtension(
  50. extension_path, manifest_dictionary,
  51. extension_l10n_util::GzippedMessagesPermission::kDisallow, error);
  52. }
  53. return base::Value(std::move(*manifest));
  54. }
  55. } // namespace
  56. ManifestTest::ManifestTest()
  57. : enable_apps_(true) {
  58. }
  59. ManifestTest::~ManifestTest() {
  60. }
  61. // Helper class that simplifies creating methods that take either a filename
  62. // to a manifest or the manifest itself.
  63. ManifestTest::ManifestData::ManifestData(base::StringPiece name)
  64. : name_(name) {}
  65. ManifestTest::ManifestData::ManifestData(base::Value manifest,
  66. base::StringPiece name)
  67. : name_(name), manifest_(std::move(manifest)) {
  68. CHECK(manifest_.is_dict()) << "Manifest must be a dictionary. " << name_;
  69. }
  70. ManifestTest::ManifestData::ManifestData(base::Value manifest)
  71. : name_(GetNameFromManifest(manifest)), manifest_(std::move(manifest)) {
  72. CHECK(manifest_.is_dict()) << "Manifest must be a dictionary.";
  73. CHECK(!name_.empty()) << R"("name" must be specified in the manifest.)";
  74. }
  75. ManifestTest::ManifestData::ManifestData(ManifestData&& other) = default;
  76. ManifestTest::ManifestData::~ManifestData() = default;
  77. const base::Value& ManifestTest::ManifestData::GetManifest(
  78. const base::FilePath& test_data_dir,
  79. std::string* error) const {
  80. if (manifest_.is_none()) {
  81. base::FilePath manifest_path = test_data_dir.AppendASCII(name_);
  82. manifest_ = LoadManifestFile(manifest_path, error);
  83. }
  84. return manifest_;
  85. }
  86. std::string ManifestTest::GetTestExtensionID() const {
  87. return std::string();
  88. }
  89. base::FilePath ManifestTest::GetTestDataDir() {
  90. base::FilePath path;
  91. base::PathService::Get(DIR_TEST_DATA, &path);
  92. return path.AppendASCII("manifest_tests");
  93. }
  94. base::Value ManifestTest::LoadManifest(char const* manifest_name,
  95. std::string* error) {
  96. base::FilePath manifest_path = GetTestDataDir().AppendASCII(manifest_name);
  97. return LoadManifestFile(manifest_path, error);
  98. }
  99. scoped_refptr<Extension> ManifestTest::LoadExtension(
  100. const ManifestData& manifest,
  101. std::string* error,
  102. ManifestLocation location,
  103. int flags) {
  104. base::FilePath test_data_dir = GetTestDataDir();
  105. const base::Value& value = manifest.GetManifest(test_data_dir, error);
  106. if (value.is_none())
  107. return nullptr;
  108. DCHECK(value.is_dict());
  109. const base::DictionaryValue* dictionary_manifest = nullptr;
  110. value.GetAsDictionary(&dictionary_manifest);
  111. return Extension::Create(test_data_dir.DirName(), location,
  112. *dictionary_manifest, flags, GetTestExtensionID(),
  113. error);
  114. }
  115. scoped_refptr<Extension> ManifestTest::LoadAndExpectSuccess(
  116. const ManifestData& manifest,
  117. ManifestLocation location,
  118. int flags) {
  119. std::string error;
  120. scoped_refptr<Extension> extension =
  121. LoadExtension(manifest, &error, location, flags);
  122. EXPECT_TRUE(extension.get()) << manifest.name();
  123. EXPECT_EQ(std::string(), error) << manifest.name();
  124. return extension;
  125. }
  126. scoped_refptr<Extension> ManifestTest::LoadAndExpectSuccess(
  127. char const* manifest_name,
  128. ManifestLocation location,
  129. int flags) {
  130. return LoadAndExpectSuccess(ManifestData(manifest_name), location, flags);
  131. }
  132. scoped_refptr<Extension> ManifestTest::LoadAndExpectWarning(
  133. const ManifestData& manifest,
  134. const std::string& expected_warning,
  135. ManifestLocation location,
  136. int flags) {
  137. std::string error;
  138. scoped_refptr<Extension> extension =
  139. LoadExtension(manifest, &error, location, flags);
  140. EXPECT_TRUE(extension.get()) << manifest.name();
  141. EXPECT_EQ(std::string(), error) << manifest.name();
  142. EXPECT_EQ(1u, extension->install_warnings().size());
  143. if (extension->install_warnings().size() == 1)
  144. EXPECT_EQ(expected_warning, extension->install_warnings()[0].message);
  145. return extension;
  146. }
  147. scoped_refptr<Extension> ManifestTest::LoadAndExpectWarning(
  148. char const* manifest_name,
  149. const std::string& expected_warning,
  150. ManifestLocation location,
  151. int flags) {
  152. return LoadAndExpectWarning(
  153. ManifestData(manifest_name), expected_warning, location, flags);
  154. }
  155. scoped_refptr<Extension> ManifestTest::LoadAndExpectWarnings(
  156. char const* manifest_name,
  157. const std::vector<std::string>& expected_warnings,
  158. ManifestLocation location,
  159. int flags) {
  160. std::string error;
  161. scoped_refptr<Extension> extension =
  162. LoadExtension(ManifestData(manifest_name), &error, location, flags);
  163. EXPECT_TRUE(extension.get()) << manifest_name;
  164. EXPECT_EQ(std::string(), error) << manifest_name;
  165. std::vector<std::string> warning_messages;
  166. warning_messages.reserve(extension->install_warnings().size());
  167. for (const auto& warning : extension->install_warnings()) {
  168. warning_messages.push_back(warning.message);
  169. }
  170. EXPECT_THAT(warning_messages,
  171. testing::UnorderedElementsAreArray(expected_warnings));
  172. return extension;
  173. }
  174. void ManifestTest::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(base::MatchPattern(error, expected_error))
  183. << name << " expected '" << expected_error << "' but got '" << error
  184. << "'";
  185. }
  186. void ManifestTest::LoadAndExpectError(const ManifestData& manifest,
  187. const std::string& expected_error,
  188. ManifestLocation location,
  189. int flags) {
  190. std::string error;
  191. scoped_refptr<Extension> extension(
  192. LoadExtension(manifest, &error, location, flags));
  193. VerifyExpectedError(extension.get(), manifest.name(), error,
  194. expected_error);
  195. }
  196. void ManifestTest::LoadAndExpectError(const ManifestData& manifest,
  197. const std::u16string& expected_error,
  198. ManifestLocation location,
  199. int flags) {
  200. return LoadAndExpectError(manifest, base::UTF16ToUTF8(expected_error),
  201. location, flags);
  202. }
  203. void ManifestTest::LoadAndExpectError(char const* manifest_name,
  204. const std::string& expected_error,
  205. ManifestLocation location,
  206. int flags) {
  207. return LoadAndExpectError(
  208. ManifestData(manifest_name), expected_error, location, flags);
  209. }
  210. void ManifestTest::LoadAndExpectError(char const* manifest_name,
  211. const std::u16string& expected_error,
  212. ManifestLocation location,
  213. int flags) {
  214. return LoadAndExpectError(ManifestData(manifest_name),
  215. base::UTF16ToUTF8(expected_error), location, flags);
  216. }
  217. void ManifestTest::AddPattern(extensions::URLPatternSet* extent,
  218. const std::string& pattern) {
  219. int schemes = URLPattern::SCHEME_ALL;
  220. extent->AddPattern(URLPattern(schemes, pattern));
  221. }
  222. ManifestTest::Testcase::Testcase(const std::string& manifest_filename,
  223. const std::string& expected_error,
  224. ManifestLocation location,
  225. int flags)
  226. : manifest_filename_(manifest_filename),
  227. expected_error_(expected_error),
  228. location_(location),
  229. flags_(flags) {}
  230. ManifestTest::Testcase::Testcase(const std::string& manifest_filename,
  231. const std::u16string& expected_error,
  232. ManifestLocation location,
  233. int flags)
  234. : Testcase(manifest_filename,
  235. base::UTF16ToUTF8(expected_error),
  236. location,
  237. flags) {}
  238. ManifestTest::Testcase::Testcase(const std::string& manifest_filename,
  239. const std::string& expected_error)
  240. : manifest_filename_(manifest_filename),
  241. expected_error_(expected_error),
  242. location_(ManifestLocation::kInternal),
  243. flags_(Extension::NO_FLAGS) {}
  244. ManifestTest::Testcase::Testcase(const std::string& manifest_filename,
  245. const std::u16string& expected_error)
  246. : Testcase(manifest_filename, base::UTF16ToUTF8(expected_error)) {}
  247. ManifestTest::Testcase::Testcase(const std::string& manifest_filename)
  248. : manifest_filename_(manifest_filename),
  249. location_(ManifestLocation::kInternal),
  250. flags_(Extension::NO_FLAGS) {}
  251. ManifestTest::Testcase::Testcase(const std::string& manifest_filename,
  252. ManifestLocation location,
  253. int flags)
  254. : manifest_filename_(manifest_filename),
  255. location_(location),
  256. flags_(flags) {}
  257. void ManifestTest::RunTestcases(const Testcase* testcases,
  258. size_t num_testcases,
  259. ExpectType type) {
  260. for (size_t i = 0; i < num_testcases; ++i)
  261. RunTestcase(testcases[i], type);
  262. }
  263. void ManifestTest::RunTestcase(const Testcase& testcase,
  264. ExpectType type) {
  265. SCOPED_TRACE(base::StringPrintf("Testing file '%s'",
  266. testcase.manifest_filename_.c_str()));
  267. switch (type) {
  268. case EXPECT_TYPE_ERROR:
  269. LoadAndExpectError(testcase.manifest_filename_.c_str(),
  270. testcase.expected_error_,
  271. testcase.location_,
  272. testcase.flags_);
  273. break;
  274. case EXPECT_TYPE_WARNING:
  275. LoadAndExpectWarning(testcase.manifest_filename_.c_str(),
  276. testcase.expected_error_,
  277. testcase.location_,
  278. testcase.flags_);
  279. break;
  280. case EXPECT_TYPE_SUCCESS:
  281. LoadAndExpectSuccess(testcase.manifest_filename_.c_str(),
  282. testcase.location_,
  283. testcase.flags_);
  284. break;
  285. }
  286. }
  287. } // namespace extensions