10f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)// Copyright 2013 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles)#include "extensions/common/extension_api.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm> 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string> 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <vector> 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_reader.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/json/json_writer.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/lazy_instance.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_number_conversions.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_split.h" 17868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/string_util.h" 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/values.h" 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/api/generated_schemas.h" 20f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 213551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/features/feature.h" 22ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "extensions/common/features/feature_provider.h" 231e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.h" 24f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/permissions/permissions_data.h" 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/common_resources.h" 265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "grit/extensions_api_resources.h" 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/resource/resource_bundle.h" 287dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h" 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace extensions { 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using api::GeneratedSchemas; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace { 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char* kChildKinds[] = { 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "functions", 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) "events" 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::StringPiece ReadFromResource(int resource_id) { 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return ResourceBundle::GetSharedInstance().GetRawDataResource( 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) resource_id); 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)scoped_ptr<base::ListValue> LoadSchemaList(const std::string& name, 477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::StringPiece& schema) { 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string error_message; 497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::Value> result( 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSONReader::ReadAndReturnError( 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schema, 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::JSON_PARSE_RFC | base::JSON_DETACHABLE_CHILDREN, // options 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NULL, // error code 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) &error_message)); 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Tracking down http://crbug.com/121424 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) char buf[128]; 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::snprintf(buf, arraysize(buf), "%s: (%d) '%s'", 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) name.c_str(), 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result.get() ? result->GetType() : -1, 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) error_message.c_str()); 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(result.get()) << error_message << " for schema " << schema; 647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CHECK(result->IsType(base::Value::TYPE_LIST)) << " for schema " << schema; 657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return scoped_ptr<base::ListValue>(static_cast<base::ListValue*>( 667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) result.release())); 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* FindListItem(const base::ListValue* list, 707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string& property_name, 717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string& property_value) { 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < list->GetSize(); ++i) { 737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* item = NULL; 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(list->GetDictionary(i, &item)) 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) << property_value << "/" << property_name; 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string value; 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (item->GetString(property_name, &value) && value == property_value) 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return item; 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* GetSchemaChild( 857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* schema_node, 867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string& child_name) { 877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* child_node = NULL; 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(kChildKinds); ++i) { 897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::ListValue* list_node = NULL; 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!schema_node->GetList(kChildKinds[i], &list_node)) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) continue; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) child_node = FindListItem(list_node, "name", child_name); 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_node) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return child_node; 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct Static { 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Static() 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) : api(ExtensionAPI::CreateWithDefaultConfiguration()) { 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) scoped_ptr<ExtensionAPI> api; 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}; 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)base::LazyInstance<Static> g_lazy_instance = LAZY_INSTANCE_INITIALIZER; 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// If it exists and does not already specify a namespace, then the value stored 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// with key |key| in |schema| will be updated to |schema_namespace| + "." + 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |schema[key]|. 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void MaybePrefixFieldWithNamespace(const std::string& schema_namespace, 1137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* schema, 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& key) { 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!schema->HasKey(key)) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string old_id; 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(schema->GetString(key, &old_id)); 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (old_id.find(".") == std::string::npos) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schema->SetString(key, schema_namespace + "." + old_id); 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Modify all "$ref" keys anywhere in |schema| to be prefxied by 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |schema_namespace| if they do not already specify a namespace. 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefixRefsWithNamespace(const std::string& schema_namespace, 1277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Value* value) { 1287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::ListValue* list = NULL; 1297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* dict = NULL; 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (value->GetAsList(&list)) { 1317d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (base::ListValue::iterator i = list->begin(); i != list->end(); ++i) { 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefixRefsWithNamespace(schema_namespace, *i); 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else if (value->GetAsDictionary(&dict)) { 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybePrefixFieldWithNamespace(schema_namespace, dict, "$ref"); 1367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (base::DictionaryValue::Iterator i(*dict); !i.IsAtEnd(); i.Advance()) { 1377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::Value* value = NULL; 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) CHECK(dict->GetWithoutPathExpansion(i.key(), &value)); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) PrefixRefsWithNamespace(schema_namespace, value); 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Modify all objects in the "types" section of the schema to be prefixed by 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |schema_namespace| if they do not already specify a namespace. 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefixTypesWithNamespace(const std::string& schema_namespace, 1477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* schema) { 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!schema->HasKey("types")) 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Add the namespace to all of the types defined in this schema 1527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::ListValue *types = NULL; 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(schema->GetList("types", &types)); 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < types->GetSize(); ++i) { 1557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue *type = NULL; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(types->GetDictionary(i, &type)); 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybePrefixFieldWithNamespace(schema_namespace, type, "id"); 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) MaybePrefixFieldWithNamespace(schema_namespace, type, "customBindings"); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Modify the schema so that all types are fully qualified. 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void PrefixWithNamespace(const std::string& schema_namespace, 1647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* schema) { 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefixTypesWithNamespace(schema_namespace, schema); 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefixRefsWithNamespace(schema_namespace, schema); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAPI* ExtensionAPI::GetSharedInstance() { 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return g_lazy_instance.Get().api.get(); 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAPI* ExtensionAPI::CreateWithDefaultConfiguration() { 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExtensionAPI* api = new ExtensionAPI(); 1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) api->InitDefaultConfiguration(); 1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return api; 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// static 1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAPI::SplitDependencyName(const std::string& full_name, 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* feature_type, 1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* feature_name) { 1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t colon_index = full_name.find(':'); 1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (colon_index == std::string::npos) { 1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(aa): Remove this code when all API descriptions have been updated. 1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *feature_type = "api"; 1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *feature_name = full_name; 1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *feature_type = full_name.substr(0, colon_index); 1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *feature_name = full_name.substr(colon_index + 1); 1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAPI::LoadSchema(const std::string& name, 2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const base::StringPiece& schema) { 2017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) scoped_ptr<base::ListValue> schema_list(LoadSchemaList(name, schema)); 2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string schema_namespace; 2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (!schema_list->empty()) { 2057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) base::DictionaryValue* schema = NULL; 2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) { 2073240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch scoped_ptr<base::Value> value; 2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schema_list->Remove(schema_list->GetSize() - 1, &value); 2093240926e260ce088908e02ac07a6cf7b0c0cbf44Ben Murdoch CHECK(value.release()->GetAsDictionary(&schema)); 2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(schema->GetString("namespace", &schema_namespace)); 2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) PrefixWithNamespace(schema_namespace, schema); 2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) schemas_[schema_namespace] = make_linked_ptr(schema); 2157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (!GeneratedSchemas::IsGenerated(schema_namespace)) 2167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CHECK_EQ(1u, unloaded_schemas_.erase(schema_namespace)); 2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2207d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)ExtensionAPI::ExtensionAPI() : default_configuration_initialized_(false) { 2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ExtensionAPI::~ExtensionAPI() { 2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAPI::InitDefaultConfiguration() { 2274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const char* names[] = {"api", "manifest", "permission"}; 2284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) for (size_t i = 0; i < arraysize(names); ++i) 2294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) RegisterDependencyProvider(names[i], FeatureProvider::GetByName(names[i])); 2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Schemas to be loaded from resources. 2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(unloaded_schemas_.empty()); 2337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("app", IDR_EXTENSION_API_JSON_APP); 2347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("browserAction", IDR_EXTENSION_API_JSON_BROWSERACTION); 2357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("browsingData", IDR_EXTENSION_API_JSON_BROWSINGDATA); 2367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("commands", IDR_EXTENSION_API_JSON_COMMANDS); 2377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("declarativeContent", 2387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_DECLARATIVE_CONTENT); 2397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("declarativeWebRequest", 2407d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_DECLARATIVE_WEBREQUEST); 2417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("runtime", IDR_EXTENSION_API_JSON_RUNTIME); 2427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("fileBrowserHandler", 2437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_FILEBROWSERHANDLER); 2447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("inputMethodPrivate", 2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE); 2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION); 2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("pageActions", IDR_EXTENSION_API_JSON_PAGEACTIONS); 2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("privacy", IDR_EXTENSION_API_JSON_PRIVACY); 2493551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) RegisterSchemaResource("processes", IDR_EXTENSION_API_JSON_PROCESSES); 2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY); 2517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("scriptBadge", IDR_EXTENSION_API_JSON_SCRIPTBADGE); 2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("streamsPrivate", 2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_STREAMSPRIVATE); 2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE); 2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS); 2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES); 2577dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch RegisterSchemaResource("types.private", IDR_EXTENSION_API_JSON_TYPES_PRIVATE); 2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("webRequestInternal", 2597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL); 2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE); 2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) RegisterSchemaResource("webstorePrivate", 2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE); 263f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) RegisterSchemaResource("webViewRequest", 264f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IDR_EXTENSION_API_JSON_WEBVIEW_REQUEST); 265f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) 2667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) default_configuration_initialized_ = true; 2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ExtensionAPI::RegisterSchemaResource(const std::string& name, 2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) int resource_id) { 2717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) unloaded_schemas_[name] = resource_id; 2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAPI::RegisterDependencyProvider(const std::string& name, 2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FeatureProvider* provider) { 2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dependency_providers_[name] = provider; 2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 279b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name, 2803551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const Extension* extension, 281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) Feature::Context context, 282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const GURL& url) { 283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) FeatureProviderMap::iterator provider = dependency_providers_.find("api"); 284b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) CHECK(provider != dependency_providers_.end()); 2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::vector<std::string>& features = 2867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) provider->second->GetAllFeatureNames(); 287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // Check to see if there are any parts of this API that are allowed in this 289b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) // context. 2907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) for (std::vector<std::string>::const_iterator i = features.begin(); 291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) i != features.end(); ++i) { 292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) const std::string& feature_name = *i; 293b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) if (feature_name != api_name && feature_name.find(api_name + ".") == 0) { 2943551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) if (IsAvailable(feature_name, extension, context, url).is_available()) 295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) return true; 296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 297b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) } 2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return IsAvailable(api_name, extension, context, url).is_available(); 299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)} 300b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles) 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name, 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const Extension* extension, 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Feature::Context context, 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const GURL& url) { 305c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Feature* feature = GetFeatureDependency(full_name); 3067d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CHECK(feature) << full_name; 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Feature::Availability availability = 309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) feature->IsAvailableToContext(extension, context, url); 310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!availability.is_available()) 311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return availability; 312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (std::set<std::string>::iterator iter = feature->dependencies().begin(); 314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) iter != feature->dependencies().end(); ++iter) { 315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Feature::Availability dependency_availability = 316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) IsAvailable(*iter, extension, context, url); 317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!dependency_availability.is_available()) 318c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return dependency_availability; 3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 321c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return Feature::CreateAvailability(Feature::IS_AVAILABLE, std::string()); 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionAPI::IsPrivileged(const std::string& full_name) { 325c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) Feature* feature = GetFeatureDependency(full_name); 3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) CHECK(feature); 3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) DCHECK(!feature->GetContexts()->empty()); 3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) // An API is 'privileged' if it can only be run in a blessed context. 3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) return feature->GetContexts()->size() == 3307d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT); 3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ExtensionAPI::GetSchema( 3347d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const std::string& full_name) { 3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string child_name; 3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string api_name = GetAPINameFromFullName(full_name, &child_name); 3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) const base::DictionaryValue* result = NULL; 3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SchemaMap::iterator maybe_schema = schemas_.find(api_name); 3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (maybe_schema != schemas_.end()) { 3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = maybe_schema->second.get(); 3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Might not have loaded yet; or might just not exist. 3447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) UnloadedSchemaMap::iterator maybe_schema_resource = 3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unloaded_schemas_.find(api_name); 3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) if (maybe_schema_resource != unloaded_schemas_.end()) { 3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LoadSchema(maybe_schema_resource->first, 3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) ReadFromResource(maybe_schema_resource->second)); 3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else if (default_configuration_initialized_ && 3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GeneratedSchemas::IsGenerated(api_name)) { 3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) LoadSchema(api_name, GeneratedSchemas::Get(api_name)); 3527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } else { 3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return NULL; 3547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) } 3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) maybe_schema = schemas_.find(api_name); 3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) CHECK(schemas_.end() != maybe_schema); 3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = maybe_schema->second.get(); 3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!child_name.empty()) 3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) result = GetSchemaChild(result, child_name); 3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) { 3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string feature_type; 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string feature_name; 3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SplitDependencyName(full_name, &feature_type, &feature_name); 3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) FeatureProviderMap::iterator provider = 3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) dependency_providers_.find(feature_type); 374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (provider == dependency_providers_.end()) 375c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return NULL; 3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) Feature* feature = provider->second->GetFeature(feature_name); 378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) // Try getting the feature for the parent API, if this was a child. 379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (!feature) { 380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) std::string child_name; 381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) feature = provider->second->GetFeature( 382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) GetAPINameFromFullName(feature_name, &child_name)); 383c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return feature; 3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name, 3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string* child_name) { 3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string api_name_candidate = full_name; 3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) while (true) { 391c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (schemas_.find(api_name_candidate) != schemas_.end() || 3927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles) GeneratedSchemas::IsGenerated(api_name_candidate) || 3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) { 3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::string result = api_name_candidate; 3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (child_name) { 3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (result.length() < full_name.length()) 3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *child_name = full_name.substr(result.length() + 1); 3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else 4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *child_name = ""; 4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return result; 4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) size_t last_dot_index = api_name_candidate.rfind('.'); 4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (last_dot_index == std::string::npos) 4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) api_name_candidate = api_name_candidate.substr(0, last_dot_index); 4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *child_name = ""; 414c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return std::string(); 4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace extensions 418