Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / extensions / common / manifest_handlers / requirements_info.cc
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.
4
5 #include "extensions/common/manifest_handlers/requirements_info.h"
6
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"
13
14 namespace extensions {
15
16 namespace keys = manifest_keys;
17 namespace errors = manifest_errors;
18
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();
28 }
29
30 RequirementsInfo::~RequirementsInfo() {
31 }
32
33 // static
34 const RequirementsInfo& RequirementsInfo::GetRequirements(
35     const Extension* extension) {
36   RequirementsInfo* info = static_cast<RequirementsInfo*>(
37       extension->GetManifestData(keys::kRequirements));
38
39   // We should be guaranteed to have requirements, since they are parsed for all
40   // extension types.
41   CHECK(info);
42   return *info;
43 }
44
45 RequirementsHandler::RequirementsHandler() {
46 }
47
48 RequirementsHandler::~RequirementsHandler() {
49 }
50
51 const std::vector<std::string> RequirementsHandler::PrerequisiteKeys() const {
52   return SingleKey(keys::kPlugins);
53 }
54
55 const std::vector<std::string> RequirementsHandler::Keys() const {
56   return SingleKey(keys::kRequirements);
57 }
58
59 bool RequirementsHandler::AlwaysParseForType(Manifest::Type type) const {
60   return true;
61 }
62
63 bool RequirementsHandler::Parse(Extension* extension, base::string16* error) {
64   scoped_ptr<RequirementsInfo> requirements(
65       new RequirementsInfo(extension->manifest()));
66
67   if (!extension->manifest()->HasKey(keys::kRequirements)) {
68     extension->SetManifestData(keys::kRequirements, requirements.release());
69     return true;
70   }
71
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;
77   }
78
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;
87     }
88
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;
97         }
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;
104         }
105       }
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;
114       }
115
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;
129           }
130         }
131       }
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;
140         }
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;
147         }
148       }
149     } else {
150       *error = base::ASCIIToUTF16(errors::kInvalidRequirements);
151       return false;
152     }
153   }
154
155   extension->SetManifestData(keys::kRequirements, requirements.release());
156   return true;
157 }
158
159 }  // namespace extensions