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