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

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

Issue 23257005: Move Feature and Manifest to top-level extensions. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: rebase Created 7 years, 4 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
« no previous file with comments | « chrome/common/extensions/manifest.h ('k') | chrome/common/extensions/manifest_handler.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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 "chrome/common/extensions/manifest.h"
6
7 #include "base/basictypes.h"
8 #include "base/lazy_instance.h"
9 #include "base/logging.h"
10 #include "base/strings/string_split.h"
11 #include "base/strings/stringprintf.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/common/extensions/features/feature.h"
14 #include "extensions/common/error_utils.h"
15 #include "extensions/common/features/feature_provider.h"
16 #include "extensions/common/install_warning.h"
17 #include "extensions/common/manifest_constants.h"
18
19 namespace extensions {
20
21 namespace keys = manifest_keys;
22
23 namespace {
24
25 // Rank extension locations in a way that allows
26 // Manifest::GetHigherPriorityLocation() to compare locations.
27 // An extension installed from two locations will have the location
28 // with the higher rank, as returned by this function. The actual
29 // integer values may change, and should never be persisted.
30 int GetLocationRank(Manifest::Location location) {
31 const int kInvalidRank = -1;
32 int rank = kInvalidRank; // Will CHECK that rank is not kInvalidRank.
33
34 switch (location) {
35 // Component extensions can not be overriden by any other type.
36 case Manifest::COMPONENT:
37 rank = 7;
38 break;
39
40 // Policy controlled extensions may not be overridden by any type
41 // that is not part of chrome.
42 case Manifest::EXTERNAL_POLICY_DOWNLOAD:
43 rank = 6;
44 break;
45
46 // A developer-loaded extension should override any installed type
47 // that a user can disable. Anything specified on the command-line should
48 // override one loaded via the extensions UI.
49 case Manifest::COMMAND_LINE:
50 rank = 5;
51 break;
52
53 case Manifest::UNPACKED:
54 rank = 4;
55 break;
56
57 // The relative priority of various external sources is not important,
58 // but having some order ensures deterministic behavior.
59 case Manifest::EXTERNAL_REGISTRY:
60 rank = 3;
61 break;
62
63 case Manifest::EXTERNAL_PREF:
64 rank = 2;
65 break;
66
67 case Manifest::EXTERNAL_PREF_DOWNLOAD:
68 rank = 1;
69 break;
70
71 // User installed extensions are overridden by any external type.
72 case Manifest::INTERNAL:
73 rank = 0;
74 break;
75
76 default:
77 NOTREACHED() << "Need to add new extension location " << location;
78 }
79
80 CHECK(rank != kInvalidRank);
81 return rank;
82 }
83
84 } // namespace
85
86 // static
87 Manifest::Location Manifest::GetHigherPriorityLocation(
88 Location loc1, Location loc2) {
89 if (loc1 == loc2)
90 return loc1;
91
92 int loc1_rank = GetLocationRank(loc1);
93 int loc2_rank = GetLocationRank(loc2);
94
95 // If two different locations have the same rank, then we can not
96 // deterministicly choose a location.
97 CHECK(loc1_rank != loc2_rank);
98
99 // Highest rank has highest priority.
100 return (loc1_rank > loc2_rank ? loc1 : loc2 );
101 }
102
103 Manifest::Manifest(Location location, scoped_ptr<base::DictionaryValue> value)
104 : location_(location),
105 value_(value.Pass()),
106 type_(TYPE_UNKNOWN) {
107 if (value_->HasKey(keys::kTheme)) {
108 type_ = TYPE_THEME;
109 } else if (value_->HasKey(keys::kExport)) {
110 type_ = TYPE_SHARED_MODULE;
111 } else if (value_->HasKey(keys::kApp)) {
112 if (value_->Get(keys::kWebURLs, NULL) ||
113 value_->Get(keys::kLaunchWebURL, NULL)) {
114 type_ = TYPE_HOSTED_APP;
115 } else if (value_->Get(keys::kPlatformAppBackground, NULL)) {
116 type_ = TYPE_PLATFORM_APP;
117 } else {
118 type_ = TYPE_LEGACY_PACKAGED_APP;
119 }
120 } else {
121 type_ = TYPE_EXTENSION;
122 }
123 CHECK_NE(type_, TYPE_UNKNOWN);
124 }
125
126 Manifest::~Manifest() {
127 }
128
129 bool Manifest::ValidateManifest(
130 std::string* error,
131 std::vector<InstallWarning>* warnings) const {
132 *error = "";
133
134 // Check every feature to see if its in the manifest. Note that this means
135 // we will ignore keys that are not features; we do this for forward
136 // compatibility.
137 // TODO(aa): Consider having an error here in the case of strict error
138 // checking to let developers know when they screw up.
139
140 FeatureProvider* provider = FeatureProvider::GetByName("manifest");
141 const std::vector<std::string>& feature_names =
142 provider->GetAllFeatureNames();
143 for (std::vector<std::string>::const_iterator feature_name =
144 feature_names.begin();
145 feature_name != feature_names.end(); ++feature_name) {
146 // Use Get instead of HasKey because the former uses path expansion.
147 if (!value_->Get(*feature_name, NULL))
148 continue;
149
150 Feature* feature = provider->GetFeature(*feature_name);
151 Feature::Availability result = feature->IsAvailableToManifest(
152 extension_id_, type_, Feature::ConvertLocation(location_),
153 GetManifestVersion());
154 if (!result.is_available())
155 warnings->push_back(InstallWarning(result.message(), *feature_name));
156 }
157
158 // Also generate warnings for keys that are not features.
159 for (base::DictionaryValue::Iterator it(*value_); !it.IsAtEnd();
160 it.Advance()) {
161 if (!provider->GetFeature(it.key())) {
162 warnings->push_back(InstallWarning(
163 base::StringPrintf("Unrecognized manifest key '%s'.",
164 it.key().c_str()),
165 it.key()));
166 }
167 }
168 return true;
169 }
170
171 bool Manifest::HasKey(const std::string& key) const {
172 return CanAccessKey(key) && value_->HasKey(key);
173 }
174
175 bool Manifest::HasPath(const std::string& path) const {
176 base::Value* ignored = NULL;
177 return CanAccessPath(path) && value_->Get(path, &ignored);
178 }
179
180 bool Manifest::Get(
181 const std::string& path, const base::Value** out_value) const {
182 return CanAccessPath(path) && value_->Get(path, out_value);
183 }
184
185 bool Manifest::GetBoolean(
186 const std::string& path, bool* out_value) const {
187 return CanAccessPath(path) && value_->GetBoolean(path, out_value);
188 }
189
190 bool Manifest::GetInteger(
191 const std::string& path, int* out_value) const {
192 return CanAccessPath(path) && value_->GetInteger(path, out_value);
193 }
194
195 bool Manifest::GetString(
196 const std::string& path, std::string* out_value) const {
197 return CanAccessPath(path) && value_->GetString(path, out_value);
198 }
199
200 bool Manifest::GetString(
201 const std::string& path, string16* out_value) const {
202 return CanAccessPath(path) && value_->GetString(path, out_value);
203 }
204
205 bool Manifest::GetDictionary(
206 const std::string& path, const base::DictionaryValue** out_value) const {
207 return CanAccessPath(path) && value_->GetDictionary(path, out_value);
208 }
209
210 bool Manifest::GetList(
211 const std::string& path, const base::ListValue** out_value) const {
212 return CanAccessPath(path) && value_->GetList(path, out_value);
213 }
214
215 Manifest* Manifest::DeepCopy() const {
216 Manifest* manifest = new Manifest(
217 location_, scoped_ptr<base::DictionaryValue>(value_->DeepCopy()));
218 manifest->set_extension_id(extension_id_);
219 return manifest;
220 }
221
222 bool Manifest::Equals(const Manifest* other) const {
223 return other && value_->Equals(other->value());
224 }
225
226 int Manifest::GetManifestVersion() const {
227 // Platform apps were launched after manifest version 2 was the preferred
228 // version, so they default to that.
229 int manifest_version = type_ == TYPE_PLATFORM_APP ? 2 : 1;
230 value_->GetInteger(keys::kManifestVersion, &manifest_version);
231 return manifest_version;
232 }
233
234 bool Manifest::CanAccessPath(const std::string& path) const {
235 std::vector<std::string> components;
236 base::SplitString(path, '.', &components);
237 std::string key;
238 for (size_t i = 0; i < components.size(); ++i) {
239 key += components[i];
240 if (!CanAccessKey(key))
241 return false;
242 key += '.';
243 }
244 return true;
245 }
246
247 bool Manifest::CanAccessKey(const std::string& key) const {
248 Feature* feature = FeatureProvider::GetByName("manifest")->GetFeature(key);
249 if (!feature)
250 return true;
251
252 return feature->IsAvailableToManifest(
253 extension_id_, type_, Feature::ConvertLocation(location_),
254 GetManifestVersion()).is_available();
255 }
256
257 } // namespace extensions
OLDNEW
« no previous file with comments | « chrome/common/extensions/manifest.h ('k') | chrome/common/extensions/manifest_handler.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698