OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 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 "chrome/common/extensions/api/extension_api.h" | 5 #include "chrome/common/extensions/api/extension_api.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <string> | 8 #include <string> |
9 #include <vector> | 9 #include <vector> |
10 | 10 |
11 #include "base/json/json_reader.h" | 11 #include "base/json/json_reader.h" |
12 #include "base/lazy_instance.h" | |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/string_number_conversions.h" | |
13 #include "base/string_split.h" | 15 #include "base/string_split.h" |
14 #include "base/string_util.h" | 16 #include "base/string_util.h" |
15 #include "base/values.h" | 17 #include "base/values.h" |
16 #include "chrome/common/extensions/api/generated_schemas.h" | 18 #include "chrome/common/extensions/api/generated_schemas.h" |
17 #include "chrome/common/extensions/extension.h" | 19 #include "chrome/common/extensions/extension.h" |
18 #include "chrome/common/extensions/extension_permission_set.h" | 20 #include "chrome/common/extensions/extension_permission_set.h" |
21 #include "chrome/common/extensions/simple_feature_provider.h" | |
19 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
20 #include "grit/common_resources.h" | 23 #include "grit/common_resources.h" |
21 #include "ui/base/resource/resource_bundle.h" | 24 #include "ui/base/resource/resource_bundle.h" |
22 | 25 |
23 using base::DictionaryValue; | 26 using base::DictionaryValue; |
24 using base::ListValue; | 27 using base::ListValue; |
25 using base::Value; | 28 using base::Value; |
26 | 29 |
27 namespace extensions { | 30 namespace extensions { |
28 | 31 |
29 using api::GeneratedSchemas; | 32 using api::GeneratedSchemas; |
30 | 33 |
31 namespace { | 34 namespace { |
32 | 35 |
36 const char* kChildKinds[] = { | |
37 "functions", | |
38 "events" | |
39 }; | |
40 | |
33 // Returns whether the list at |name_space_node|.|child_kind| contains any | 41 // Returns whether the list at |name_space_node|.|child_kind| contains any |
34 // children with an { "unprivileged": true } property. | 42 // children with an { "unprivileged": true } property. |
35 bool HasUnprivilegedChild(const DictionaryValue* name_space_node, | 43 bool HasUnprivilegedChild(const DictionaryValue* name_space_node, |
36 const std::string& child_kind) { | 44 const std::string& child_kind) { |
37 ListValue* child_list = NULL; | 45 ListValue* child_list = NULL; |
38 name_space_node->GetList(child_kind, &child_list); | 46 name_space_node->GetList(child_kind, &child_list); |
39 if (!child_list) | 47 if (!child_list) |
40 return false; | 48 return false; |
41 | 49 |
42 for (size_t i = 0; i < child_list->GetSize(); ++i) { | 50 for (size_t i = 0; i < child_list->GetSize(); ++i) { |
(...skipping 17 matching lines...) Expand all Loading... | |
60 base::JSONReader::ReadAndReturnError( | 68 base::JSONReader::ReadAndReturnError( |
61 schema.as_string(), | 69 schema.as_string(), |
62 false, // allow trailing commas | 70 false, // allow trailing commas |
63 NULL, // error code | 71 NULL, // error code |
64 &error_message)); | 72 &error_message)); |
65 CHECK(result.get()) << error_message; | 73 CHECK(result.get()) << error_message; |
66 CHECK(result->IsType(Value::TYPE_LIST)); | 74 CHECK(result->IsType(Value::TYPE_LIST)); |
67 return scoped_ptr<ListValue>(static_cast<ListValue*>(result.release())); | 75 return scoped_ptr<ListValue>(static_cast<ListValue*>(result.release())); |
68 } | 76 } |
69 | 77 |
78 DictionaryValue* FindListItem(const ListValue* list, | |
79 const std::string& property_name, | |
80 const std::string& property_value) { | |
81 for (size_t i = 0; i < list->GetSize(); ++i) { | |
82 DictionaryValue* item = NULL; | |
83 CHECK(list->GetDictionary(i, &item)) | |
84 << property_value << "/" << property_name; | |
85 std::string value; | |
86 if (item->GetString(property_name, &value) && value == property_value) | |
87 return item; | |
88 } | |
89 | |
90 return NULL; | |
91 } | |
92 | |
93 const DictionaryValue* GetSchemaChild(const DictionaryValue* schema_node, | |
94 const std::string& child_name) { | |
95 DictionaryValue* child_node = NULL; | |
96 for (size_t i = 0; i < arraysize(kChildKinds); ++i) { | |
97 ListValue* list_node = NULL; | |
98 if (!schema_node->GetList(kChildKinds[i], &list_node)) | |
99 continue; | |
100 child_node = FindListItem(list_node, "name", child_name); | |
101 if (child_node) | |
102 return child_node; | |
103 } | |
104 | |
105 return NULL; | |
106 } | |
107 | |
108 struct Static { | |
109 Static() { | |
110 api.InitDefaultConfiguration(); | |
111 } | |
112 ExtensionAPI api; | |
113 }; | |
114 | |
115 base::LazyInstance<Static> g_lazy_instance = LAZY_INSTANCE_INITIALIZER; | |
116 | |
70 } // namespace | 117 } // namespace |
71 | 118 |
72 // static | 119 // static |
73 ExtensionAPI* ExtensionAPI::GetInstance() { | 120 ExtensionAPI* ExtensionAPI::GetSharedInstance() { |
74 return Singleton<ExtensionAPI>::get(); | 121 return &g_lazy_instance.Get().api; |
122 } | |
123 | |
124 // static | |
125 ExtensionAPI* ExtensionAPI::CreateWithDefaultConfiguration() { | |
126 ExtensionAPI* api = new ExtensionAPI(); | |
127 api->InitDefaultConfiguration(); | |
128 return api; | |
129 } | |
130 | |
131 // static | |
132 void ExtensionAPI::SplitDependencyName(const std::string& full_name, | |
133 std::string* feature_type, | |
134 std::string* feature_name) { | |
135 size_t colon_index = full_name.find(':'); | |
136 if (colon_index == std::string::npos) { | |
137 // TODO(aa): Remove this code when all API descriptions have been updated. | |
138 *feature_type = "api"; | |
139 *feature_name = full_name; | |
140 return; | |
141 } | |
142 | |
143 *feature_type = full_name.substr(0, colon_index); | |
144 *feature_name = full_name.substr(colon_index + 1); | |
75 } | 145 } |
76 | 146 |
77 void ExtensionAPI::LoadSchema(const base::StringPiece& schema) { | 147 void ExtensionAPI::LoadSchema(const base::StringPiece& schema) { |
78 scoped_ptr<ListValue> schema_list(LoadSchemaList(schema)); | 148 scoped_ptr<ListValue> schema_list(LoadSchemaList(schema)); |
79 std::string schema_namespace; | 149 std::string schema_namespace; |
80 | 150 |
81 while (!schema_list->empty()) { | 151 while (!schema_list->empty()) { |
82 const DictionaryValue* schema = NULL; | 152 const DictionaryValue* schema = NULL; |
83 { | 153 { |
84 Value* value = NULL; | 154 Value* value = NULL; |
(...skipping 23 matching lines...) Expand all Loading... | |
108 if (schema->GetList("matches", &matches)) { | 178 if (schema->GetList("matches", &matches)) { |
109 URLPatternSet pattern_set; | 179 URLPatternSet pattern_set; |
110 for (size_t i = 0; i < matches->GetSize(); ++i) { | 180 for (size_t i = 0; i < matches->GetSize(); ++i) { |
111 std::string pattern; | 181 std::string pattern; |
112 CHECK(matches->GetString(i, &pattern)); | 182 CHECK(matches->GetString(i, &pattern)); |
113 pattern_set.AddPattern( | 183 pattern_set.AddPattern( |
114 URLPattern(UserScript::kValidUserScriptSchemes, pattern)); | 184 URLPattern(UserScript::kValidUserScriptSchemes, pattern)); |
115 } | 185 } |
116 url_matching_apis_[schema_namespace] = pattern_set; | 186 url_matching_apis_[schema_namespace] = pattern_set; |
117 } | 187 } |
188 | |
189 // Populate feature maps. | |
190 // TODO(aa): Consider not storing features that can never run on the current | |
191 // machine (e.g., because of platform restrictions). | |
192 bool uses_feature_system = false; | |
193 schema->GetBoolean("uses_feature_system", &uses_feature_system); | |
194 if (!uses_feature_system) | |
195 continue; | |
196 | |
197 Feature* feature = new Feature(); | |
198 feature->set_name(schema_namespace); | |
199 feature->Parse(schema); | |
200 | |
201 FeatureMap* schema_features = new FeatureMap(); | |
202 CHECK(features_.insert( | |
203 std::make_pair(schema_namespace, | |
204 make_linked_ptr(schema_features))).second); | |
205 CHECK(schema_features->insert( | |
206 std::make_pair("", make_linked_ptr(feature))).second); | |
207 | |
208 for (size_t i = 0; i < arraysize(kChildKinds); ++i) { | |
209 ListValue* child_list = NULL; | |
210 schema->GetList(kChildKinds[i], &child_list); | |
211 if (!child_list) | |
212 continue; | |
213 | |
214 for (size_t j = 0; j < child_list->GetSize(); ++j) { | |
215 DictionaryValue* child = NULL; | |
216 CHECK(child_list->GetDictionary(j, &child)); | |
217 | |
218 scoped_ptr<Feature> child_feature(new Feature(*feature)); | |
219 child_feature->Parse(child); | |
220 if (child_feature->Equals(*feature)) | |
221 continue; // no need to store no-op features | |
222 | |
223 std::string child_name; | |
224 CHECK(child->GetString("name", &child_name)); | |
225 child_feature->set_name(schema_namespace + "." + child_name); | |
226 CHECK(schema_features->insert( | |
227 std::make_pair(child_name, | |
228 make_linked_ptr(child_feature.release()))).second); | |
229 } | |
230 } | |
118 } | 231 } |
119 } | 232 } |
120 | 233 |
121 ExtensionAPI::ExtensionAPI() { | 234 ExtensionAPI::ExtensionAPI() { |
235 RegisterDependencyProvider("api", this); | |
236 | |
237 // TODO(aa): Can remove this when all JSON files are converted. | |
238 RegisterDependencyProvider("", this); | |
239 } | |
240 | |
241 ExtensionAPI::~ExtensionAPI() { | |
242 } | |
243 | |
244 void ExtensionAPI::InitDefaultConfiguration() { | |
245 RegisterDependencyProvider( | |
246 "manifest", SimpleFeatureProvider::GetManifestFeatures()); | |
247 RegisterDependencyProvider( | |
248 "permission", SimpleFeatureProvider::GetPermissionFeatures()); | |
249 | |
122 // Schemas to be loaded from resources. | 250 // Schemas to be loaded from resources. |
123 unloaded_schemas_["app"] = ReadFromResource( | 251 CHECK(unloaded_schemas_.empty()); |
124 IDR_EXTENSION_API_JSON_APP); | 252 RegisterSchema("app", ReadFromResource( |
125 unloaded_schemas_["bookmarks"] = ReadFromResource( | 253 IDR_EXTENSION_API_JSON_APP)); |
126 IDR_EXTENSION_API_JSON_BOOKMARKS); | 254 RegisterSchema("bookmarks", ReadFromResource( |
127 unloaded_schemas_["browserAction"] = ReadFromResource( | 255 IDR_EXTENSION_API_JSON_BOOKMARKS)); |
128 IDR_EXTENSION_API_JSON_BROWSERACTION); | 256 RegisterSchema("browserAction", ReadFromResource( |
129 unloaded_schemas_["browsingData"] = ReadFromResource( | 257 IDR_EXTENSION_API_JSON_BROWSERACTION)); |
130 IDR_EXTENSION_API_JSON_BROWSINGDATA); | 258 RegisterSchema("browsingData", ReadFromResource( |
131 unloaded_schemas_["chromeAuthPrivate"] = ReadFromResource( | 259 IDR_EXTENSION_API_JSON_BROWSINGDATA)); |
132 IDR_EXTENSION_API_JSON_CHROMEAUTHPRIVATE); | 260 RegisterSchema("chromeAuthPrivate", ReadFromResource( |
133 unloaded_schemas_["chromeosInfoPrivate"] = ReadFromResource( | 261 IDR_EXTENSION_API_JSON_CHROMEAUTHPRIVATE)); |
134 IDR_EXTENSION_API_JSON_CHROMEOSINFOPRIVATE); | 262 RegisterSchema("chromeosInfoPrivate", ReadFromResource( |
135 unloaded_schemas_["contentSettings"] = ReadFromResource( | 263 IDR_EXTENSION_API_JSON_CHROMEOSINFOPRIVATE)); |
136 IDR_EXTENSION_API_JSON_CONTENTSETTINGS); | 264 RegisterSchema("contentSettings", ReadFromResource( |
137 unloaded_schemas_["contextMenus"] = ReadFromResource( | 265 IDR_EXTENSION_API_JSON_CONTENTSETTINGS)); |
138 IDR_EXTENSION_API_JSON_CONTEXTMENUS); | 266 RegisterSchema("contextMenus", ReadFromResource( |
139 unloaded_schemas_["cookies"] = ReadFromResource( | 267 IDR_EXTENSION_API_JSON_CONTEXTMENUS)); |
140 IDR_EXTENSION_API_JSON_COOKIES); | 268 RegisterSchema("cookies", ReadFromResource( |
141 unloaded_schemas_["debugger"] = ReadFromResource( | 269 IDR_EXTENSION_API_JSON_COOKIES)); |
142 IDR_EXTENSION_API_JSON_DEBUGGER); | 270 RegisterSchema("debugger", ReadFromResource( |
143 unloaded_schemas_["devtools"] = ReadFromResource( | 271 IDR_EXTENSION_API_JSON_DEBUGGER)); |
144 IDR_EXTENSION_API_JSON_DEVTOOLS); | 272 RegisterSchema("devtools", ReadFromResource( |
145 unloaded_schemas_["experimental.accessibility"] = ReadFromResource( | 273 IDR_EXTENSION_API_JSON_DEVTOOLS)); |
146 IDR_EXTENSION_API_JSON_EXPERIMENTAL_ACCESSIBILITY); | 274 RegisterSchema("experimental.accessibility", ReadFromResource( |
147 unloaded_schemas_["experimental.alarms"] = ReadFromResource( | 275 IDR_EXTENSION_API_JSON_EXPERIMENTAL_ACCESSIBILITY)); |
148 IDR_EXTENSION_API_JSON_EXPERIMENTAL_ALARMS); | 276 RegisterSchema("experimental.alarms", ReadFromResource( |
149 unloaded_schemas_["experimental.app"] = ReadFromResource( | 277 IDR_EXTENSION_API_JSON_EXPERIMENTAL_ALARMS)); |
150 IDR_EXTENSION_API_JSON_EXPERIMENTAL_APP); | 278 RegisterSchema("experimental.app", ReadFromResource( |
151 unloaded_schemas_["experimental.bookmarkManager"] = ReadFromResource( | 279 IDR_EXTENSION_API_JSON_EXPERIMENTAL_APP)); |
152 IDR_EXTENSION_API_JSON_EXPERIMENTAL_BOOKMARKMANAGER); | 280 RegisterSchema("experimental.bookmarkManager", ReadFromResource( |
153 unloaded_schemas_["experimental.declarative"] = ReadFromResource( | 281 IDR_EXTENSION_API_JSON_EXPERIMENTAL_BOOKMARKMANAGER)); |
154 IDR_EXTENSION_API_JSON_EXPERIMENTAL_DECLARATIVE); | 282 RegisterSchema("experimental.declarative", ReadFromResource( |
155 unloaded_schemas_["experimental.downloads"] = ReadFromResource( | 283 IDR_EXTENSION_API_JSON_EXPERIMENTAL_DECLARATIVE)); |
156 IDR_EXTENSION_API_JSON_EXPERIMENTAL_DOWNLOADS); | 284 RegisterSchema("experimental.downloads", ReadFromResource( |
157 unloaded_schemas_["experimental.extension"] = ReadFromResource( | 285 IDR_EXTENSION_API_JSON_EXPERIMENTAL_DOWNLOADS)); |
158 IDR_EXTENSION_API_JSON_EXPERIMENTAL_EXTENSION); | 286 RegisterSchema("experimental.extension", ReadFromResource( |
159 unloaded_schemas_["experimental.fontSettings"] = ReadFromResource( | 287 IDR_EXTENSION_API_JSON_EXPERIMENTAL_EXTENSION)); |
160 IDR_EXTENSION_API_JSON_EXPERIMENTAL_FONTSSETTINGS); | 288 RegisterSchema("experimental.fontSettings", ReadFromResource( |
161 unloaded_schemas_["experimental.identity"] = ReadFromResource( | 289 IDR_EXTENSION_API_JSON_EXPERIMENTAL_FONTSSETTINGS)); |
162 IDR_EXTENSION_API_JSON_EXPERIMENTAL_IDENTITY); | 290 RegisterSchema("experimental.identity", ReadFromResource( |
163 unloaded_schemas_["experimental.infobars"] = ReadFromResource( | 291 IDR_EXTENSION_API_JSON_EXPERIMENTAL_IDENTITY)); |
164 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INFOBARS); | 292 RegisterSchema("experimental.infobars", ReadFromResource( |
165 unloaded_schemas_["experimental.input.ui"] = ReadFromResource( | 293 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INFOBARS)); |
166 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_UI); | 294 RegisterSchema("experimental.input.ui", ReadFromResource( |
167 unloaded_schemas_["experimental.input.virtualKeyboard"] = ReadFromResource( | 295 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_UI)); |
168 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD); | 296 RegisterSchema("experimental.input.virtualKeyboard", ReadFromResource( |
169 unloaded_schemas_["experimental.keybinding"] = ReadFromResource( | 297 IDR_EXTENSION_API_JSON_EXPERIMENTAL_INPUT_VIRTUALKEYBOARD)); |
170 IDR_EXTENSION_API_JSON_EXPERIMENTAL_KEYBINDING); | 298 RegisterSchema("experimental.keybinding", ReadFromResource( |
171 unloaded_schemas_["experimental.managedMode"] = ReadFromResource( | 299 IDR_EXTENSION_API_JSON_EXPERIMENTAL_KEYBINDING)); |
172 IDR_EXTENSION_API_JSON_EXPERIMENTAL_MANAGEDMODE); | 300 RegisterSchema("experimental.managedMode", ReadFromResource( |
173 unloaded_schemas_["experimental.offscreenTabs"] = ReadFromResource( | 301 IDR_EXTENSION_API_JSON_EXPERIMENTAL_MANAGEDMODE)); |
174 IDR_EXTENSION_API_JSON_EXPERIMENTAL_OFFSCREENTABS); | 302 RegisterSchema("experimental.offscreenTabs", ReadFromResource( |
175 unloaded_schemas_["experimental.processes"] = ReadFromResource( | 303 IDR_EXTENSION_API_JSON_EXPERIMENTAL_OFFSCREENTABS)); |
176 IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES); | 304 RegisterSchema("experimental.processes", ReadFromResource( |
177 unloaded_schemas_["experimental.rlz"] = ReadFromResource( | 305 IDR_EXTENSION_API_JSON_EXPERIMENTAL_PROCESSES)); |
178 IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ); | 306 RegisterSchema("experimental.rlz", ReadFromResource( |
179 unloaded_schemas_["experimental.serial"] = ReadFromResource( | 307 IDR_EXTENSION_API_JSON_EXPERIMENTAL_RLZ)); |
180 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SERIAL); | 308 RegisterSchema("experimental.serial", ReadFromResource( |
181 unloaded_schemas_["experimental.socket"] = ReadFromResource( | 309 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SERIAL)); |
182 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SOCKET); | 310 RegisterSchema("experimental.socket", ReadFromResource( |
183 unloaded_schemas_["experimental.speechInput"] = ReadFromResource( | 311 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SOCKET)); |
184 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SPEECHINPUT); | 312 RegisterSchema("experimental.speechInput", ReadFromResource( |
185 unloaded_schemas_["experimental.webRequest"] = ReadFromResource( | 313 IDR_EXTENSION_API_JSON_EXPERIMENTAL_SPEECHINPUT)); |
186 IDR_EXTENSION_API_JSON_EXPERIMENTAL_WEBREQUEST); | 314 RegisterSchema("experimental.webRequest", ReadFromResource( |
187 unloaded_schemas_["extension"] = ReadFromResource( | 315 IDR_EXTENSION_API_JSON_EXPERIMENTAL_WEBREQUEST)); |
188 IDR_EXTENSION_API_JSON_EXTENSION); | 316 RegisterSchema("extension", ReadFromResource( |
189 unloaded_schemas_["fileBrowserHandler"] = ReadFromResource( | 317 IDR_EXTENSION_API_JSON_EXTENSION)); |
190 IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER); | 318 RegisterSchema("fileBrowserHandler", ReadFromResource( |
191 unloaded_schemas_["fileBrowserPrivate"] = ReadFromResource( | 319 IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER)); |
192 IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE); | 320 RegisterSchema("fileBrowserPrivate", ReadFromResource( |
193 unloaded_schemas_["history"] = ReadFromResource( | 321 IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE)); |
194 IDR_EXTENSION_API_JSON_HISTORY); | 322 RegisterSchema("history", ReadFromResource( |
195 unloaded_schemas_["i18n"] = ReadFromResource( | 323 IDR_EXTENSION_API_JSON_HISTORY)); |
196 IDR_EXTENSION_API_JSON_I18N); | 324 RegisterSchema("i18n", ReadFromResource( |
197 unloaded_schemas_["idle"] = ReadFromResource( | 325 IDR_EXTENSION_API_JSON_I18N)); |
198 IDR_EXTENSION_API_JSON_IDLE); | 326 RegisterSchema("idle", ReadFromResource( |
199 unloaded_schemas_["input.ime"] = ReadFromResource( | 327 IDR_EXTENSION_API_JSON_IDLE)); |
200 IDR_EXTENSION_API_JSON_INPUT_IME); | 328 RegisterSchema("input.ime", ReadFromResource( |
201 unloaded_schemas_["inputMethodPrivate"] = ReadFromResource( | 329 IDR_EXTENSION_API_JSON_INPUT_IME)); |
202 IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE); | 330 RegisterSchema("inputMethodPrivate", ReadFromResource( |
203 unloaded_schemas_["management"] = ReadFromResource( | 331 IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE)); |
204 IDR_EXTENSION_API_JSON_MANAGEMENT); | 332 RegisterSchema("management", ReadFromResource( |
205 unloaded_schemas_["mediaPlayerPrivate"] = ReadFromResource( | 333 IDR_EXTENSION_API_JSON_MANAGEMENT)); |
206 IDR_EXTENSION_API_JSON_MEDIAPLAYERPRIVATE); | 334 RegisterSchema("mediaPlayerPrivate", ReadFromResource( |
207 unloaded_schemas_["metricsPrivate"] = ReadFromResource( | 335 IDR_EXTENSION_API_JSON_MEDIAPLAYERPRIVATE)); |
208 IDR_EXTENSION_API_JSON_METRICSPRIVATE); | 336 RegisterSchema("metricsPrivate", ReadFromResource( |
209 unloaded_schemas_["offersPrivate"] = ReadFromResource( | 337 IDR_EXTENSION_API_JSON_METRICSPRIVATE)); |
210 IDR_EXTENSION_API_JSON_OFFERSPRIVATE); | 338 RegisterSchema("offersPrivate", ReadFromResource( |
211 unloaded_schemas_["omnibox"] = ReadFromResource( | 339 IDR_EXTENSION_API_JSON_OFFERSPRIVATE)); |
212 IDR_EXTENSION_API_JSON_OMNIBOX); | 340 RegisterSchema("omnibox", ReadFromResource( |
213 unloaded_schemas_["pageAction"] = ReadFromResource( | 341 IDR_EXTENSION_API_JSON_OMNIBOX)); |
214 IDR_EXTENSION_API_JSON_PAGEACTION); | 342 RegisterSchema("pageAction", ReadFromResource( |
215 unloaded_schemas_["pageActions"] = ReadFromResource( | 343 IDR_EXTENSION_API_JSON_PAGEACTION)); |
216 IDR_EXTENSION_API_JSON_PAGEACTIONS); | 344 RegisterSchema("pageActions", ReadFromResource( |
217 unloaded_schemas_["pageCapture"] = ReadFromResource( | 345 IDR_EXTENSION_API_JSON_PAGEACTIONS)); |
218 IDR_EXTENSION_API_JSON_PAGECAPTURE); | 346 RegisterSchema("pageCapture", ReadFromResource( |
219 unloaded_schemas_["permissions"] = ReadFromResource( | 347 IDR_EXTENSION_API_JSON_PAGECAPTURE)); |
220 IDR_EXTENSION_API_JSON_PERMISSIONS); | 348 RegisterSchema("permissions", ReadFromResource( |
221 unloaded_schemas_["privacy"] = ReadFromResource( | 349 IDR_EXTENSION_API_JSON_PERMISSIONS)); |
222 IDR_EXTENSION_API_JSON_PRIVACY); | 350 RegisterSchema("privacy", ReadFromResource( |
223 unloaded_schemas_["proxy"] = ReadFromResource( | 351 IDR_EXTENSION_API_JSON_PRIVACY)); |
224 IDR_EXTENSION_API_JSON_PROXY); | 352 RegisterSchema("proxy", ReadFromResource( |
225 unloaded_schemas_["storage"] = ReadFromResource( | 353 IDR_EXTENSION_API_JSON_PROXY)); |
226 IDR_EXTENSION_API_JSON_STORAGE); | 354 RegisterSchema("storage", ReadFromResource( |
227 unloaded_schemas_["systemPrivate"] = ReadFromResource( | 355 IDR_EXTENSION_API_JSON_STORAGE)); |
228 IDR_EXTENSION_API_JSON_SYSTEMPRIVATE); | 356 RegisterSchema("systemPrivate", ReadFromResource( |
229 unloaded_schemas_["tabs"] = ReadFromResource( | 357 IDR_EXTENSION_API_JSON_SYSTEMPRIVATE)); |
230 IDR_EXTENSION_API_JSON_TABS); | 358 RegisterSchema("tabs", ReadFromResource( |
231 unloaded_schemas_["terminalPrivate"] = ReadFromResource( | 359 IDR_EXTENSION_API_JSON_TABS)); |
232 IDR_EXTENSION_API_JSON_TERMINALPRIVATE); | 360 RegisterSchema("terminalPrivate", ReadFromResource( |
233 unloaded_schemas_["test"] = ReadFromResource( | 361 IDR_EXTENSION_API_JSON_TERMINALPRIVATE)); |
234 IDR_EXTENSION_API_JSON_TEST); | 362 RegisterSchema("test", ReadFromResource( |
235 unloaded_schemas_["topSites"] = ReadFromResource( | 363 IDR_EXTENSION_API_JSON_TEST)); |
236 IDR_EXTENSION_API_JSON_TOPSITES); | 364 RegisterSchema("topSites", ReadFromResource( |
237 unloaded_schemas_["ttsEngine"] = ReadFromResource( | 365 IDR_EXTENSION_API_JSON_TOPSITES)); |
238 IDR_EXTENSION_API_JSON_TTSENGINE); | 366 RegisterSchema("ttsEngine", ReadFromResource( |
239 unloaded_schemas_["tts"] = ReadFromResource( | 367 IDR_EXTENSION_API_JSON_TTSENGINE)); |
240 IDR_EXTENSION_API_JSON_TTS); | 368 RegisterSchema("tts", ReadFromResource( |
241 unloaded_schemas_["types"] = ReadFromResource( | 369 IDR_EXTENSION_API_JSON_TTS)); |
242 IDR_EXTENSION_API_JSON_TYPES); | 370 RegisterSchema("types", ReadFromResource( |
243 unloaded_schemas_["webNavigation"] = ReadFromResource( | 371 IDR_EXTENSION_API_JSON_TYPES)); |
244 IDR_EXTENSION_API_JSON_WEBNAVIGATION); | 372 RegisterSchema("webNavigation", ReadFromResource( |
245 unloaded_schemas_["webRequest"] = ReadFromResource( | 373 IDR_EXTENSION_API_JSON_WEBNAVIGATION)); |
246 IDR_EXTENSION_API_JSON_WEBREQUEST); | 374 RegisterSchema("webRequest", ReadFromResource( |
247 unloaded_schemas_["webSocketProxyPrivate"] = ReadFromResource( | 375 IDR_EXTENSION_API_JSON_WEBREQUEST)); |
248 IDR_EXTENSION_API_JSON_WEBSOCKETPROXYPRIVATE); | 376 RegisterSchema("webSocketProxyPrivate", ReadFromResource( |
249 unloaded_schemas_["webstore"] = ReadFromResource( | 377 IDR_EXTENSION_API_JSON_WEBSOCKETPROXYPRIVATE)); |
250 IDR_EXTENSION_API_JSON_WEBSTORE); | 378 RegisterSchema("webstore", ReadFromResource( |
251 unloaded_schemas_["webstorePrivate"] = ReadFromResource( | 379 IDR_EXTENSION_API_JSON_WEBSTORE)); |
252 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE); | 380 RegisterSchema("webstorePrivate", ReadFromResource( |
253 unloaded_schemas_["windows"] = ReadFromResource( | 381 IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE)); |
254 IDR_EXTENSION_API_JSON_WINDOWS); | 382 RegisterSchema("windows", ReadFromResource( |
383 IDR_EXTENSION_API_JSON_WINDOWS)); | |
255 | 384 |
256 // Schemas to be loaded via JSON generated from IDL files. | 385 // Schemas to be loaded via JSON generated from IDL files. |
257 GeneratedSchemas::Get(&unloaded_schemas_); | 386 GeneratedSchemas::Get(&unloaded_schemas_); |
258 } | 387 } |
259 | 388 |
260 ExtensionAPI::~ExtensionAPI() { | 389 void ExtensionAPI::RegisterSchema(const std::string& name, |
390 const base::StringPiece& source) { | |
391 unloaded_schemas_[name] = source; | |
392 } | |
393 | |
394 void ExtensionAPI::RegisterDependencyProvider(const std::string& name, | |
395 FeatureProvider* provider) { | |
396 dependency_providers_[name] = provider; | |
397 } | |
398 | |
399 bool ExtensionAPI::IsAvailable(const std::string& full_name, | |
400 const Extension* extension, | |
401 Feature::Context context) { | |
402 std::set<std::string> dependency_names; | |
403 dependency_names.insert(full_name); | |
404 ResolveDependencies(&dependency_names); | |
405 | |
406 for (std::set<std::string>::iterator iter = dependency_names.begin(); | |
407 iter != dependency_names.end(); ++iter) { | |
408 std::string feature_type; | |
409 std::string feature_name; | |
410 SplitDependencyName(*iter, &feature_type, &feature_name); | |
411 | |
412 FeatureProviderMap::iterator provider = | |
413 dependency_providers_.find(feature_type); | |
414 CHECK(provider != dependency_providers_.end()) << *iter; | |
415 | |
416 scoped_ptr<Feature> feature(provider->second->GetFeature(feature_name)); | |
417 CHECK(feature.get()) << *iter; | |
418 | |
419 Feature::Availability availability = | |
420 feature->IsAvailableToContext(extension, context); | |
421 if (availability != Feature::IS_AVAILABLE) | |
422 return false; | |
423 } | |
424 | |
425 return true; | |
261 } | 426 } |
262 | 427 |
263 bool ExtensionAPI::IsPrivileged(const std::string& full_name) { | 428 bool ExtensionAPI::IsPrivileged(const std::string& full_name) { |
264 std::string api_name; | |
265 std::string child_name; | 429 std::string child_name; |
266 | 430 std::string api_name = GetAPINameForFullName(full_name, &child_name); |
koz (OOO until 15th September)
2012/04/02 06:39:48
GetAPINameForFullName() -> GetAPINameFromFullName(
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
267 { | |
268 std::vector<std::string> split; | |
269 base::SplitString(full_name, '.', &split); | |
270 std::reverse(split.begin(), split.end()); | |
271 | |
272 api_name = split.back(); | |
273 split.pop_back(); | |
274 if (api_name == "experimental") { | |
275 api_name += "." + split.back(); | |
276 split.pop_back(); | |
277 } | |
278 | |
279 // This only really works properly if split.size() == 1, however: | |
280 // - if it's empty, it's ok to leave child_name empty; presumably there's | |
281 // no functions or events with empty names. | |
282 // - if it's > 1, we can just do our best. | |
283 if (split.size() > 0) | |
284 child_name = split[0]; | |
285 } | |
286 | 431 |
287 // GetSchema to ensure that it gets loaded before any checks. | 432 // GetSchema to ensure that it gets loaded before any checks. |
288 const DictionaryValue* schema = GetSchema(api_name); | 433 const DictionaryValue* schema = GetSchema(api_name); |
289 | 434 if (api_name.empty() || !schema) |
435 return true; // default to privileged for paranoia's sake. | |
436 | |
437 // First try to use the feature system. | |
438 scoped_ptr<Feature> feature(GetFeature(full_name)); | |
439 if (feature.get()) { | |
440 // An API is 'privileged' if any of its dependencies requires a blessed | |
koz (OOO until 15th September)
2012/04/02 06:39:48
Would this comment be more accurately written as "
Aaron Boodman
2012/04/02 08:21:54
Actually the logic was slightly wrong :/. The unit
| |
441 // extension context. | |
442 std::set<std::string> resolved_dependencies; | |
443 resolved_dependencies.insert(full_name); | |
444 ResolveDependencies(&resolved_dependencies); | |
445 for (std::set<std::string>::iterator iter = resolved_dependencies.begin(); | |
446 iter != resolved_dependencies.end(); ++iter) { | |
447 scoped_ptr<Feature> dependency(GetFeature(*iter)); | |
448 for (std::set<Feature::Context>::iterator context = | |
449 dependency->contexts()->begin(); | |
450 context != dependency->contexts()->end(); ++context) { | |
451 if (*context == Feature::BLESSED_EXTENSION_CONTEXT) | |
452 return true; | |
453 } | |
454 } | |
455 return false; | |
456 } | |
457 | |
458 // If this API has been converted yet, fall back to the old system. | |
koz (OOO until 15th September)
2012/04/02 06:39:48
has -> hasn't
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
290 if (completely_unprivileged_apis_.count(api_name)) | 459 if (completely_unprivileged_apis_.count(api_name)) |
291 return false; | 460 return false; |
292 | 461 |
293 if (partially_unprivileged_apis_.count(api_name)) { | 462 if (partially_unprivileged_apis_.count(api_name)) |
294 return IsChildNamePrivileged(schema, "functions", child_name) && | 463 return IsChildNamePrivileged(schema, child_name); |
295 IsChildNamePrivileged(schema, "events", child_name); | |
296 } | |
297 | 464 |
298 return true; | 465 return true; |
299 } | 466 } |
300 | 467 |
301 DictionaryValue* ExtensionAPI::FindListItem( | |
302 const ListValue* list, | |
303 const std::string& property_name, | |
304 const std::string& property_value) { | |
305 for (size_t i = 0; i < list->GetSize(); ++i) { | |
306 DictionaryValue* item = NULL; | |
307 CHECK(list->GetDictionary(i, &item)) | |
308 << property_value << "/" << property_name; | |
309 std::string value; | |
310 if (item->GetString(property_name, &value) && value == property_value) | |
311 return item; | |
312 } | |
313 | |
314 return NULL; | |
315 } | |
316 | |
317 bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node, | 468 bool ExtensionAPI::IsChildNamePrivileged(const DictionaryValue* name_space_node, |
318 const std::string& child_kind, | |
319 const std::string& child_name) { | 469 const std::string& child_name) { |
320 ListValue* child_list = NULL; | |
321 name_space_node->GetList(child_kind, &child_list); | |
322 if (!child_list) | |
323 return true; | |
324 | |
325 bool unprivileged = false; | 470 bool unprivileged = false; |
326 DictionaryValue* child = FindListItem(child_list, "name", child_name); | 471 const DictionaryValue* child = GetSchemaChild(name_space_node, child_name); |
327 if (!child || !child->GetBoolean("unprivileged", &unprivileged)) | 472 if (!child || !child->GetBoolean("unprivileged", &unprivileged)) |
328 return true; | 473 return true; |
329 | 474 |
330 return !unprivileged; | 475 return !unprivileged; |
331 } | 476 } |
332 | 477 |
333 const DictionaryValue* ExtensionAPI::GetSchema(const std::string& api_name) { | 478 const DictionaryValue* ExtensionAPI::GetSchema(const std::string& full_name) { |
334 SchemaMap::const_iterator maybe_schema = schemas_.find(api_name); | 479 std::string child_name; |
335 if (maybe_schema != schemas_.end()) | 480 std::string api_name = GetAPINameForFullName(full_name, &child_name); |
336 return maybe_schema->second.get(); | 481 |
337 | 482 const DictionaryValue* result = NULL; |
338 // Might not have loaded yet; or might just not exist. | 483 SchemaMap::iterator maybe_schema = schemas_.find(api_name); |
339 std::map<std::string, base::StringPiece>::iterator maybe_schema_resource = | 484 if (maybe_schema != schemas_.end()) { |
340 unloaded_schemas_.find(api_name); | 485 result = maybe_schema->second.get(); |
341 if (maybe_schema_resource == unloaded_schemas_.end()) | 486 } else { |
342 return NULL; | 487 // Might not have loaded yet; or might just not exist. |
343 | 488 std::map<std::string, base::StringPiece>::iterator maybe_schema_resource = |
344 LoadSchema(maybe_schema_resource->second); | 489 unloaded_schemas_.find(api_name); |
345 maybe_schema = schemas_.find(api_name); | 490 if (maybe_schema_resource == unloaded_schemas_.end()) |
346 CHECK(schemas_.end() != maybe_schema); | 491 return NULL; |
347 return maybe_schema->second.get(); | 492 |
493 LoadSchema(maybe_schema_resource->second); | |
494 maybe_schema = schemas_.find(api_name); | |
495 CHECK(schemas_.end() != maybe_schema); | |
496 result = maybe_schema->second.get(); | |
497 } | |
498 | |
499 if (!child_name.empty()) | |
500 result = GetSchemaChild(result, child_name); | |
501 | |
502 return result; | |
348 } | 503 } |
349 | 504 |
350 scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext( | 505 scoped_ptr<std::set<std::string> > ExtensionAPI::GetAPIsForContext( |
351 Feature::Context context, const Extension* extension, const GURL& url) { | 506 Feature::Context context, const Extension* extension, const GURL& url) { |
352 // We're forced to load all schemas now because we need to know the metadata | 507 // We're forced to load all schemas now because we need to know the metadata |
353 // about every API -- and the metadata is stored in the schemas themselves. | 508 // about every API -- and the metadata is stored in the schemas themselves. |
354 // This is a shame. | 509 // This is a shame. |
355 // TODO(aa/kalman): store metadata in a separate file and don't load all | 510 // TODO(aa/kalman): store metadata in a separate file and don't load all |
356 // schemas. | 511 // schemas. |
357 LoadAllSchemas(); | 512 LoadAllSchemas(); |
358 | 513 |
359 scoped_ptr<std::set<std::string> > result(new std::set<std::string>()); | 514 std::set<std::string> temp_result; |
360 | 515 |
516 // First handle all the APIs that have been converted to the feature system. | |
517 if (extension) { | |
518 for (APIFeatureMap::iterator iter = features_.begin(); | |
519 iter != features_.end(); ++iter) { | |
520 if (IsAvailable(iter->first, extension, context)) | |
521 temp_result.insert(iter->first); | |
522 } | |
523 } | |
524 | |
525 // Second, fall back to the old way. | |
526 // TODO(aa): Remove this when all APIs have been converted. | |
361 switch (context) { | 527 switch (context) { |
362 case Feature::UNSPECIFIED_CONTEXT: | 528 case Feature::UNSPECIFIED_CONTEXT: |
363 break; | 529 break; |
364 | 530 |
365 case Feature::BLESSED_EXTENSION_CONTEXT: | 531 case Feature::BLESSED_EXTENSION_CONTEXT: |
366 // Availability is determined by the permissions of the extension. | 532 // Availability is determined by the permissions of the extension. |
367 CHECK(extension); | 533 CHECK(extension); |
368 GetAllowedAPIs(extension, result.get()); | 534 GetAllowedAPIs(extension, &temp_result); |
369 ResolveDependencies(result.get()); | 535 ResolveDependencies(&temp_result); |
370 break; | 536 break; |
371 | 537 |
372 case Feature::UNBLESSED_EXTENSION_CONTEXT: | 538 case Feature::UNBLESSED_EXTENSION_CONTEXT: |
373 case Feature::CONTENT_SCRIPT_CONTEXT: | 539 case Feature::CONTENT_SCRIPT_CONTEXT: |
374 // Same as BLESSED_EXTENSION_CONTEXT, but only those APIs that are | 540 // Same as BLESSED_EXTENSION_CONTEXT, but only those APIs that are |
375 // unprivileged. | 541 // unprivileged. |
376 CHECK(extension); | 542 CHECK(extension); |
377 GetAllowedAPIs(extension, result.get()); | 543 GetAllowedAPIs(extension, &temp_result); |
378 // Resolving dependencies before removing unprivileged APIs means that | 544 // Resolving dependencies before removing unprivileged APIs means that |
379 // some unprivileged APIs may have unrealised dependencies. Too bad! | 545 // some unprivileged APIs may have unrealised dependencies. Too bad! |
380 ResolveDependencies(result.get()); | 546 ResolveDependencies(&temp_result); |
381 RemovePrivilegedAPIs(result.get()); | 547 RemovePrivilegedAPIs(&temp_result); |
382 break; | 548 break; |
383 | 549 |
384 case Feature::WEB_PAGE_CONTEXT: | 550 case Feature::WEB_PAGE_CONTEXT: |
385 // Availablility is determined by the url. | 551 // Availablility is determined by the url. |
386 CHECK(url.is_valid()); | 552 CHECK(url.is_valid()); |
387 GetAPIsMatchingURL(url, result.get()); | 553 GetAPIsMatchingURL(url, &temp_result); |
388 break; | 554 break; |
389 } | 555 } |
390 | 556 |
557 // Filter out all non-API features and remove the feature type part of the | |
558 // name. | |
559 scoped_ptr<std::set<std::string> > result(new std::set<std::string>()); | |
560 for (std::set<std::string>::iterator iter = temp_result.begin(); | |
561 iter != temp_result.end(); ++iter) { | |
562 std::string feature_type; | |
563 std::string feature_name; | |
564 SplitDependencyName(*iter, &feature_type, &feature_name); | |
565 if (feature_type == "api") | |
566 result->insert(feature_name); | |
567 } | |
568 | |
391 return result.Pass(); | 569 return result.Pass(); |
392 } | 570 } |
393 | 571 |
572 scoped_ptr<Feature> ExtensionAPI::GetFeature(const std::string& full_name) { | |
573 LoadAllSchemas(); | |
koz (OOO until 15th September)
2012/04/02 06:39:48
Could you add a comment explaining why we need to
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
574 | |
575 std::string child_name; | |
576 std::string api_namespace = GetAPINameForFullName(full_name, &child_name); | |
577 | |
578 APIFeatureMap::iterator feature_map = features_.find(api_namespace); | |
koz (OOO until 15th September)
2012/04/02 06:39:48
feature_map -> api_features?
I think that is more
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
579 if (feature_map == features_.end()) | |
580 return scoped_ptr<Feature>(NULL); | |
581 | |
582 scoped_ptr<Feature> result; | |
583 FeatureMap::iterator child_feature = feature_map->second->find(child_name); | |
584 if (child_feature != feature_map->second->end()) { | |
585 // TODO(aa): Argh, having FeatureProvider return a scoped pointer was a | |
586 // mistake. See: crbug.com/120068. | |
587 result.reset(new Feature(*child_feature->second)); | |
588 } else { | |
589 FeatureMap::iterator parent_feature = feature_map->second->find(""); | |
590 CHECK(parent_feature != feature_map->second->end()); | |
591 result.reset(new Feature(*parent_feature->second)); | |
592 } | |
593 | |
594 if (result->contexts()->empty()) { | |
595 result.reset(); | |
596 LOG(ERROR) << "API feature '" << full_name | |
597 << "' must specify at least one context."; | |
598 } | |
599 | |
600 return result.Pass(); | |
601 } | |
602 | |
603 std::string ExtensionAPI::GetAPINameForFullName(const std::string& full_name, | |
604 std::string* child_name) { | |
605 std::string api_name_candidate = full_name; | |
606 while (true) { | |
607 if (features_.find(api_name_candidate) != features_.end() || | |
608 schemas_.find(api_name_candidate) != schemas_.end() || | |
609 unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) { | |
610 std::string result = api_name_candidate; | |
611 | |
612 if (child_name) { | |
613 if (result.length() < full_name.length()) | |
614 *child_name = full_name.substr(result.length() + 1); | |
615 else | |
616 *child_name = ""; | |
617 } | |
618 | |
619 return result; | |
620 } | |
621 | |
622 size_t last_dot_index = api_name_candidate.rfind('.'); | |
623 if (last_dot_index == std::string::npos) | |
624 break; | |
625 | |
626 api_name_candidate = api_name_candidate.substr(0, last_dot_index); | |
627 } | |
628 | |
629 *child_name = ""; | |
630 return ""; | |
631 } | |
632 | |
394 void ExtensionAPI::GetAllowedAPIs( | 633 void ExtensionAPI::GetAllowedAPIs( |
395 const Extension* extension, std::set<std::string>* out) { | 634 const Extension* extension, std::set<std::string>* out) { |
396 for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end(); | 635 for (SchemaMap::const_iterator i = schemas_.begin(); i != schemas_.end(); |
397 ++i) { | 636 ++i) { |
637 if (features_.find(i->first) != features_.end()) { | |
638 // This API is controlled by the feature system. Nothing to do here. | |
koz (OOO until 15th September)
2012/04/02 06:39:48
Could you add a comment to the declaration of this
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
639 continue; | |
640 } | |
641 | |
398 if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) || | 642 if (extension->required_permission_set()->HasAnyAccessToAPI(i->first) || |
399 extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) { | 643 extension->optional_permission_set()->HasAnyAccessToAPI(i->first)) { |
400 out->insert(i->first); | 644 out->insert(i->first); |
401 } | 645 } |
402 } | 646 } |
403 } | 647 } |
404 | 648 |
405 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) { | 649 void ExtensionAPI::ResolveDependencies(std::set<std::string>* out) { |
406 std::set<std::string> missing_dependencies; | 650 std::set<std::string> missing_dependencies; |
407 for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i) | 651 for (std::set<std::string>::iterator i = out->begin(); i != out->end(); ++i) |
408 GetMissingDependencies(*i, *out, &missing_dependencies); | 652 GetMissingDependencies(*i, *out, &missing_dependencies); |
409 | 653 |
410 while (missing_dependencies.size()) { | 654 while (missing_dependencies.size()) { |
411 std::string next = *missing_dependencies.begin(); | 655 std::string next = *missing_dependencies.begin(); |
412 missing_dependencies.erase(next); | 656 missing_dependencies.erase(next); |
413 out->insert(next); | 657 out->insert(next); |
414 GetMissingDependencies(next, *out, &missing_dependencies); | 658 GetMissingDependencies(next, *out, &missing_dependencies); |
415 } | 659 } |
416 } | 660 } |
417 | 661 |
418 void ExtensionAPI::GetMissingDependencies( | 662 void ExtensionAPI::GetMissingDependencies( |
419 const std::string& api_name, | 663 const std::string& api_name, |
420 const std::set<std::string>& excluding, | 664 const std::set<std::string>& excluding, |
421 std::set<std::string>* out) { | 665 std::set<std::string>* out) { |
422 const DictionaryValue* schema = GetSchema(api_name); | 666 std::string feature_type; |
423 CHECK(schema) << "Schema for " << api_name << " not found"; | 667 std::string feature_name; |
668 SplitDependencyName(api_name, &feature_type, &feature_name); | |
669 | |
670 // Only API features can have dependencies for now. | |
671 if (feature_type != "api") | |
672 return; | |
673 | |
674 const DictionaryValue* schema = GetSchema(feature_name); | |
675 CHECK(schema) << "Schema for " << feature_name << " not found"; | |
424 | 676 |
425 ListValue* dependencies = NULL; | 677 ListValue* dependencies = NULL; |
426 if (!schema->GetList("dependencies", &dependencies)) | 678 if (!schema->GetList("dependencies", &dependencies)) |
427 return; | 679 return; |
428 | 680 |
429 for (size_t i = 0; i < dependencies->GetSize(); ++i) { | 681 for (size_t i = 0; i < dependencies->GetSize(); ++i) { |
430 std::string api_name; | 682 std::string dependency_name; |
431 if (dependencies->GetString(i, &api_name) && !excluding.count(api_name)) | 683 if (dependencies->GetString(i, &dependency_name) && |
432 out->insert(api_name); | 684 !excluding.count(dependency_name)) { |
685 out->insert(dependency_name); | |
686 } | |
433 } | 687 } |
434 } | 688 } |
435 | 689 |
436 void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) { | 690 void ExtensionAPI::RemovePrivilegedAPIs(std::set<std::string>* apis) { |
437 std::set<std::string> privileged_apis; | 691 std::set<std::string> privileged_apis; |
438 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end(); | 692 for (std::set<std::string>::iterator i = apis->begin(); i != apis->end(); |
439 ++i) { | 693 ++i) { |
440 if (!completely_unprivileged_apis_.count(*i) && | 694 if (!completely_unprivileged_apis_.count(*i) && |
441 !partially_unprivileged_apis_.count(*i)) { | 695 !partially_unprivileged_apis_.count(*i)) { |
442 privileged_apis.insert(*i); | 696 privileged_apis.insert(*i); |
443 } | 697 } |
444 } | 698 } |
445 for (std::set<std::string>::iterator i = privileged_apis.begin(); | 699 for (std::set<std::string>::iterator i = privileged_apis.begin(); |
446 i != privileged_apis.end(); ++i) { | 700 i != privileged_apis.end(); ++i) { |
447 apis->erase(*i); | 701 apis->erase(*i); |
448 } | 702 } |
449 } | 703 } |
450 | 704 |
451 void ExtensionAPI::GetAPIsMatchingURL(const GURL& url, | 705 void ExtensionAPI::GetAPIsMatchingURL(const GURL& url, |
452 std::set<std::string>* out) { | 706 std::set<std::string>* out) { |
453 for (std::map<std::string, URLPatternSet>::const_iterator i = | 707 for (std::map<std::string, URLPatternSet>::const_iterator i = |
454 url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) { | 708 url_matching_apis_.begin(); i != url_matching_apis_.end(); ++i) { |
709 if (features_.find(i->first) != features_.end()) { | |
710 // This API is controlled by the feature system. Nothing to do. | |
koz (OOO until 15th September)
2012/04/02 06:39:48
Same comment as above - this should probably be me
Aaron Boodman
2012/04/02 08:21:54
Done.
| |
711 continue; | |
712 } | |
713 | |
455 if (i->second.MatchesURL(url)) | 714 if (i->second.MatchesURL(url)) |
456 out->insert(i->first); | 715 out->insert(i->first); |
457 } | 716 } |
458 } | 717 } |
459 | 718 |
460 void ExtensionAPI::LoadAllSchemas() { | 719 void ExtensionAPI::LoadAllSchemas() { |
461 while (unloaded_schemas_.size()) { | 720 while (unloaded_schemas_.size()) { |
462 LoadSchema(unloaded_schemas_.begin()->second); | 721 LoadSchema(unloaded_schemas_.begin()->second); |
463 } | 722 } |
464 } | 723 } |
465 | 724 |
466 } // namespace extensions | 725 } // namespace extensions |
OLD | NEW |