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

Side by Side Diff: chrome/common/extensions/api/extension_api.cc

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

Powered by Google App Engine
This is Rietveld 408576698