Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1913)

Side by Side Diff: chrome/common/extensions/manifest_handler_unittest.cc

Issue 12091115: Allow manifest handlers to declare keys they depend on that must be parsed before them. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
(Empty)
1 // Copyright (c) 2013 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 <string>
6 #include <vector>
7
8 #include "base/file_path.h"
9 #include "base/stl_util.h"
10 #include "base/utf_string_conversions.h"
11 #include "chrome/common/extensions/extension.h"
12 #include "chrome/common/extensions/extension_builder.h"
13 #include "chrome/common/extensions/manifest_handler.h"
14 #include "chrome/common/extensions/value_builder.h"
15 #include "testing/gtest/include/gtest/gtest.h"
16
17 namespace extensions {
18
19 class ManifestHandlerTest : public testing::Test {
20 public:
21 class ParsingWatcher {
22 public:
23 // Called when a manifest handler parses.
24 void Record(std::string name) {
25 parsed_names_.push_back(name);
26 }
27
28 const std::vector<std::string>& parsed_names() {
29 return parsed_names_;
30 }
31
32 // Returns true if |name_before| was parsed before |name_after|.
33 bool ParsedBefore(std::string name_before, std::string name_after) {
34 size_t i_before = parsed_names_.size();
35 size_t i_after = 0;
36 for (size_t i = 0; i < parsed_names_.size(); ++i) {
37 if (parsed_names_[i] == name_before)
38 i_before = i;
39 if (parsed_names_[i] == name_after)
40 i_after = i;
41 }
42 if (i_before < i_after)
43 return true;
44 return false;
45 }
46
47 private:
48 // The order of manifest handlers that we watched parsing.
49 std::vector<std::string> parsed_names_;
50 };
51
52 class TestManifestHandler : public ManifestHandler {
53 public:
54 TestManifestHandler(const std::string& name,
55 const std::vector<std::string> prereqs,
56 ParsingWatcher* watcher)
57 : name_(name), prereqs_(prereqs), watcher_(watcher) {
58 }
59
60 virtual bool Parse(Extension* extension, string16* error) OVERRIDE {
61 watcher_->Record(name_);
62 return true;
63 }
64
65 virtual const std::vector<std::string>& PrerequisiteKeys() OVERRIDE {
66 return prereqs_;
67 }
68
69 std::string name_;
70 std::vector<std::string> prereqs_;
71 ParsingWatcher* watcher_;
72 };
73
74 class FailingTestManifestHandler : public TestManifestHandler {
75 public:
76 FailingTestManifestHandler(const std::string& name,
77 const std::vector<std::string> prereqs,
78 ParsingWatcher* watcher)
79 : TestManifestHandler(name, prereqs, watcher) {
80 }
81 virtual bool Parse(Extension* extension, string16* error) OVERRIDE {
82 *error = ASCIIToUTF16(name_);
83 return false;
84 }
85 };
86
87 class AlwaysParseTestManifestHandler : public TestManifestHandler {
88 public:
89 AlwaysParseTestManifestHandler(const std::string& name,
90 const std::vector<std::string> prereqs,
91 ParsingWatcher* watcher)
92 : TestManifestHandler(name, prereqs, watcher) {
93 }
94
95 virtual bool AlwaysParseForType(Manifest::Type type) OVERRIDE {
96 return true;
97 }
98 };
99
100 protected:
101 virtual void SetUp() OVERRIDE {
102 ManifestHandler::ClearRegistryForTesting();
103 }
104 };
105
106 TEST_F(ManifestHandlerTest, DependentHandlers) {
107 ParsingWatcher watcher;
108 std::vector<std::string> prereqs;
109 ManifestHandler::Register(
110 "a", make_linked_ptr(new TestManifestHandler("A", prereqs, &watcher)));
111 ManifestHandler::Register(
112 "b", make_linked_ptr(new TestManifestHandler("B", prereqs, &watcher)));
113 ManifestHandler::Register(
114 "j", make_linked_ptr(new TestManifestHandler("J", prereqs, &watcher)));
115 ManifestHandler::Register(
116 "k", make_linked_ptr(
117 new AlwaysParseTestManifestHandler("K", prereqs, &watcher)));
118 prereqs.push_back("c.d");
119 linked_ptr<TestManifestHandler> handler_c2(
120 new TestManifestHandler("C.EZ", prereqs, &watcher));
121 ManifestHandler::Register("c.e", handler_c2);
122 ManifestHandler::Register("c.z", handler_c2);
123 prereqs.clear();
124 prereqs.push_back("b");
125 prereqs.push_back("k");
126 prereqs.push_back("w");
127 ManifestHandler::Register(
128 "c.d", make_linked_ptr(new TestManifestHandler(
129 "C.D", prereqs, &watcher)));
130
131 scoped_refptr<Extension> extension = ExtensionBuilder()
132 .SetManifest(DictionaryBuilder()
133 .Set("name", "no name")
134 .Set("version", "0")
135 .Set("manifest_version", 2)
136 .Set("a", 1)
137 .Set("b", 2)
138 .Set("c", DictionaryBuilder()
139 .Set("d", 3)
140 .Set("e", 4)
141 .Set("f", 5))
142 .Set("g", 6))
143 .Build();
144
145 // A, B, C.EZ, C.D, K
146 EXPECT_EQ(5u, watcher.parsed_names().size());
147 EXPECT_TRUE(watcher.ParsedBefore("B", "C.D"));
148 EXPECT_TRUE(watcher.ParsedBefore("K", "C.D"));
149 EXPECT_TRUE(watcher.ParsedBefore("C.D", "C.EZ"));
150 }
151
152 TEST_F(ManifestHandlerTest, FailingHandlers) {
153 // Can't use ExtensionBuilder, because this extension will fail to
154 // be parsed.
155 scoped_ptr<base::DictionaryValue> manifest_a(
156 DictionaryBuilder()
157 .Set("name", "no name")
158 .Set("version", "0")
159 .Set("manifest_version", 2)
160 .Set("a", 1)
161 .Build());
162
163 // Succeeds when "a" is not recognized.
164 std::string error;
165 scoped_refptr<Extension> extension = Extension::Create(
166 FilePath(),
167 Manifest::INVALID_LOCATION,
168 *manifest_a,
169 Extension::NO_FLAGS,
170 &error);
171 EXPECT_TRUE(extension);
172
173 // Register a handler for "a" that fails.
174 ParsingWatcher watcher;
175 ManifestHandler::Register(
176 "a", make_linked_ptr(new FailingTestManifestHandler(
177 "A", std::vector<std::string>(), &watcher)));
178
179 extension = Extension::Create(
180 FilePath(),
181 Manifest::INVALID_LOCATION,
182 *manifest_a,
183 Extension::NO_FLAGS,
184 &error);
185 EXPECT_FALSE(extension);
186 EXPECT_EQ("A", error);
187 }
188
189 TEST_F(ManifestHandlerTest, CircularDependencies) {
190 ParsingWatcher watcher;
191 std::vector<std::string> prereqs;
192 prereqs.push_back("b");
193 prereqs.push_back("d");
194 ManifestHandler::Register(
195 "a", make_linked_ptr(new TestManifestHandler("A", prereqs, &watcher)));
196 prereqs.clear();
197 prereqs.push_back("a");
198 linked_ptr<TestManifestHandler> handler_bc(
199 new TestManifestHandler("BC", prereqs, &watcher));
200 ManifestHandler::Register("b", handler_bc);
201 ManifestHandler::Register("c", handler_bc);
202 prereqs.clear();
203 ManifestHandler::Register(
204 "d", make_linked_ptr(new TestManifestHandler("D", prereqs, &watcher)));
205
206 scoped_refptr<Extension> extension = ExtensionBuilder()
207 .SetManifest(DictionaryBuilder()
208 .Set("name", "no name")
209 .Set("version", "0")
210 .Set("manifest_version", 2)
211 .Set("a", 1)
212 .Set("c", 3)
213 .Set("d", 4))
214 .Build();
215 EXPECT_EQ(1u, watcher.parsed_names().size());
216 EXPECT_EQ("D", watcher.parsed_names()[0]);
217 }
218
219 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698