Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / extensions / common / manifest_handlers / requirements_info.cc
blob9a2a22b92aaf39ddfb247ecbd48aa2754b749178
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "extensions/common/manifest_handlers/requirements_info.h"
7 #include "base/lazy_instance.h"
8 #include "base/memory/scoped_ptr.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "base/values.h"
11 #include "extensions/common/error_utils.h"
12 #include "extensions/common/manifest_constants.h"
14 namespace extensions {
16 namespace keys = manifest_keys;
17 namespace errors = manifest_errors;
19 RequirementsInfo::RequirementsInfo(const Manifest* manifest)
20 : webgl(false),
21 npapi(false),
22 window_shape(false) {
23 // Before parsing requirements from the manifest, automatically default the
24 // NPAPI plugin requirement based on whether it includes NPAPI plugins.
25 const base::ListValue* list_value = NULL;
26 npapi = manifest->GetList(keys::kPlugins, &list_value) &&
27 !list_value->empty();
30 RequirementsInfo::~RequirementsInfo() {
33 // static
34 const RequirementsInfo& RequirementsInfo::GetRequirements(
35 const Extension* extension) {
36 RequirementsInfo* info = static_cast<RequirementsInfo*>(
37 extension->GetManifestData(keys::kRequirements));
39 // We should be guaranteed to have requirements, since they are parsed for all
40 // extension types.
41 CHECK(info);
42 return *info;
45 RequirementsHandler::RequirementsHandler() {
48 RequirementsHandler::~RequirementsHandler() {
51 const std::vector<std::string> RequirementsHandler::PrerequisiteKeys() const {
52 return SingleKey(keys::kPlugins);
55 const std::vector<std::string> RequirementsHandler::Keys() const {
56 return SingleKey(keys::kRequirements);
59 bool RequirementsHandler::AlwaysParseForType(Manifest::Type type) const {
60 return true;
63 bool RequirementsHandler::Parse(Extension* extension, base::string16* error) {
64 scoped_ptr<RequirementsInfo> requirements(
65 new RequirementsInfo(extension->manifest()));
67 if (!extension->manifest()->HasKey(keys::kRequirements)) {
68 extension->SetManifestData(keys::kRequirements, requirements.release());
69 return true;
72 const base::DictionaryValue* requirements_value = NULL;
73 if (!extension->manifest()->GetDictionary(keys::kRequirements,
74 &requirements_value)) {
75 *error = base::ASCIIToUTF16(errors::kInvalidRequirements);
76 return false;
79 for (base::DictionaryValue::Iterator iter(*requirements_value);
80 !iter.IsAtEnd();
81 iter.Advance()) {
82 const base::DictionaryValue* requirement_value;
83 if (!iter.value().GetAsDictionary(&requirement_value)) {
84 *error = ErrorUtils::FormatErrorMessageUTF16(
85 errors::kInvalidRequirement, iter.key());
86 return false;
89 if (iter.key() == "plugins") {
90 for (base::DictionaryValue::Iterator plugin_iter(*requirement_value);
91 !plugin_iter.IsAtEnd(); plugin_iter.Advance()) {
92 bool plugin_required = false;
93 if (!plugin_iter.value().GetAsBoolean(&plugin_required)) {
94 *error = ErrorUtils::FormatErrorMessageUTF16(
95 errors::kInvalidRequirement, iter.key());
96 return false;
98 if (plugin_iter.key() == "npapi") {
99 requirements->npapi = plugin_required;
100 } else {
101 *error = ErrorUtils::FormatErrorMessageUTF16(
102 errors::kInvalidRequirement, iter.key());
103 return false;
106 } else if (iter.key() == "3D") {
107 const base::ListValue* features = NULL;
108 if (!requirement_value->GetListWithoutPathExpansion("features",
109 &features) ||
110 !features) {
111 *error = ErrorUtils::FormatErrorMessageUTF16(
112 errors::kInvalidRequirement, iter.key());
113 return false;
116 for (base::ListValue::const_iterator feature_iter = features->begin();
117 feature_iter != features->end(); ++feature_iter) {
118 std::string feature;
119 if ((*feature_iter)->GetAsString(&feature)) {
120 if (feature == "webgl") {
121 requirements->webgl = true;
122 } else if (feature == "css3d") {
123 // css3d is always available, so no check is needed, but no error is
124 // generated.
125 } else {
126 *error = ErrorUtils::FormatErrorMessageUTF16(
127 errors::kInvalidRequirement, iter.key());
128 return false;
132 } else if (iter.key() == "window") {
133 for (base::DictionaryValue::Iterator feature_iter(*requirement_value);
134 !feature_iter.IsAtEnd(); feature_iter.Advance()) {
135 bool feature_required = false;
136 if (!feature_iter.value().GetAsBoolean(&feature_required)) {
137 *error = ErrorUtils::FormatErrorMessageUTF16(
138 errors::kInvalidRequirement, iter.key());
139 return false;
141 if (feature_iter.key() == "shape") {
142 requirements->window_shape = feature_required;
143 } else {
144 *error = ErrorUtils::FormatErrorMessageUTF16(
145 errors::kInvalidRequirement, iter.key());
146 return false;
149 } else {
150 *error = base::ASCIIToUTF16(errors::kInvalidRequirements);
151 return false;
155 extension->SetManifestData(keys::kRequirements, requirements.release());
156 return true;
159 } // namespace extensions