1 // Copyright (c) 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 "chrome/common/extensions/manifest_handlers/requirements_handler.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 "chrome/common/extensions/extension_manifest_constants.h" 12 #include "extensions/common/error_utils.h" 13 14 namespace keys = extension_manifest_keys; 15 namespace errors = extension_manifest_errors; 16 17 namespace extensions { 18 19 RequirementsInfo::RequirementsInfo(const Manifest* manifest) 20 : webgl(false), 21 css3d(false), 22 npapi(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, 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 = 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 requirements->css3d = true; 124 } else { 125 *error = ErrorUtils::FormatErrorMessageUTF16( 126 errors::kInvalidRequirement, iter.key()); 127 return false; 128 } 129 } 130 } 131 } else { 132 *error = ASCIIToUTF16(errors::kInvalidRequirements); 133 return false; 134 } 135 } 136 137 extension->SetManifestData(keys::kRequirements, requirements.release()); 138 return true; 139 } 140 141 } // namespace extensions 142