OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | |
Aaron Boodman
2011/12/01 21:32:04
This class turned out really tight and clean. Nice
jstritar
2011/12/02 16:26:33
Nice, thanks!
| |
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/string_split.h" | |
11 #include "base/values.h" | |
12 #include "chrome/common/extensions/extension_constants.h" | |
13 #include "chrome/common/extensions/extension_error_utils.h" | |
14 | |
15 namespace errors = extension_manifest_errors; | |
16 namespace keys = extension_manifest_keys; | |
17 | |
18 namespace extensions { | |
19 | |
20 namespace { | |
21 | |
22 typedef std::map<std::string, int> RestrictionMap; | |
23 | |
24 struct Restrictions { | |
25 Restrictions() { | |
26 // Base keys that all manifests can specify. | |
27 map[keys::kName] = Manifest::kTypeAll; | |
28 map[keys::kVersion] = Manifest::kTypeAll; | |
29 map[keys::kManifestVersion] = Manifest::kTypeAll; | |
30 map[keys::kDescription] = Manifest::kTypeAll; | |
31 map[keys::kIcons] = Manifest::kTypeAll; | |
32 map[keys::kCurrentLocale] = Manifest::kTypeAll; | |
33 map[keys::kDefaultLocale] = Manifest::kTypeAll; | |
34 map[keys::kSignature] = Manifest::kTypeAll; | |
35 map[keys::kUpdateURL] = Manifest::kTypeAll; | |
36 map[keys::kPublicKey] = Manifest::kTypeAll; | |
37 | |
38 // Type specific. | |
39 map[keys::kApp] = Manifest::kTypeHostedApp | Manifest::kTypePackagedApp | | |
40 Manifest::kTypePlatformApp; | |
41 map[keys::kTheme] = Manifest::kTypeTheme; | |
42 map[keys::kPlatformApp] = Manifest::kTypePlatformApp; | |
43 | |
44 // Extensions only. | |
45 map[keys::kBrowserAction] = Manifest::kTypeExtension; | |
46 map[keys::kPageAction] = Manifest::kTypeExtension; | |
47 map[keys::kPageActions] = Manifest::kTypeExtension; | |
48 map[keys::kChromeURLOverrides] = Manifest::kTypeExtension; | |
49 | |
50 // Everything except themes. | |
51 int all_but_themes = Manifest::kTypeAll - Manifest::kTypeTheme; | |
52 map[keys::kPermissions] = all_but_themes; | |
53 map[keys::kOptionalPermissions] = all_but_themes; | |
54 map[keys::kOptionsPage] = all_but_themes; | |
55 map[keys::kBackground] = all_but_themes; | |
56 map[keys::kOfflineEnabled] = all_but_themes; | |
57 map[keys::kMinimumChromeVersion] = all_but_themes; | |
58 map[keys::kRequirements] = all_but_themes; | |
59 map[keys::kConvertedFromUserScript] = all_but_themes; | |
60 map[keys::kNaClModules] = all_but_themes; | |
61 map[keys::kPlugins] = all_but_themes; | |
62 | |
63 // Extensions and packaged apps. | |
64 int ext_and_packaged = | |
65 Manifest::kTypeExtension | Manifest::kTypePackagedApp; | |
66 map[keys::kContentScripts] = ext_and_packaged; | |
67 map[keys::kOmnibox] = ext_and_packaged; | |
68 map[keys::kDevToolsPage] = ext_and_packaged; | |
69 map[keys::kSidebar] = ext_and_packaged; | |
70 map[keys::kHomepageURL] = ext_and_packaged; | |
71 | |
72 // Extensions, packaged apps and platform apps. | |
73 int local_apps_and_ext = ext_and_packaged | Manifest::kTypePlatformApp; | |
74 map[keys::kContentSecurityPolicy] = local_apps_and_ext; | |
75 map[keys::kFileBrowserHandlers] = local_apps_and_ext; | |
76 map[keys::kIncognito] = local_apps_and_ext; | |
77 map[keys::kInputComponents] = local_apps_and_ext; | |
78 map[keys::kTtsEngine] = local_apps_and_ext; | |
79 map[keys::kIntents] = local_apps_and_ext; | |
80 } | |
81 | |
82 // Returns true if the |key| is recognized. | |
83 bool IsKnownKey(const std::string& key) const { | |
84 RestrictionMap::const_iterator i = map.find(key); | |
85 return i != map.end(); | |
86 } | |
87 | |
88 // Returns true if the given |key| can be specified by the manifest |type|. | |
89 bool CanAccessKey(const std::string& key, Manifest::Type type) const { | |
90 RestrictionMap::const_iterator i = map.find(key); | |
91 return (i != map.end() && (type & i->second) != 0); | |
92 } | |
93 | |
94 RestrictionMap map; | |
95 }; | |
96 | |
97 base::LazyInstance<Restrictions> g_restrictions; | |
98 | |
99 } // namespace | |
100 | |
101 // static | |
102 std::set<std::string> Manifest::GetAllKnownKeys() { | |
103 std::set<std::string> keys; | |
104 const RestrictionMap& map = g_restrictions.Get().map; | |
105 for (RestrictionMap::const_iterator i = map.begin(); i != map.end(); i++) | |
106 keys.insert(i->first); | |
107 return keys; | |
108 } | |
109 | |
110 Manifest::Manifest(DictionaryValue* value) : value_(value) {} | |
111 Manifest::~Manifest() {} | |
112 | |
113 bool Manifest::ValidateManifest(std::string* error) const { | |
114 Restrictions restrictions = g_restrictions.Get(); | |
115 Type type = GetType(); | |
116 | |
117 for (DictionaryValue::key_iterator key = value_->begin_keys(); | |
118 key != value_->end_keys(); ++key) { | |
119 // When validating the extension manifests, we ignore keys that are not | |
120 // recognized for forward compatibility. | |
121 if (!restrictions.IsKnownKey(*key)) { | |
122 // TODO(aa): Consider having an error here in the case of strict error | |
123 // checking to let developers know when they screw up. | |
124 continue; | |
125 } | |
126 | |
127 if (!restrictions.CanAccessKey(*key, type)) { | |
128 *error = ExtensionErrorUtils::FormatErrorMessage( | |
129 errors::kFeatureNotAllowed, *key); | |
130 return false; | |
131 } | |
132 } | |
133 | |
134 return true; | |
135 } | |
136 | |
137 bool Manifest::HasKey(const std::string& key) const { | |
138 Restrictions restrictions = g_restrictions.Get(); | |
139 return restrictions.CanAccessKey(key, GetType()) && value_->HasKey(key); | |
140 } | |
141 | |
142 bool Manifest::Get( | |
143 const std::string& path, Value** out_value) const { | |
144 return CanAccessPath(path) && value_->Get(path, out_value); | |
145 } | |
146 | |
147 bool Manifest::GetBoolean( | |
148 const std::string& path, bool* out_value) const { | |
149 return CanAccessPath(path) && value_->GetBoolean(path, out_value); | |
150 } | |
151 | |
152 bool Manifest::GetInteger( | |
153 const std::string& path, int* out_value) const { | |
154 return CanAccessPath(path) && value_->GetInteger(path, out_value); | |
155 } | |
156 | |
157 bool Manifest::GetString( | |
158 const std::string& path, std::string* out_value) const { | |
159 return CanAccessPath(path) && value_->GetString(path, out_value); | |
160 } | |
161 | |
162 bool Manifest::GetString( | |
163 const std::string& path, string16* out_value) const { | |
164 return CanAccessPath(path) && value_->GetString(path, out_value); | |
165 } | |
166 | |
167 bool Manifest::GetDictionary( | |
168 const std::string& path, DictionaryValue** out_value) const { | |
169 return CanAccessPath(path) && value_->GetDictionary(path, out_value); | |
170 } | |
171 | |
172 bool Manifest::GetList( | |
173 const std::string& path, ListValue** out_value) const { | |
174 return CanAccessPath(path) && value_->GetList(path, out_value); | |
175 } | |
176 | |
177 Manifest* Manifest::DeepCopy() const { | |
178 return new Manifest(value_->DeepCopy()); | |
179 } | |
180 | |
181 bool Manifest::Equals(const Manifest* other) const { | |
182 return other && value_->Equals(other->value()); | |
183 } | |
184 | |
185 Manifest::Type Manifest::GetType() const { | |
186 if (value_->HasKey(keys::kTheme) && value_->GetDictionary(keys::kTheme, NULL)) | |
Aaron Boodman
2011/12/01 21:32:04
Why do you test that the value is a dictionary for
jstritar
2011/12/02 16:26:33
I did that to be consistent with the previous beha
| |
187 return kTypeTheme; | |
188 if (value_->HasKey(keys::kPlatformApp)) | |
189 return kTypePlatformApp; | |
190 if (value_->HasKey(keys::kApp)) { | |
191 if (value_->Get(keys::kWebURLs, NULL) || | |
192 value_->Get(keys::kLaunchWebURL, NULL)) | |
193 return kTypeHostedApp; | |
194 else | |
195 return kTypePackagedApp; | |
196 } else { | |
197 return kTypeExtension; | |
198 } | |
199 } | |
200 | |
201 bool Manifest::IsTheme() const { | |
202 return GetType() == kTypeTheme; | |
203 } | |
204 | |
205 bool Manifest::IsPlatformApp() const { | |
206 return GetType() == kTypePlatformApp; | |
207 } | |
208 | |
209 bool Manifest::IsPackagedApp() const { | |
210 return GetType() == kTypePackagedApp; | |
211 } | |
212 | |
213 bool Manifest::IsHostedApp() const { | |
214 return GetType() == kTypeHostedApp; | |
215 } | |
216 | |
217 bool Manifest::CanAccessPath(const std::string& path) const { | |
218 std::vector<std::string> components; | |
219 base::SplitString(path, '.', &components); | |
220 | |
221 Restrictions restrictions = g_restrictions.Get(); | |
222 return restrictions.CanAccessKey(components[0], GetType()); | |
223 } | |
224 | |
225 } // namespace extensions | |
OLD | NEW |