OLD | NEW |
1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "extensions/common/features/simple_feature.h" | 5 #include "extensions/common/features/simple_feature.h" |
6 | 6 |
7 #include "chrome/common/extensions/features/chrome_channel_feature_filter.h" | 7 #include <string> |
8 #include "chrome/common/extensions/features/feature_channel.h" | 8 |
| 9 #include "base/values.h" |
| 10 #include "extensions/common/manifest.h" |
9 #include "extensions/common/value_builder.h" | 11 #include "extensions/common/value_builder.h" |
10 #include "testing/gtest/include/gtest/gtest.h" | 12 #include "testing/gtest/include/gtest/gtest.h" |
11 | 13 |
12 using chrome::VersionInfo; | |
13 using extensions::DictionaryBuilder; | |
14 using extensions::Extension; | |
15 using extensions::Feature; | |
16 using extensions::ListBuilder; | |
17 using extensions::Manifest; | |
18 using extensions::ScopedCurrentChannel; | |
19 using extensions::SimpleFeature; | |
20 | |
21 namespace extensions { | 14 namespace extensions { |
22 | 15 |
23 namespace { | 16 namespace { |
24 | 17 |
25 struct IsAvailableTestData { | 18 struct IsAvailableTestData { |
26 std::string extension_id; | 19 std::string extension_id; |
27 Manifest::Type extension_type; | 20 Manifest::Type extension_type; |
28 Manifest::Location location; | 21 Manifest::Location location; |
29 Feature::Platform platform; | 22 Feature::Platform platform; |
30 int manifest_version; | 23 int manifest_version; |
31 Feature::AvailabilityResult expected_result; | 24 Feature::AvailabilityResult expected_result; |
32 }; | 25 }; |
33 | 26 |
| 27 bool LocationIsAvailable(SimpleFeature::Location feature_location, |
| 28 Manifest::Location manifest_location) { |
| 29 SimpleFeature feature; |
| 30 feature.set_location(feature_location); |
| 31 Feature::AvailabilityResult availability_result = |
| 32 feature.IsAvailableToManifest(std::string(), |
| 33 Manifest::TYPE_UNKNOWN, |
| 34 manifest_location, |
| 35 -1, |
| 36 Feature::UNSPECIFIED_PLATFORM).result(); |
| 37 return availability_result == Feature::IS_AVAILABLE; |
| 38 } |
| 39 |
34 } // namespace | 40 } // namespace |
35 | 41 |
36 class ExtensionSimpleFeatureTest : public testing::Test { | 42 TEST(SimpleFeatureTest, IsAvailableNullCase) { |
37 protected: | |
38 ExtensionSimpleFeatureTest() | |
39 : current_channel_(VersionInfo::CHANNEL_UNKNOWN) {} | |
40 virtual ~ExtensionSimpleFeatureTest() {} | |
41 | |
42 bool LocationIsAvailable(SimpleFeature::Location feature_location, | |
43 Manifest::Location manifest_location) { | |
44 SimpleFeature feature; | |
45 feature.set_location(feature_location); | |
46 Feature::AvailabilityResult availability_result = | |
47 feature.IsAvailableToManifest(std::string(), | |
48 Manifest::TYPE_UNKNOWN, | |
49 manifest_location, | |
50 -1, | |
51 Feature::UNSPECIFIED_PLATFORM).result(); | |
52 return availability_result == Feature::IS_AVAILABLE; | |
53 } | |
54 | |
55 private: | |
56 ScopedCurrentChannel current_channel_; | |
57 }; | |
58 | |
59 TEST_F(ExtensionSimpleFeatureTest, IsAvailableNullCase) { | |
60 const IsAvailableTestData tests[] = { | 43 const IsAvailableTestData tests[] = { |
61 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, | 44 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, |
62 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, | 45 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, |
63 {"random-extension", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, | 46 {"random-extension", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, |
64 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, | 47 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, |
65 {"", Manifest::TYPE_LEGACY_PACKAGED_APP, Manifest::INVALID_LOCATION, | 48 {"", Manifest::TYPE_LEGACY_PACKAGED_APP, Manifest::INVALID_LOCATION, |
66 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, | 49 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, |
67 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, | 50 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, |
68 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, | 51 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, |
69 {"", Manifest::TYPE_UNKNOWN, Manifest::COMPONENT, | 52 {"", Manifest::TYPE_UNKNOWN, Manifest::COMPONENT, |
70 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, | 53 Feature::UNSPECIFIED_PLATFORM, -1, Feature::IS_AVAILABLE}, |
71 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, | 54 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, |
72 Feature::CHROMEOS_PLATFORM, -1, Feature::IS_AVAILABLE}, | 55 Feature::CHROMEOS_PLATFORM, -1, Feature::IS_AVAILABLE}, |
73 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, | 56 {"", Manifest::TYPE_UNKNOWN, Manifest::INVALID_LOCATION, |
74 Feature::UNSPECIFIED_PLATFORM, 25, Feature::IS_AVAILABLE}}; | 57 Feature::UNSPECIFIED_PLATFORM, 25, Feature::IS_AVAILABLE}}; |
75 | 58 |
76 SimpleFeature feature; | 59 SimpleFeature feature; |
77 for (size_t i = 0; i < arraysize(tests); ++i) { | 60 for (size_t i = 0; i < arraysize(tests); ++i) { |
78 const IsAvailableTestData& test = tests[i]; | 61 const IsAvailableTestData& test = tests[i]; |
79 EXPECT_EQ(test.expected_result, | 62 EXPECT_EQ(test.expected_result, |
80 feature.IsAvailableToManifest(test.extension_id, | 63 feature.IsAvailableToManifest(test.extension_id, |
81 test.extension_type, | 64 test.extension_type, |
82 test.location, | 65 test.location, |
83 test.manifest_version, | 66 test.manifest_version, |
84 test.platform).result()); | 67 test.platform).result()); |
85 } | 68 } |
86 } | 69 } |
87 | 70 |
88 TEST_F(ExtensionSimpleFeatureTest, Whitelist) { | 71 TEST(SimpleFeatureTest, Whitelist) { |
89 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); | 72 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); |
90 const std::string kIdBar("barabbbbccccddddeeeeffffgggghhhh"); | 73 const std::string kIdBar("barabbbbccccddddeeeeffffgggghhhh"); |
91 const std::string kIdBaz("bazabbbbccccddddeeeeffffgggghhhh"); | 74 const std::string kIdBaz("bazabbbbccccddddeeeeffffgggghhhh"); |
92 SimpleFeature feature; | 75 SimpleFeature feature; |
93 feature.whitelist()->insert(kIdFoo); | 76 feature.whitelist()->insert(kIdFoo); |
94 feature.whitelist()->insert(kIdBar); | 77 feature.whitelist()->insert(kIdBar); |
95 | 78 |
96 EXPECT_EQ( | 79 EXPECT_EQ( |
97 Feature::IS_AVAILABLE, | 80 Feature::IS_AVAILABLE, |
98 feature.IsAvailableToManifest(kIdFoo, | 81 feature.IsAvailableToManifest(kIdFoo, |
(...skipping 27 matching lines...) Expand all Loading... |
126 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); | 109 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); |
127 EXPECT_EQ( | 110 EXPECT_EQ( |
128 Feature::NOT_FOUND_IN_WHITELIST, | 111 Feature::NOT_FOUND_IN_WHITELIST, |
129 feature.IsAvailableToManifest(kIdBaz, | 112 feature.IsAvailableToManifest(kIdBaz, |
130 Manifest::TYPE_LEGACY_PACKAGED_APP, | 113 Manifest::TYPE_LEGACY_PACKAGED_APP, |
131 Manifest::INVALID_LOCATION, | 114 Manifest::INVALID_LOCATION, |
132 -1, | 115 -1, |
133 Feature::UNSPECIFIED_PLATFORM).result()); | 116 Feature::UNSPECIFIED_PLATFORM).result()); |
134 } | 117 } |
135 | 118 |
136 TEST_F(ExtensionSimpleFeatureTest, HashedIdWhitelist) { | 119 TEST(SimpleFeatureTest, HashedIdWhitelist) { |
137 // echo -n "fooabbbbccccddddeeeeffffgggghhhh" | | 120 // echo -n "fooabbbbccccddddeeeeffffgggghhhh" | |
138 // sha1sum | tr '[:lower:]' '[:upper:]' | 121 // sha1sum | tr '[:lower:]' '[:upper:]' |
139 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); | 122 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); |
140 const std::string kIdFooHashed("55BC7228A0D502A2A48C9BB16B07062A01E62897"); | 123 const std::string kIdFooHashed("55BC7228A0D502A2A48C9BB16B07062A01E62897"); |
141 SimpleFeature feature; | 124 SimpleFeature feature; |
142 | 125 |
143 feature.whitelist()->insert(kIdFooHashed); | 126 feature.whitelist()->insert(kIdFooHashed); |
144 | 127 |
145 EXPECT_EQ( | 128 EXPECT_EQ( |
146 Feature::IS_AVAILABLE, | 129 Feature::IS_AVAILABLE, |
(...skipping 18 matching lines...) Expand all Loading... |
165 Feature::UNSPECIFIED_PLATFORM).result()); | 148 Feature::UNSPECIFIED_PLATFORM).result()); |
166 EXPECT_EQ( | 149 EXPECT_EQ( |
167 Feature::NOT_FOUND_IN_WHITELIST, | 150 Feature::NOT_FOUND_IN_WHITELIST, |
168 feature.IsAvailableToManifest("tooshortforanextensionid", | 151 feature.IsAvailableToManifest("tooshortforanextensionid", |
169 Manifest::TYPE_UNKNOWN, | 152 Manifest::TYPE_UNKNOWN, |
170 Manifest::INVALID_LOCATION, | 153 Manifest::INVALID_LOCATION, |
171 -1, | 154 -1, |
172 Feature::UNSPECIFIED_PLATFORM).result()); | 155 Feature::UNSPECIFIED_PLATFORM).result()); |
173 } | 156 } |
174 | 157 |
175 TEST_F(ExtensionSimpleFeatureTest, Blacklist) { | 158 TEST(SimpleFeatureTest, Blacklist) { |
176 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); | 159 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); |
177 const std::string kIdBar("barabbbbccccddddeeeeffffgggghhhh"); | 160 const std::string kIdBar("barabbbbccccddddeeeeffffgggghhhh"); |
178 const std::string kIdBaz("bazabbbbccccddddeeeeffffgggghhhh"); | 161 const std::string kIdBaz("bazabbbbccccddddeeeeffffgggghhhh"); |
179 SimpleFeature feature; | 162 SimpleFeature feature; |
180 feature.blacklist()->insert(kIdFoo); | 163 feature.blacklist()->insert(kIdFoo); |
181 feature.blacklist()->insert(kIdBar); | 164 feature.blacklist()->insert(kIdBar); |
182 | 165 |
183 EXPECT_EQ( | 166 EXPECT_EQ( |
184 Feature::FOUND_IN_BLACKLIST, | 167 Feature::FOUND_IN_BLACKLIST, |
185 feature.IsAvailableToManifest(kIdFoo, | 168 feature.IsAvailableToManifest(kIdFoo, |
(...skipping 18 matching lines...) Expand all Loading... |
204 Feature::UNSPECIFIED_PLATFORM).result()); | 187 Feature::UNSPECIFIED_PLATFORM).result()); |
205 EXPECT_EQ( | 188 EXPECT_EQ( |
206 Feature::IS_AVAILABLE, | 189 Feature::IS_AVAILABLE, |
207 feature.IsAvailableToManifest(std::string(), | 190 feature.IsAvailableToManifest(std::string(), |
208 Manifest::TYPE_UNKNOWN, | 191 Manifest::TYPE_UNKNOWN, |
209 Manifest::INVALID_LOCATION, | 192 Manifest::INVALID_LOCATION, |
210 -1, | 193 -1, |
211 Feature::UNSPECIFIED_PLATFORM).result()); | 194 Feature::UNSPECIFIED_PLATFORM).result()); |
212 } | 195 } |
213 | 196 |
214 TEST_F(ExtensionSimpleFeatureTest, HashedIdBlacklist) { | 197 TEST(SimpleFeatureTest, HashedIdBlacklist) { |
215 // echo -n "fooabbbbccccddddeeeeffffgggghhhh" | | 198 // echo -n "fooabbbbccccddddeeeeffffgggghhhh" | |
216 // sha1sum | tr '[:lower:]' '[:upper:]' | 199 // sha1sum | tr '[:lower:]' '[:upper:]' |
217 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); | 200 const std::string kIdFoo("fooabbbbccccddddeeeeffffgggghhhh"); |
218 const std::string kIdFooHashed("55BC7228A0D502A2A48C9BB16B07062A01E62897"); | 201 const std::string kIdFooHashed("55BC7228A0D502A2A48C9BB16B07062A01E62897"); |
219 SimpleFeature feature; | 202 SimpleFeature feature; |
220 | 203 |
221 feature.blacklist()->insert(kIdFooHashed); | 204 feature.blacklist()->insert(kIdFooHashed); |
222 | 205 |
223 EXPECT_EQ( | 206 EXPECT_EQ( |
224 Feature::FOUND_IN_BLACKLIST, | 207 Feature::FOUND_IN_BLACKLIST, |
(...skipping 18 matching lines...) Expand all Loading... |
243 Feature::UNSPECIFIED_PLATFORM).result()); | 226 Feature::UNSPECIFIED_PLATFORM).result()); |
244 EXPECT_EQ( | 227 EXPECT_EQ( |
245 Feature::IS_AVAILABLE, | 228 Feature::IS_AVAILABLE, |
246 feature.IsAvailableToManifest("tooshortforanextensionid", | 229 feature.IsAvailableToManifest("tooshortforanextensionid", |
247 Manifest::TYPE_UNKNOWN, | 230 Manifest::TYPE_UNKNOWN, |
248 Manifest::INVALID_LOCATION, | 231 Manifest::INVALID_LOCATION, |
249 -1, | 232 -1, |
250 Feature::UNSPECIFIED_PLATFORM).result()); | 233 Feature::UNSPECIFIED_PLATFORM).result()); |
251 } | 234 } |
252 | 235 |
253 TEST_F(ExtensionSimpleFeatureTest, PackageType) { | 236 TEST(SimpleFeatureTest, PackageType) { |
254 SimpleFeature feature; | 237 SimpleFeature feature; |
255 feature.extension_types()->insert(Manifest::TYPE_EXTENSION); | 238 feature.extension_types()->insert(Manifest::TYPE_EXTENSION); |
256 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); | 239 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); |
257 | 240 |
258 EXPECT_EQ( | 241 EXPECT_EQ( |
259 Feature::IS_AVAILABLE, | 242 Feature::IS_AVAILABLE, |
260 feature.IsAvailableToManifest(std::string(), | 243 feature.IsAvailableToManifest(std::string(), |
261 Manifest::TYPE_EXTENSION, | 244 Manifest::TYPE_EXTENSION, |
262 Manifest::INVALID_LOCATION, | 245 Manifest::INVALID_LOCATION, |
263 -1, | 246 -1, |
(...skipping 15 matching lines...) Expand all Loading... |
279 Feature::UNSPECIFIED_PLATFORM).result()); | 262 Feature::UNSPECIFIED_PLATFORM).result()); |
280 EXPECT_EQ( | 263 EXPECT_EQ( |
281 Feature::INVALID_TYPE, | 264 Feature::INVALID_TYPE, |
282 feature.IsAvailableToManifest(std::string(), | 265 feature.IsAvailableToManifest(std::string(), |
283 Manifest::TYPE_THEME, | 266 Manifest::TYPE_THEME, |
284 Manifest::INVALID_LOCATION, | 267 Manifest::INVALID_LOCATION, |
285 -1, | 268 -1, |
286 Feature::UNSPECIFIED_PLATFORM).result()); | 269 Feature::UNSPECIFIED_PLATFORM).result()); |
287 } | 270 } |
288 | 271 |
289 TEST_F(ExtensionSimpleFeatureTest, Context) { | 272 TEST(SimpleFeatureTest, Context) { |
290 SimpleFeature feature; | 273 SimpleFeature feature; |
291 feature.set_name("somefeature"); | 274 feature.set_name("somefeature"); |
292 feature.contexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT); | 275 feature.contexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT); |
293 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); | 276 feature.extension_types()->insert(Manifest::TYPE_LEGACY_PACKAGED_APP); |
294 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); | 277 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); |
295 feature.set_min_manifest_version(21); | 278 feature.set_min_manifest_version(21); |
296 feature.set_max_manifest_version(25); | 279 feature.set_max_manifest_version(25); |
297 | 280 |
298 base::DictionaryValue manifest; | 281 base::DictionaryValue manifest; |
299 manifest.SetString("name", "test"); | 282 manifest.SetString("name", "test"); |
(...skipping 70 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
370 Feature::CHROMEOS_PLATFORM).result()); | 353 Feature::CHROMEOS_PLATFORM).result()); |
371 feature.set_min_manifest_version(21); | 354 feature.set_min_manifest_version(21); |
372 | 355 |
373 feature.set_max_manifest_version(18); | 356 feature.set_max_manifest_version(18); |
374 EXPECT_EQ(Feature::INVALID_MAX_MANIFEST_VERSION, feature.IsAvailableToContext( | 357 EXPECT_EQ(Feature::INVALID_MAX_MANIFEST_VERSION, feature.IsAvailableToContext( |
375 extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, | 358 extension.get(), Feature::BLESSED_EXTENSION_CONTEXT, |
376 Feature::CHROMEOS_PLATFORM).result()); | 359 Feature::CHROMEOS_PLATFORM).result()); |
377 feature.set_max_manifest_version(25); | 360 feature.set_max_manifest_version(25); |
378 } | 361 } |
379 | 362 |
380 TEST_F(ExtensionSimpleFeatureTest, Location) { | 363 TEST(SimpleFeatureTest, Location) { |
381 // Component extensions can access any location. | 364 // Component extensions can access any location. |
382 EXPECT_TRUE(LocationIsAvailable(SimpleFeature::COMPONENT_LOCATION, | 365 EXPECT_TRUE(LocationIsAvailable(SimpleFeature::COMPONENT_LOCATION, |
383 Manifest::COMPONENT)); | 366 Manifest::COMPONENT)); |
384 EXPECT_TRUE( | 367 EXPECT_TRUE( |
385 LocationIsAvailable(SimpleFeature::POLICY_LOCATION, Manifest::COMPONENT)); | 368 LocationIsAvailable(SimpleFeature::POLICY_LOCATION, Manifest::COMPONENT)); |
386 EXPECT_TRUE(LocationIsAvailable(SimpleFeature::UNSPECIFIED_LOCATION, | 369 EXPECT_TRUE(LocationIsAvailable(SimpleFeature::UNSPECIFIED_LOCATION, |
387 Manifest::COMPONENT)); | 370 Manifest::COMPONENT)); |
388 | 371 |
389 // Only component extensions can access the "component" location. | 372 // Only component extensions can access the "component" location. |
390 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::COMPONENT_LOCATION, | 373 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::COMPONENT_LOCATION, |
(...skipping 15 matching lines...) Expand all Loading... |
406 | 389 |
407 // Non-policy (except component) extensions cannot access policy. | 390 // Non-policy (except component) extensions cannot access policy. |
408 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::POLICY_LOCATION, | 391 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::POLICY_LOCATION, |
409 Manifest::INVALID_LOCATION)); | 392 Manifest::INVALID_LOCATION)); |
410 EXPECT_FALSE( | 393 EXPECT_FALSE( |
411 LocationIsAvailable(SimpleFeature::POLICY_LOCATION, Manifest::UNPACKED)); | 394 LocationIsAvailable(SimpleFeature::POLICY_LOCATION, Manifest::UNPACKED)); |
412 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::POLICY_LOCATION, | 395 EXPECT_FALSE(LocationIsAvailable(SimpleFeature::POLICY_LOCATION, |
413 Manifest::EXTERNAL_PREF_DOWNLOAD)); | 396 Manifest::EXTERNAL_PREF_DOWNLOAD)); |
414 } | 397 } |
415 | 398 |
416 TEST_F(ExtensionSimpleFeatureTest, Platform) { | 399 TEST(SimpleFeatureTest, Platform) { |
417 SimpleFeature feature; | 400 SimpleFeature feature; |
418 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); | 401 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); |
419 EXPECT_EQ(Feature::IS_AVAILABLE, | 402 EXPECT_EQ(Feature::IS_AVAILABLE, |
420 feature.IsAvailableToManifest(std::string(), | 403 feature.IsAvailableToManifest(std::string(), |
421 Manifest::TYPE_UNKNOWN, | 404 Manifest::TYPE_UNKNOWN, |
422 Manifest::INVALID_LOCATION, | 405 Manifest::INVALID_LOCATION, |
423 -1, | 406 -1, |
424 Feature::CHROMEOS_PLATFORM).result()); | 407 Feature::CHROMEOS_PLATFORM).result()); |
425 EXPECT_EQ( | 408 EXPECT_EQ( |
426 Feature::INVALID_PLATFORM, | 409 Feature::INVALID_PLATFORM, |
427 feature.IsAvailableToManifest(std::string(), | 410 feature.IsAvailableToManifest(std::string(), |
428 Manifest::TYPE_UNKNOWN, | 411 Manifest::TYPE_UNKNOWN, |
429 Manifest::INVALID_LOCATION, | 412 Manifest::INVALID_LOCATION, |
430 -1, | 413 -1, |
431 Feature::UNSPECIFIED_PLATFORM).result()); | 414 Feature::UNSPECIFIED_PLATFORM).result()); |
432 } | 415 } |
433 | 416 |
434 TEST_F(ExtensionSimpleFeatureTest, Version) { | 417 TEST(SimpleFeatureTest, ManifestVersion) { |
435 SimpleFeature feature; | 418 SimpleFeature feature; |
436 feature.set_min_manifest_version(5); | 419 feature.set_min_manifest_version(5); |
437 | 420 |
438 EXPECT_EQ( | 421 EXPECT_EQ( |
439 Feature::INVALID_MIN_MANIFEST_VERSION, | 422 Feature::INVALID_MIN_MANIFEST_VERSION, |
440 feature.IsAvailableToManifest(std::string(), | 423 feature.IsAvailableToManifest(std::string(), |
441 Manifest::TYPE_UNKNOWN, | 424 Manifest::TYPE_UNKNOWN, |
442 Manifest::INVALID_LOCATION, | 425 Manifest::INVALID_LOCATION, |
443 0, | 426 0, |
444 Feature::UNSPECIFIED_PLATFORM).result()); | 427 Feature::UNSPECIFIED_PLATFORM).result()); |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
483 Feature::UNSPECIFIED_PLATFORM).result()); | 466 Feature::UNSPECIFIED_PLATFORM).result()); |
484 EXPECT_EQ( | 467 EXPECT_EQ( |
485 Feature::IS_AVAILABLE, | 468 Feature::IS_AVAILABLE, |
486 feature.IsAvailableToManifest(std::string(), | 469 feature.IsAvailableToManifest(std::string(), |
487 Manifest::TYPE_UNKNOWN, | 470 Manifest::TYPE_UNKNOWN, |
488 Manifest::INVALID_LOCATION, | 471 Manifest::INVALID_LOCATION, |
489 7, | 472 7, |
490 Feature::UNSPECIFIED_PLATFORM).result()); | 473 Feature::UNSPECIFIED_PLATFORM).result()); |
491 } | 474 } |
492 | 475 |
493 TEST_F(ExtensionSimpleFeatureTest, ParseNull) { | 476 TEST(SimpleFeatureTest, ParseNull) { |
494 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 477 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
495 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 478 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
496 feature->Parse(value.get()); | 479 feature->Parse(value.get()); |
497 EXPECT_TRUE(feature->whitelist()->empty()); | 480 EXPECT_TRUE(feature->whitelist()->empty()); |
498 EXPECT_TRUE(feature->extension_types()->empty()); | 481 EXPECT_TRUE(feature->extension_types()->empty()); |
499 EXPECT_TRUE(feature->contexts()->empty()); | 482 EXPECT_TRUE(feature->contexts()->empty()); |
500 EXPECT_EQ(SimpleFeature::UNSPECIFIED_LOCATION, feature->location()); | 483 EXPECT_EQ(SimpleFeature::UNSPECIFIED_LOCATION, feature->location()); |
501 EXPECT_TRUE(feature->platforms()->empty()); | 484 EXPECT_TRUE(feature->platforms()->empty()); |
502 EXPECT_EQ(0, feature->min_manifest_version()); | 485 EXPECT_EQ(0, feature->min_manifest_version()); |
503 EXPECT_EQ(0, feature->max_manifest_version()); | 486 EXPECT_EQ(0, feature->max_manifest_version()); |
504 } | 487 } |
505 | 488 |
506 TEST_F(ExtensionSimpleFeatureTest, ParseWhitelist) { | 489 TEST(SimpleFeatureTest, ParseWhitelist) { |
507 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 490 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
508 base::ListValue* whitelist = new base::ListValue(); | 491 base::ListValue* whitelist = new base::ListValue(); |
509 whitelist->Append(new base::StringValue("foo")); | 492 whitelist->Append(new base::StringValue("foo")); |
510 whitelist->Append(new base::StringValue("bar")); | 493 whitelist->Append(new base::StringValue("bar")); |
511 value->Set("whitelist", whitelist); | 494 value->Set("whitelist", whitelist); |
512 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 495 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
513 feature->Parse(value.get()); | 496 feature->Parse(value.get()); |
514 EXPECT_EQ(2u, feature->whitelist()->size()); | 497 EXPECT_EQ(2u, feature->whitelist()->size()); |
515 EXPECT_TRUE(feature->whitelist()->count("foo")); | 498 EXPECT_TRUE(feature->whitelist()->count("foo")); |
516 EXPECT_TRUE(feature->whitelist()->count("bar")); | 499 EXPECT_TRUE(feature->whitelist()->count("bar")); |
517 } | 500 } |
518 | 501 |
519 TEST_F(ExtensionSimpleFeatureTest, ParsePackageTypes) { | 502 TEST(SimpleFeatureTest, ParsePackageTypes) { |
520 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 503 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
521 base::ListValue* extension_types = new base::ListValue(); | 504 base::ListValue* extension_types = new base::ListValue(); |
522 extension_types->Append(new base::StringValue("extension")); | 505 extension_types->Append(new base::StringValue("extension")); |
523 extension_types->Append(new base::StringValue("theme")); | 506 extension_types->Append(new base::StringValue("theme")); |
524 extension_types->Append(new base::StringValue("legacy_packaged_app")); | 507 extension_types->Append(new base::StringValue("legacy_packaged_app")); |
525 extension_types->Append(new base::StringValue("hosted_app")); | 508 extension_types->Append(new base::StringValue("hosted_app")); |
526 extension_types->Append(new base::StringValue("platform_app")); | 509 extension_types->Append(new base::StringValue("platform_app")); |
527 extension_types->Append(new base::StringValue("shared_module")); | 510 extension_types->Append(new base::StringValue("shared_module")); |
528 value->Set("extension_types", extension_types); | 511 value->Set("extension_types", extension_types); |
529 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 512 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
530 feature->Parse(value.get()); | 513 feature->Parse(value.get()); |
531 EXPECT_EQ(6u, feature->extension_types()->size()); | 514 EXPECT_EQ(6u, feature->extension_types()->size()); |
532 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_EXTENSION)); | 515 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_EXTENSION)); |
533 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_THEME)); | 516 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_THEME)); |
534 EXPECT_TRUE(feature->extension_types()->count( | 517 EXPECT_TRUE(feature->extension_types()->count( |
535 Manifest::TYPE_LEGACY_PACKAGED_APP)); | 518 Manifest::TYPE_LEGACY_PACKAGED_APP)); |
536 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_HOSTED_APP)); | 519 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_HOSTED_APP)); |
537 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP)); | 520 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_PLATFORM_APP)); |
538 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE)); | 521 EXPECT_TRUE(feature->extension_types()->count(Manifest::TYPE_SHARED_MODULE)); |
539 | 522 |
540 value->SetString("extension_types", "all"); | 523 value->SetString("extension_types", "all"); |
541 scoped_ptr<SimpleFeature> feature2(new SimpleFeature()); | 524 scoped_ptr<SimpleFeature> feature2(new SimpleFeature()); |
542 feature2->Parse(value.get()); | 525 feature2->Parse(value.get()); |
543 EXPECT_EQ(*(feature->extension_types()), *(feature2->extension_types())); | 526 EXPECT_EQ(*(feature->extension_types()), *(feature2->extension_types())); |
544 } | 527 } |
545 | 528 |
546 TEST_F(ExtensionSimpleFeatureTest, ParseContexts) { | 529 TEST(SimpleFeatureTest, ParseContexts) { |
547 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 530 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
548 base::ListValue* contexts = new base::ListValue(); | 531 base::ListValue* contexts = new base::ListValue(); |
549 contexts->Append(new base::StringValue("blessed_extension")); | 532 contexts->Append(new base::StringValue("blessed_extension")); |
550 contexts->Append(new base::StringValue("unblessed_extension")); | 533 contexts->Append(new base::StringValue("unblessed_extension")); |
551 contexts->Append(new base::StringValue("content_script")); | 534 contexts->Append(new base::StringValue("content_script")); |
552 contexts->Append(new base::StringValue("web_page")); | 535 contexts->Append(new base::StringValue("web_page")); |
553 contexts->Append(new base::StringValue("blessed_web_page")); | 536 contexts->Append(new base::StringValue("blessed_web_page")); |
554 contexts->Append(new base::StringValue("webui")); | 537 contexts->Append(new base::StringValue("webui")); |
555 value->Set("contexts", contexts); | 538 value->Set("contexts", contexts); |
556 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 539 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
557 feature->Parse(value.get()); | 540 feature->Parse(value.get()); |
558 EXPECT_EQ(6u, feature->contexts()->size()); | 541 EXPECT_EQ(6u, feature->contexts()->size()); |
559 EXPECT_TRUE(feature->contexts()->count(Feature::BLESSED_EXTENSION_CONTEXT)); | 542 EXPECT_TRUE(feature->contexts()->count(Feature::BLESSED_EXTENSION_CONTEXT)); |
560 EXPECT_TRUE(feature->contexts()->count(Feature::UNBLESSED_EXTENSION_CONTEXT)); | 543 EXPECT_TRUE(feature->contexts()->count(Feature::UNBLESSED_EXTENSION_CONTEXT)); |
561 EXPECT_TRUE(feature->contexts()->count(Feature::CONTENT_SCRIPT_CONTEXT)); | 544 EXPECT_TRUE(feature->contexts()->count(Feature::CONTENT_SCRIPT_CONTEXT)); |
562 EXPECT_TRUE(feature->contexts()->count(Feature::WEB_PAGE_CONTEXT)); | 545 EXPECT_TRUE(feature->contexts()->count(Feature::WEB_PAGE_CONTEXT)); |
563 EXPECT_TRUE(feature->contexts()->count(Feature::BLESSED_WEB_PAGE_CONTEXT)); | 546 EXPECT_TRUE(feature->contexts()->count(Feature::BLESSED_WEB_PAGE_CONTEXT)); |
564 | 547 |
565 value->SetString("contexts", "all"); | 548 value->SetString("contexts", "all"); |
566 scoped_ptr<SimpleFeature> feature2(new SimpleFeature()); | 549 scoped_ptr<SimpleFeature> feature2(new SimpleFeature()); |
567 feature2->Parse(value.get()); | 550 feature2->Parse(value.get()); |
568 EXPECT_EQ(*(feature->contexts()), *(feature2->contexts())); | 551 EXPECT_EQ(*(feature->contexts()), *(feature2->contexts())); |
569 } | 552 } |
570 | 553 |
571 TEST_F(ExtensionSimpleFeatureTest, ParseLocation) { | 554 TEST(SimpleFeatureTest, ParseLocation) { |
572 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 555 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
573 value->SetString("location", "component"); | 556 value->SetString("location", "component"); |
574 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 557 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
575 feature->Parse(value.get()); | 558 feature->Parse(value.get()); |
576 EXPECT_EQ(SimpleFeature::COMPONENT_LOCATION, feature->location()); | 559 EXPECT_EQ(SimpleFeature::COMPONENT_LOCATION, feature->location()); |
577 } | 560 } |
578 | 561 |
579 TEST_F(ExtensionSimpleFeatureTest, ParsePlatforms) { | 562 TEST(SimpleFeatureTest, ParsePlatforms) { |
580 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 563 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
581 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 564 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
582 base::ListValue* platforms = new base::ListValue(); | 565 base::ListValue* platforms = new base::ListValue(); |
583 value->Set("platforms", platforms); | 566 value->Set("platforms", platforms); |
584 feature->Parse(value.get()); | 567 feature->Parse(value.get()); |
585 EXPECT_TRUE(feature->platforms()->empty()); | 568 EXPECT_TRUE(feature->platforms()->empty()); |
586 | 569 |
587 platforms->AppendString("chromeos"); | 570 platforms->AppendString("chromeos"); |
588 feature->Parse(value.get()); | 571 feature->Parse(value.get()); |
589 EXPECT_FALSE(feature->platforms()->empty()); | 572 EXPECT_FALSE(feature->platforms()->empty()); |
(...skipping 10 matching lines...) Expand all Loading... |
600 platforms->AppendString("chromeos"); | 583 platforms->AppendString("chromeos"); |
601 feature->Parse(value.get()); | 584 feature->Parse(value.get()); |
602 std::set<Feature::Platform> expected_platforms; | 585 std::set<Feature::Platform> expected_platforms; |
603 expected_platforms.insert(Feature::CHROMEOS_PLATFORM); | 586 expected_platforms.insert(Feature::CHROMEOS_PLATFORM); |
604 expected_platforms.insert(Feature::WIN_PLATFORM); | 587 expected_platforms.insert(Feature::WIN_PLATFORM); |
605 | 588 |
606 EXPECT_FALSE(feature->platforms()->empty()); | 589 EXPECT_FALSE(feature->platforms()->empty()); |
607 EXPECT_EQ(expected_platforms, *feature->platforms()); | 590 EXPECT_EQ(expected_platforms, *feature->platforms()); |
608 } | 591 } |
609 | 592 |
610 TEST_F(ExtensionSimpleFeatureTest, ManifestVersion) { | 593 TEST(SimpleFeatureTest, ParseManifestVersion) { |
611 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); | 594 scoped_ptr<base::DictionaryValue> value(new base::DictionaryValue()); |
612 value->SetInteger("min_manifest_version", 1); | 595 value->SetInteger("min_manifest_version", 1); |
613 value->SetInteger("max_manifest_version", 5); | 596 value->SetInteger("max_manifest_version", 5); |
614 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); | 597 scoped_ptr<SimpleFeature> feature(new SimpleFeature()); |
615 feature->Parse(value.get()); | 598 feature->Parse(value.get()); |
616 EXPECT_EQ(1, feature->min_manifest_version()); | 599 EXPECT_EQ(1, feature->min_manifest_version()); |
617 EXPECT_EQ(5, feature->max_manifest_version()); | 600 EXPECT_EQ(5, feature->max_manifest_version()); |
618 } | 601 } |
619 | 602 |
620 TEST_F(ExtensionSimpleFeatureTest, Inheritance) { | 603 TEST(SimpleFeatureTest, Inheritance) { |
621 SimpleFeature feature; | 604 SimpleFeature feature; |
622 feature.whitelist()->insert("foo"); | 605 feature.whitelist()->insert("foo"); |
623 feature.extension_types()->insert(Manifest::TYPE_THEME); | 606 feature.extension_types()->insert(Manifest::TYPE_THEME); |
624 feature.contexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT); | 607 feature.contexts()->insert(Feature::BLESSED_EXTENSION_CONTEXT); |
625 feature.set_location(SimpleFeature::COMPONENT_LOCATION); | 608 feature.set_location(SimpleFeature::COMPONENT_LOCATION); |
626 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); | 609 feature.platforms()->insert(Feature::CHROMEOS_PLATFORM); |
627 feature.set_min_manifest_version(1); | 610 feature.set_min_manifest_version(1); |
628 feature.set_max_manifest_version(2); | 611 feature.set_max_manifest_version(2); |
629 | 612 |
630 // Test additive parsing. Parsing an empty dictionary should result in no | 613 // Test additive parsing. Parsing an empty dictionary should result in no |
(...skipping 28 matching lines...) Expand all Loading... |
659 EXPECT_EQ(1u, feature.extension_types()->size()); | 642 EXPECT_EQ(1u, feature.extension_types()->size()); |
660 EXPECT_EQ(1u, feature.contexts()->size()); | 643 EXPECT_EQ(1u, feature.contexts()->size()); |
661 EXPECT_EQ(1u, feature.whitelist()->count("bar")); | 644 EXPECT_EQ(1u, feature.whitelist()->count("bar")); |
662 EXPECT_EQ(1u, feature.extension_types()->count(Manifest::TYPE_EXTENSION)); | 645 EXPECT_EQ(1u, feature.extension_types()->count(Manifest::TYPE_EXTENSION)); |
663 EXPECT_EQ(1u, | 646 EXPECT_EQ(1u, |
664 feature.contexts()->count(Feature::UNBLESSED_EXTENSION_CONTEXT)); | 647 feature.contexts()->count(Feature::UNBLESSED_EXTENSION_CONTEXT)); |
665 EXPECT_EQ(2, feature.min_manifest_version()); | 648 EXPECT_EQ(2, feature.min_manifest_version()); |
666 EXPECT_EQ(3, feature.max_manifest_version()); | 649 EXPECT_EQ(3, feature.max_manifest_version()); |
667 } | 650 } |
668 | 651 |
669 Feature::AvailabilityResult IsAvailableInChannel( | |
670 const std::string& channel, VersionInfo::Channel channel_for_testing) { | |
671 ScopedCurrentChannel current_channel(channel_for_testing); | |
672 | |
673 SimpleFeature feature; | |
674 feature.AddFilter(scoped_ptr<extensions::SimpleFeatureFilter>( | |
675 new extensions::ChromeChannelFeatureFilter(&feature))); | |
676 if (!channel.empty()) { | |
677 base::DictionaryValue feature_value; | |
678 feature_value.SetString("channel", channel); | |
679 feature.Parse(&feature_value); | |
680 } | |
681 | |
682 return feature.IsAvailableToManifest("random-extension", | |
683 Manifest::TYPE_UNKNOWN, | |
684 Manifest::INVALID_LOCATION, | |
685 -1, | |
686 Feature::GetCurrentPlatform()).result(); | |
687 } | |
688 | |
689 TEST_F(ExtensionSimpleFeatureTest, SupportedChannel) { | |
690 // stable supported. | |
691 EXPECT_EQ(Feature::IS_AVAILABLE, | |
692 IsAvailableInChannel("stable", VersionInfo::CHANNEL_UNKNOWN)); | |
693 EXPECT_EQ(Feature::IS_AVAILABLE, | |
694 IsAvailableInChannel("stable", VersionInfo::CHANNEL_CANARY)); | |
695 EXPECT_EQ(Feature::IS_AVAILABLE, | |
696 IsAvailableInChannel("stable", VersionInfo::CHANNEL_DEV)); | |
697 EXPECT_EQ(Feature::IS_AVAILABLE, | |
698 IsAvailableInChannel("stable", VersionInfo::CHANNEL_BETA)); | |
699 EXPECT_EQ(Feature::IS_AVAILABLE, | |
700 IsAvailableInChannel("stable", VersionInfo::CHANNEL_STABLE)); | |
701 | |
702 // beta supported. | |
703 EXPECT_EQ(Feature::IS_AVAILABLE, | |
704 IsAvailableInChannel("beta", VersionInfo::CHANNEL_UNKNOWN)); | |
705 EXPECT_EQ(Feature::IS_AVAILABLE, | |
706 IsAvailableInChannel("beta", VersionInfo::CHANNEL_CANARY)); | |
707 EXPECT_EQ(Feature::IS_AVAILABLE, | |
708 IsAvailableInChannel("beta", VersionInfo::CHANNEL_DEV)); | |
709 EXPECT_EQ(Feature::IS_AVAILABLE, | |
710 IsAvailableInChannel("beta", VersionInfo::CHANNEL_BETA)); | |
711 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
712 IsAvailableInChannel("beta", VersionInfo::CHANNEL_STABLE)); | |
713 | |
714 // dev supported. | |
715 EXPECT_EQ(Feature::IS_AVAILABLE, | |
716 IsAvailableInChannel("dev", VersionInfo::CHANNEL_UNKNOWN)); | |
717 EXPECT_EQ(Feature::IS_AVAILABLE, | |
718 IsAvailableInChannel("dev", VersionInfo::CHANNEL_CANARY)); | |
719 EXPECT_EQ(Feature::IS_AVAILABLE, | |
720 IsAvailableInChannel("dev", VersionInfo::CHANNEL_DEV)); | |
721 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
722 IsAvailableInChannel("dev", VersionInfo::CHANNEL_BETA)); | |
723 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
724 IsAvailableInChannel("dev", VersionInfo::CHANNEL_STABLE)); | |
725 | |
726 // canary supported. | |
727 EXPECT_EQ(Feature::IS_AVAILABLE, | |
728 IsAvailableInChannel("canary", VersionInfo::CHANNEL_UNKNOWN)); | |
729 EXPECT_EQ(Feature::IS_AVAILABLE, | |
730 IsAvailableInChannel("canary", VersionInfo::CHANNEL_CANARY)); | |
731 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
732 IsAvailableInChannel("canary", VersionInfo::CHANNEL_DEV)); | |
733 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
734 IsAvailableInChannel("canary", VersionInfo::CHANNEL_BETA)); | |
735 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
736 IsAvailableInChannel("canary", VersionInfo::CHANNEL_STABLE)); | |
737 | |
738 // trunk supported. | |
739 EXPECT_EQ(Feature::IS_AVAILABLE, | |
740 IsAvailableInChannel("trunk", VersionInfo::CHANNEL_UNKNOWN)); | |
741 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
742 IsAvailableInChannel("trunk", VersionInfo::CHANNEL_CANARY)); | |
743 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
744 IsAvailableInChannel("trunk", VersionInfo::CHANNEL_DEV)); | |
745 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
746 IsAvailableInChannel("trunk", VersionInfo::CHANNEL_BETA)); | |
747 EXPECT_EQ(Feature::UNSUPPORTED_CHANNEL, | |
748 IsAvailableInChannel("trunk", VersionInfo::CHANNEL_STABLE)); | |
749 } | |
750 | |
751 } // namespace extensions | 652 } // namespace extensions |
OLD | NEW |