普通文本  |  142行  |  4.51 KB

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "extensions/common/manifest_handlers/requirements_info.h"

#include "base/lazy_instance.h"
#include "base/memory/scoped_ptr.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/manifest_constants.h"

namespace extensions {

namespace keys = manifest_keys;
namespace errors = manifest_errors;

RequirementsInfo::RequirementsInfo(const Manifest* manifest)
    : webgl(false),
      css3d(false),
      npapi(false) {
  // Before parsing requirements from the manifest, automatically default the
  // NPAPI plugin requirement based on whether it includes NPAPI plugins.
  const base::ListValue* list_value = NULL;
  npapi = manifest->GetList(keys::kPlugins, &list_value) &&
          !list_value->empty();
}

RequirementsInfo::~RequirementsInfo() {
}

// static
const RequirementsInfo& RequirementsInfo::GetRequirements(
    const Extension* extension) {
  RequirementsInfo* info = static_cast<RequirementsInfo*>(
      extension->GetManifestData(keys::kRequirements));

  // We should be guaranteed to have requirements, since they are parsed for all
  // extension types.
  CHECK(info);
  return *info;
}

RequirementsHandler::RequirementsHandler() {
}

RequirementsHandler::~RequirementsHandler() {
}

const std::vector<std::string> RequirementsHandler::PrerequisiteKeys() const {
  return SingleKey(keys::kPlugins);
}

const std::vector<std::string> RequirementsHandler::Keys() const {
  return SingleKey(keys::kRequirements);
}

bool RequirementsHandler::AlwaysParseForType(Manifest::Type type) const {
  return true;
}

bool RequirementsHandler::Parse(Extension* extension, string16* error) {
  scoped_ptr<RequirementsInfo> requirements(
      new RequirementsInfo(extension->manifest()));

  if (!extension->manifest()->HasKey(keys::kRequirements)) {
    extension->SetManifestData(keys::kRequirements, requirements.release());
    return true;
  }

  const base::DictionaryValue* requirements_value = NULL;
  if (!extension->manifest()->GetDictionary(keys::kRequirements,
                                            &requirements_value)) {
    *error = ASCIIToUTF16(errors::kInvalidRequirements);
    return false;
  }

  for (base::DictionaryValue::Iterator iter(*requirements_value);
       !iter.IsAtEnd();
       iter.Advance()) {
    const base::DictionaryValue* requirement_value;
    if (!iter.value().GetAsDictionary(&requirement_value)) {
      *error = ErrorUtils::FormatErrorMessageUTF16(
          errors::kInvalidRequirement, iter.key());
      return false;
    }

    if (iter.key() == "plugins") {
      for (base::DictionaryValue::Iterator plugin_iter(*requirement_value);
           !plugin_iter.IsAtEnd(); plugin_iter.Advance()) {
        bool plugin_required = false;
        if (!plugin_iter.value().GetAsBoolean(&plugin_required)) {
          *error = ErrorUtils::FormatErrorMessageUTF16(
              errors::kInvalidRequirement, iter.key());
          return false;
        }
        if (plugin_iter.key() == "npapi") {
          requirements->npapi = plugin_required;
        } else {
          *error = ErrorUtils::FormatErrorMessageUTF16(
              errors::kInvalidRequirement, iter.key());
          return false;
        }
      }
    } else if (iter.key() == "3D") {
      const base::ListValue* features = NULL;
      if (!requirement_value->GetListWithoutPathExpansion("features",
                                                          &features) ||
          !features) {
        *error = ErrorUtils::FormatErrorMessageUTF16(
            errors::kInvalidRequirement, iter.key());
        return false;
      }

      for (base::ListValue::const_iterator feature_iter = features->begin();
           feature_iter != features->end(); ++feature_iter) {
        std::string feature;
        if ((*feature_iter)->GetAsString(&feature)) {
          if (feature == "webgl") {
            requirements->webgl = true;
          } else if (feature == "css3d") {
            requirements->css3d = true;
          } else {
            *error = ErrorUtils::FormatErrorMessageUTF16(
                errors::kInvalidRequirement, iter.key());
            return false;
          }
        }
      }
    } else {
      *error = ASCIIToUTF16(errors::kInvalidRequirements);
      return false;
    }
  }

  extension->SetManifestData(keys::kRequirements, requirements.release());
  return true;
}

}  // namespace extensions