extension_api.cc revision 0f1bc08d4cfcc34181b0b5cbf065c40f687bf740
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"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/extensions/extension.h"
21b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)#include "chrome/common/extensions/permissions/permissions_data.h"
223551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)#include "extensions/common/features/feature.h"
23ba5b9a6411cb1792fd21f0a078d7a25cd1ceec16Ben Murdoch#include "extensions/common/features/feature_provider.h"
241e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "extensions/common/permissions/permission_set.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("fileBrowserPrivate",
2457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IDR_EXTENSION_API_JSON_FILEBROWSERPRIVATE);
2467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("inputMethodPrivate",
2477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IDR_EXTENSION_API_JSON_INPUTMETHODPRIVATE);
2487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("pageAction", IDR_EXTENSION_API_JSON_PAGEACTION);
2497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("pageActions", IDR_EXTENSION_API_JSON_PAGEACTIONS);
2507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("privacy", IDR_EXTENSION_API_JSON_PRIVACY);
2513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  RegisterSchemaResource("processes", IDR_EXTENSION_API_JSON_PROCESSES);
2527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("proxy", IDR_EXTENSION_API_JSON_PROXY);
2537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("scriptBadge", IDR_EXTENSION_API_JSON_SCRIPTBADGE);
2547d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("streamsPrivate",
2557d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IDR_EXTENSION_API_JSON_STREAMSPRIVATE);
2567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("ttsEngine", IDR_EXTENSION_API_JSON_TTSENGINE);
2577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("tts", IDR_EXTENSION_API_JSON_TTS);
2587d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("types", IDR_EXTENSION_API_JSON_TYPES);
2597dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch  RegisterSchemaResource("types.private", IDR_EXTENSION_API_JSON_TYPES_PRIVATE);
2607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("webRequestInternal",
2617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IDR_EXTENSION_API_JSON_WEBREQUESTINTERNAL);
2627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("webstore", IDR_EXTENSION_API_JSON_WEBSTORE);
2637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  RegisterSchemaResource("webstorePrivate",
2647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      IDR_EXTENSION_API_JSON_WEBSTOREPRIVATE);
2657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  default_configuration_initialized_ = true;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)void ExtensionAPI::RegisterSchemaResource(const std::string& name,
2697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                                          int resource_id) {
2707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  unloaded_schemas_[name] = resource_id;
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ExtensionAPI::RegisterDependencyProvider(const std::string& name,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                              FeatureProvider* provider) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  dependency_providers_[name] = provider;
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
278b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)bool ExtensionAPI::IsAnyFeatureAvailableToContext(const std::string& api_name,
2793551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)                                                  const Extension* extension,
280b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                  Feature::Context context,
281b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)                                                  const GURL& url) {
282b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  FeatureProviderMap::iterator provider = dependency_providers_.find("api");
283b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  CHECK(provider != dependency_providers_.end());
2847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const std::vector<std::string>& features =
2857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      provider->second->GetAllFeatureNames();
286b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
287b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // Check to see if there are any parts of this API that are allowed in this
288b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  // context.
2897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  for (std::vector<std::string>::const_iterator i = features.begin();
290b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)       i != features.end(); ++i) {
291b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    const std::string& feature_name = *i;
292b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    if (feature_name != api_name && feature_name.find(api_name + ".") == 0) {
2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      if (IsAvailable(feature_name, extension, context, url).is_available())
294b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)        return true;
295b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)    }
296b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)  }
2973551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)  return IsAvailable(api_name, extension, context, url).is_available();
298b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)}
299b2df76ea8fec9e32f6f3718986dba0d95315b29cTorne (Richard Coles)
3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)Feature::Availability ExtensionAPI::IsAvailable(const std::string& full_name,
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                const Extension* extension,
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                Feature::Context context,
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                const GURL& url) {
304c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Feature* feature = GetFeatureDependency(full_name);
3057d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK(feature) << full_name;
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
307c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Feature::Availability availability =
308c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      feature->IsAvailableToContext(extension, context, url);
309c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!availability.is_available())
310c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return availability;
311c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)
312c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  for (std::set<std::string>::iterator iter = feature->dependencies().begin();
313c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)       iter != feature->dependencies().end(); ++iter) {
314c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    Feature::Availability dependency_availability =
315c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        IsAvailable(*iter, extension, context, url);
316c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (!dependency_availability.is_available())
317c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      return dependency_availability;
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
320c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return Feature::CreateAvailability(Feature::IS_AVAILABLE, std::string());
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool ExtensionAPI::IsPrivileged(const std::string& full_name) {
324c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  Feature* feature = GetFeatureDependency(full_name);
3257d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  CHECK(feature);
3267d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  DCHECK(!feature->GetContexts()->empty());
3277d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  // An API is 'privileged' if it can only be run in a blessed context.
3287d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  return feature->GetContexts()->size() ==
3297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      feature->GetContexts()->count(Feature::BLESSED_EXTENSION_CONTEXT);
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)const base::DictionaryValue* ExtensionAPI::GetSchema(
3337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    const std::string& full_name) {
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string child_name;
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string api_name = GetAPINameFromFullName(full_name, &child_name);
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3377d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  const base::DictionaryValue* result = NULL;
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SchemaMap::iterator maybe_schema = schemas_.find(api_name);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (maybe_schema != schemas_.end()) {
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = maybe_schema->second.get();
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  } else {
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Might not have loaded yet; or might just not exist.
3437d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)   UnloadedSchemaMap::iterator maybe_schema_resource =
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unloaded_schemas_.find(api_name);
3457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (maybe_schema_resource != unloaded_schemas_.end()) {
3467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      LoadSchema(maybe_schema_resource->first,
3477d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                 ReadFromResource(maybe_schema_resource->second));
3487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    } else if (default_configuration_initialized_ &&
3497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)               GeneratedSchemas::IsGenerated(api_name)) {
3507d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      LoadSchema(api_name, GeneratedSchemas::Get(api_name));
3517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    } else {
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return NULL;
3537d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    maybe_schema = schemas_.find(api_name);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    CHECK(schemas_.end() != maybe_schema);
3575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = maybe_schema->second.get();
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!child_name.empty())
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    result = GetSchemaChild(result, child_name);
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Feature* ExtensionAPI::GetFeatureDependency(const std::string& full_name) {
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string feature_type;
3685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string feature_name;
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  SplitDependencyName(full_name, &feature_type, &feature_name);
3705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  FeatureProviderMap::iterator provider =
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      dependency_providers_.find(feature_type);
373c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (provider == dependency_providers_.end())
374c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    return NULL;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  Feature* feature = provider->second->GetFeature(feature_name);
377c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  // Try getting the feature for the parent API, if this was a child.
378c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  if (!feature) {
379c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    std::string child_name;
380c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    feature = provider->second->GetFeature(
381c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        GetAPINameFromFullName(feature_name, &child_name));
382c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  }
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return feature;
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string ExtensionAPI::GetAPINameFromFullName(const std::string& full_name,
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                                 std::string* child_name) {
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string api_name_candidate = full_name;
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (true) {
390c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    if (schemas_.find(api_name_candidate) != schemas_.end() ||
3917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        GeneratedSchemas::IsGenerated(api_name_candidate) ||
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        unloaded_schemas_.find(api_name_candidate) != unloaded_schemas_.end()) {
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      std::string result = api_name_candidate;
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (child_name) {
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if (result.length() < full_name.length())
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *child_name = full_name.substr(result.length() + 1);
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          *child_name = "";
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return result;
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t last_dot_index = api_name_candidate.rfind('.');
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (last_dot_index == std::string::npos)
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    api_name_candidate = api_name_candidate.substr(0, last_dot_index);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *child_name = "";
413c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  return std::string();
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace extensions
417