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.
5 #include "extensions/common/manifest.h"
11 #include "base/memory/scoped_ptr.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/features/feature.h"
16 #include "extensions/common/features/simple_feature.h"
17 #include "extensions/common/install_warning.h"
18 #include "extensions/common/manifest_constants.h"
19 #include "testing/gtest/include/gtest/gtest.h"
21 namespace extensions
{
23 namespace errors
= manifest_errors
;
24 namespace keys
= manifest_keys
;
26 class ManifestTest
: public testing::Test
{
28 ManifestTest() : default_value_("test") {}
31 void AssertType(Manifest
* manifest
, Manifest::Type type
) {
32 EXPECT_EQ(type
, manifest
->type());
33 EXPECT_EQ(type
== Manifest::TYPE_THEME
, manifest
->is_theme());
34 EXPECT_EQ(type
== Manifest::TYPE_PLATFORM_APP
,
35 manifest
->is_platform_app());
36 EXPECT_EQ(type
== Manifest::TYPE_LEGACY_PACKAGED_APP
,
37 manifest
->is_legacy_packaged_app());
38 EXPECT_EQ(type
== Manifest::TYPE_HOSTED_APP
, manifest
->is_hosted_app());
39 EXPECT_EQ(type
== Manifest::TYPE_SHARED_MODULE
,
40 manifest
->is_shared_module());
43 // Helper function that replaces the Manifest held by |manifest| with a copy
44 // with its |key| changed to |value|. If |value| is NULL, then |key| will
45 // instead be deleted.
46 void MutateManifest(scoped_ptr
<Manifest
>* manifest
,
47 const std::string
& key
,
49 scoped_ptr
<base::DictionaryValue
> manifest_value(
50 manifest
->get()->value()->DeepCopy());
52 manifest_value
->Set(key
, value
);
54 manifest_value
->Remove(key
, NULL
);
55 manifest
->reset(new Manifest(Manifest::INTERNAL
, manifest_value
.Pass()));
58 std::string default_value_
;
61 // Verifies that extensions can access the correct keys.
62 TEST_F(ManifestTest
, Extension
) {
63 scoped_ptr
<base::DictionaryValue
> manifest_value(new base::DictionaryValue());
64 manifest_value
->SetString(keys::kName
, "extension");
65 manifest_value
->SetString(keys::kVersion
, "1");
66 // Only supported in manifest_version=1.
67 manifest_value
->SetString(keys::kBackgroundPageLegacy
, "bg.html");
68 manifest_value
->SetString("unknown_key", "foo");
70 scoped_ptr
<Manifest
> manifest(
71 new Manifest(Manifest::INTERNAL
, manifest_value
.Pass()));
73 std::vector
<InstallWarning
> warnings
;
74 EXPECT_TRUE(manifest
->ValidateManifest(&error
, &warnings
));
75 EXPECT_TRUE(error
.empty());
76 ASSERT_EQ(1u, warnings
.size());
77 AssertType(manifest
.get(), Manifest::TYPE_EXTENSION
);
79 // The known key 'background_page' should be accessible.
81 EXPECT_TRUE(manifest
->GetString(keys::kBackgroundPageLegacy
, &value
));
82 EXPECT_EQ("bg.html", value
);
84 // The unknown key 'unknown_key' should be accesible.
86 EXPECT_TRUE(manifest
->GetString("unknown_key", &value
));
87 EXPECT_EQ("foo", value
);
89 // Set the manifest_version to 2; background_page should stop working.
92 &manifest
, keys::kManifestVersion
, new base::FundamentalValue(2));
93 EXPECT_FALSE(manifest
->GetString("background_page", &value
));
96 // Validate should also give a warning.
98 EXPECT_TRUE(manifest
->ValidateManifest(&error
, &warnings
));
99 EXPECT_TRUE(error
.empty());
100 ASSERT_EQ(2u, warnings
.size());
102 SimpleFeature feature
;
103 feature
.set_name("background_page");
104 feature
.set_max_manifest_version(1);
106 "'background_page' requires manifest version of 1 or lower.",
107 warnings
[0].message
);
110 // Test DeepCopy and Equals.
111 scoped_ptr
<Manifest
> manifest2(manifest
->DeepCopy());
112 EXPECT_TRUE(manifest
->Equals(manifest2
.get()));
113 EXPECT_TRUE(manifest2
->Equals(manifest
.get()));
115 &manifest
, "foo", new base::StringValue("blah"));
116 EXPECT_FALSE(manifest
->Equals(manifest2
.get()));
119 // Verifies that key restriction based on type works.
120 TEST_F(ManifestTest
, ExtensionTypes
) {
121 scoped_ptr
<base::DictionaryValue
> value(new base::DictionaryValue());
122 value
->SetString(keys::kName
, "extension");
123 value
->SetString(keys::kVersion
, "1");
125 scoped_ptr
<Manifest
> manifest(
126 new Manifest(Manifest::INTERNAL
, value
.Pass()));
128 std::vector
<InstallWarning
> warnings
;
129 EXPECT_TRUE(manifest
->ValidateManifest(&error
, &warnings
));
130 EXPECT_TRUE(error
.empty());
131 EXPECT_TRUE(warnings
.empty());
133 // By default, the type is Extension.
134 AssertType(manifest
.get(), Manifest::TYPE_EXTENSION
);
138 &manifest
, keys::kTheme
, new base::DictionaryValue());
139 AssertType(manifest
.get(), Manifest::TYPE_THEME
);
141 &manifest
, keys::kTheme
, NULL
);
145 &manifest
, keys::kExport
, new base::DictionaryValue());
146 AssertType(manifest
.get(), Manifest::TYPE_SHARED_MODULE
);
148 &manifest
, keys::kExport
, NULL
);
152 &manifest
, keys::kApp
, new base::DictionaryValue());
153 AssertType(manifest
.get(), Manifest::TYPE_LEGACY_PACKAGED_APP
);
155 // Platform app with event page.
157 &manifest
, keys::kPlatformAppBackground
, new base::DictionaryValue());
158 AssertType(manifest
.get(), Manifest::TYPE_PLATFORM_APP
);
160 &manifest
, keys::kPlatformAppBackground
, NULL
);
162 // Platform app with service worker.
164 &manifest
, keys::kPlatformAppServiceWorker
, new base::DictionaryValue());
165 AssertType(manifest
.get(), Manifest::TYPE_PLATFORM_APP
);
166 MutateManifest(&manifest
, keys::kPlatformAppServiceWorker
, NULL
);
170 &manifest
, keys::kWebURLs
, new base::ListValue());
171 AssertType(manifest
.get(), Manifest::TYPE_HOSTED_APP
);
173 &manifest
, keys::kWebURLs
, NULL
);
175 &manifest
, keys::kLaunchWebURL
, new base::StringValue("foo"));
176 AssertType(manifest
.get(), Manifest::TYPE_HOSTED_APP
);
178 &manifest
, keys::kLaunchWebURL
, NULL
);
181 // Verifies that the getters filter restricted keys.
182 TEST_F(ManifestTest
, RestrictedKeys
) {
183 scoped_ptr
<base::DictionaryValue
> value(new base::DictionaryValue());
184 value
->SetString(keys::kName
, "extension");
185 value
->SetString(keys::kVersion
, "1");
187 scoped_ptr
<Manifest
> manifest(
188 new Manifest(Manifest::INTERNAL
, value
.Pass()));
190 std::vector
<InstallWarning
> warnings
;
191 EXPECT_TRUE(manifest
->ValidateManifest(&error
, &warnings
));
192 EXPECT_TRUE(error
.empty());
193 EXPECT_TRUE(warnings
.empty());
195 // "Commands" requires manifest version 2.
196 const base::Value
* output
= NULL
;
198 &manifest
, keys::kCommands
, new base::DictionaryValue());
199 EXPECT_FALSE(manifest
->HasKey(keys::kCommands
));
200 EXPECT_FALSE(manifest
->Get(keys::kCommands
, &output
));
203 &manifest
, keys::kManifestVersion
, new base::FundamentalValue(2));
204 EXPECT_TRUE(manifest
->HasKey(keys::kCommands
));
205 EXPECT_TRUE(manifest
->Get(keys::kCommands
, &output
));
208 &manifest
, keys::kPageAction
, new base::DictionaryValue());
209 AssertType(manifest
.get(), Manifest::TYPE_EXTENSION
);
210 EXPECT_TRUE(manifest
->HasKey(keys::kPageAction
));
211 EXPECT_TRUE(manifest
->Get(keys::kPageAction
, &output
));
213 // Platform apps cannot have a "page_action" key.
215 &manifest
, keys::kPlatformAppBackground
, new base::DictionaryValue());
216 AssertType(manifest
.get(), Manifest::TYPE_PLATFORM_APP
);
217 EXPECT_FALSE(manifest
->HasKey(keys::kPageAction
));
218 EXPECT_FALSE(manifest
->Get(keys::kPageAction
, &output
));
220 &manifest
, keys::kPlatformAppBackground
, NULL
);
222 // Platform apps also can't have a "Commands" key.
223 EXPECT_FALSE(manifest
->HasKey(keys::kCommands
));
224 EXPECT_FALSE(manifest
->Get(keys::kCommands
, &output
));
227 } // namespace extensions