OLD | NEW |
---|---|
(Empty) | |
1 // Copyright (c) 2011 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/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 | |
43 // keys::kPlatformApp holds a boolean, so all types can define it. | |
Mihai Parparita -not on Chrome
2011/12/05 23:24:07
If this makes platform apps weird (because all the
jstritar
2011/12/14 19:00:31
If you can think of any fields that could go under
| |
44 map[keys::kPlatformApp] = Manifest::kTypeAll; | |
45 | |
46 // Extensions only. | |
47 map[keys::kBrowserAction] = Manifest::kTypeExtension; | |
48 map[keys::kPageAction] = Manifest::kTypeExtension; | |
49 map[keys::kPageActions] = Manifest::kTypeExtension; | |
50 | |
51 // Everything except themes. | |
52 int all_but_themes = Manifest::kTypeAll - Manifest::kTypeTheme; | |
53 map[keys::kPermissions] = all_but_themes; | |
54 map[keys::kOptionalPermissions] = all_but_themes; | |
55 map[keys::kOptionsPage] = all_but_themes; | |
56 map[keys::kBackground] = all_but_themes; | |
57 map[keys::kOfflineEnabled] = all_but_themes; | |
Mihai Parparita -not on Chrome
2011/12/05 23:24:07
Does this make sense for extensions? I guess we we
jstritar
2011/12/14 19:00:31
Not sure, I don't think it'll hurt, but yeah it wa
| |
58 map[keys::kMinimumChromeVersion] = all_but_themes; | |
59 map[keys::kRequirements] = all_but_themes; | |
60 map[keys::kConvertedFromUserScript] = all_but_themes; | |
Mihai Parparita -not on Chrome
2011/12/05 23:24:07
I don't think this makes sense for apps (of any ki
jstritar
2011/12/14 19:00:31
This is kind of like platform_app where it's a boo
| |
61 map[keys::kNaClModules] = all_but_themes; | |
62 map[keys::kPlugins] = all_but_themes; | |
Mihai Parparita -not on Chrome
2011/12/05 23:24:07
I think we're going to try removing NPAPI plugin s
jstritar
2011/12/14 19:00:31
I'll fix this in another CL.
| |
63 | |
64 // Extensions and packaged apps. | |
65 int ext_and_packaged = | |
66 Manifest::kTypeExtension | Manifest::kTypePackagedApp; | |
67 map[keys::kContentScripts] = ext_and_packaged; | |
68 map[keys::kOmnibox] = ext_and_packaged; | |
69 map[keys::kDevToolsPage] = ext_and_packaged; | |
70 map[keys::kSidebar] = ext_and_packaged; | |
71 map[keys::kHomepageURL] = ext_and_packaged; | |
72 map[keys::kChromeURLOverrides] = ext_and_packaged; | |
73 | |
74 // Extensions, packaged apps and platform apps. | |
75 int local_apps_and_ext = ext_and_packaged | Manifest::kTypePlatformApp; | |
76 map[keys::kContentSecurityPolicy] = local_apps_and_ext; | |
77 map[keys::kFileBrowserHandlers] = local_apps_and_ext; | |
78 map[keys::kIncognito] = local_apps_and_ext; | |
79 map[keys::kInputComponents] = local_apps_and_ext; | |
80 map[keys::kTtsEngine] = local_apps_and_ext; | |
81 map[keys::kIntents] = local_apps_and_ext; | |
82 } | |
83 | |
84 // Returns true if the |key| is recognized. | |
85 bool IsKnownKey(const std::string& key) const { | |
86 RestrictionMap::const_iterator i = map.find(key); | |
87 return i != map.end(); | |
88 } | |
89 | |
90 // Returns true if the given |key| can be specified by the manifest |type|. | |
91 bool CanAccessKey(const std::string& key, Manifest::Type type) const { | |
92 RestrictionMap::const_iterator i = map.find(key); | |
93 return (i != map.end() && (type & i->second) != 0); | |
94 } | |
95 | |
96 RestrictionMap map; | |
97 }; | |
98 | |
99 base::LazyInstance<Restrictions> g_restrictions; | |
100 | |
101 } // namespace | |
102 | |
103 // static | |
104 std::set<std::string> Manifest::GetAllKnownKeys() { | |
105 std::set<std::string> keys; | |
106 const RestrictionMap& map = g_restrictions.Get().map; | |
107 for (RestrictionMap::const_iterator i = map.begin(); i != map.end(); i++) | |
108 keys.insert(i->first); | |
109 return keys; | |
110 } | |
111 | |
112 Manifest::Manifest(DictionaryValue* value) : value_(value) {} | |
113 Manifest::~Manifest() {} | |
114 | |
115 bool Manifest::ValidateManifest(std::string* error) const { | |
116 Restrictions restrictions = g_restrictions.Get(); | |
117 Type type = GetType(); | |
118 | |
119 for (DictionaryValue::key_iterator key = value_->begin_keys(); | |
120 key != value_->end_keys(); ++key) { | |
121 // When validating the extension manifests, we ignore keys that are not | |
122 // recognized for forward compatibility. | |
123 if (!restrictions.IsKnownKey(*key)) { | |
124 // TODO(aa): Consider having an error here in the case of strict error | |
125 // checking to let developers know when they screw up. | |
126 continue; | |
127 } | |
128 | |
129 if (!restrictions.CanAccessKey(*key, type)) { | |
130 *error = ExtensionErrorUtils::FormatErrorMessage( | |
131 errors::kFeatureNotAllowed, *key); | |
132 return false; | |
133 } | |
134 } | |
135 | |
136 return true; | |
137 } | |
138 | |
139 bool Manifest::HasKey(const std::string& key) const { | |
140 Restrictions restrictions = g_restrictions.Get(); | |
141 return restrictions.CanAccessKey(key, GetType()) && value_->HasKey(key); | |
142 } | |
143 | |
144 bool Manifest::Get( | |
145 const std::string& path, Value** out_value) const { | |
146 return CanAccessPath(path) && value_->Get(path, out_value); | |
147 } | |
148 | |
149 bool Manifest::GetBoolean( | |
150 const std::string& path, bool* out_value) const { | |
151 return CanAccessPath(path) && value_->GetBoolean(path, out_value); | |
152 } | |
153 | |
154 bool Manifest::GetInteger( | |
155 const std::string& path, int* out_value) const { | |
156 return CanAccessPath(path) && value_->GetInteger(path, out_value); | |
157 } | |
158 | |
159 bool Manifest::GetString( | |
160 const std::string& path, std::string* out_value) const { | |
161 return CanAccessPath(path) && value_->GetString(path, out_value); | |
162 } | |
163 | |
164 bool Manifest::GetString( | |
165 const std::string& path, string16* out_value) const { | |
166 return CanAccessPath(path) && value_->GetString(path, out_value); | |
167 } | |
168 | |
169 bool Manifest::GetDictionary( | |
170 const std::string& path, DictionaryValue** out_value) const { | |
171 return CanAccessPath(path) && value_->GetDictionary(path, out_value); | |
172 } | |
173 | |
174 bool Manifest::GetList( | |
175 const std::string& path, ListValue** out_value) const { | |
176 return CanAccessPath(path) && value_->GetList(path, out_value); | |
177 } | |
178 | |
179 Manifest* Manifest::DeepCopy() const { | |
180 return new Manifest(value_->DeepCopy()); | |
181 } | |
182 | |
183 bool Manifest::Equals(const Manifest* other) const { | |
184 return other && value_->Equals(other->value()); | |
185 } | |
186 | |
187 Manifest::Type Manifest::GetType() const { | |
188 if (value_->HasKey(keys::kTheme)) | |
189 return kTypeTheme; | |
190 bool is_platform_app = false; | |
191 if (value_->GetBoolean(keys::kPlatformApp, &is_platform_app) && | |
192 is_platform_app) | |
193 return kTypePlatformApp; | |
194 if (value_->HasKey(keys::kApp)) { | |
195 if (value_->Get(keys::kWebURLs, NULL) || | |
196 value_->Get(keys::kLaunchWebURL, NULL)) | |
197 return kTypeHostedApp; | |
198 else | |
199 return kTypePackagedApp; | |
200 } else { | |
201 return kTypeExtension; | |
202 } | |
203 } | |
204 | |
205 bool Manifest::IsTheme() const { | |
206 return GetType() == kTypeTheme; | |
207 } | |
208 | |
209 bool Manifest::IsPlatformApp() const { | |
210 return GetType() == kTypePlatformApp; | |
211 } | |
212 | |
213 bool Manifest::IsPackagedApp() const { | |
214 return GetType() == kTypePackagedApp; | |
215 } | |
216 | |
217 bool Manifest::IsHostedApp() const { | |
218 return GetType() == kTypeHostedApp; | |
219 } | |
220 | |
221 bool Manifest::CanAccessPath(const std::string& path) const { | |
222 std::vector<std::string> components; | |
223 base::SplitString(path, '.', &components); | |
224 | |
225 Restrictions restrictions = g_restrictions.Get(); | |
226 return restrictions.CanAccessKey(components[0], GetType()); | |
227 } | |
228 | |
229 } // namespace extensions | |
OLD | NEW |