This source file includes following definitions.
- GetLocationRank
- GetHigherPriorityLocation
- type_
- ValidateManifest
- HasKey
- HasPath
- Get
- GetBoolean
- GetInteger
- GetString
- GetString
- GetDictionary
- GetList
- DeepCopy
- Equals
- GetManifestVersion
- CanAccessPath
- CanAccessKey
#include "extensions/common/manifest.h"
#include "base/basictypes.h"
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/strings/string_split.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "extensions/common/error_utils.h"
#include "extensions/common/features/feature.h"
#include "extensions/common/features/feature_provider.h"
#include "extensions/common/install_warning.h"
#include "extensions/common/manifest_constants.h"
namespace extensions {
namespace keys = manifest_keys;
namespace {
int GetLocationRank(Manifest::Location location) {
const int kInvalidRank = -1;
int rank = kInvalidRank;
switch (location) {
case Manifest::COMPONENT:
rank = 9;
break;
case Manifest::EXTERNAL_COMPONENT:
rank = 8;
break;
case Manifest::EXTERNAL_POLICY:
rank = 7;
break;
case Manifest::EXTERNAL_POLICY_DOWNLOAD:
rank = 6;
break;
case Manifest::COMMAND_LINE:
rank = 5;
break;
case Manifest::UNPACKED:
rank = 4;
break;
case Manifest::EXTERNAL_REGISTRY:
rank = 3;
break;
case Manifest::EXTERNAL_PREF:
rank = 2;
break;
case Manifest::EXTERNAL_PREF_DOWNLOAD:
rank = 1;
break;
case Manifest::INTERNAL:
rank = 0;
break;
default:
NOTREACHED() << "Need to add new extension location " << location;
}
CHECK(rank != kInvalidRank);
return rank;
}
}
Manifest::Location Manifest::GetHigherPriorityLocation(
Location loc1, Location loc2) {
if (loc1 == loc2)
return loc1;
int loc1_rank = GetLocationRank(loc1);
int loc2_rank = GetLocationRank(loc2);
CHECK(loc1_rank != loc2_rank);
return (loc1_rank > loc2_rank ? loc1 : loc2 );
}
Manifest::Manifest(Location location, scoped_ptr<base::DictionaryValue> value)
: location_(location),
value_(value.Pass()),
type_(TYPE_UNKNOWN) {
if (value_->HasKey(keys::kTheme)) {
type_ = TYPE_THEME;
} else if (value_->HasKey(keys::kExport)) {
type_ = TYPE_SHARED_MODULE;
} else if (value_->HasKey(keys::kApp)) {
if (value_->Get(keys::kWebURLs, NULL) ||
value_->Get(keys::kLaunchWebURL, NULL)) {
type_ = TYPE_HOSTED_APP;
} else if (value_->Get(keys::kPlatformAppBackground, NULL) ||
value_->Get(keys::kPlatformAppServiceWorker, NULL)) {
type_ = TYPE_PLATFORM_APP;
} else {
type_ = TYPE_LEGACY_PACKAGED_APP;
}
} else {
type_ = TYPE_EXTENSION;
}
CHECK_NE(type_, TYPE_UNKNOWN);
}
Manifest::~Manifest() {
}
bool Manifest::ValidateManifest(
std::string* error,
std::vector<InstallWarning>* warnings) const {
*error = "";
FeatureProvider* manifest_feature_provider =
FeatureProvider::GetManifestFeatures();
const std::vector<std::string>& feature_names =
manifest_feature_provider->GetAllFeatureNames();
for (std::vector<std::string>::const_iterator feature_name =
feature_names.begin();
feature_name != feature_names.end(); ++feature_name) {
if (!value_->Get(*feature_name, NULL))
continue;
Feature* feature = manifest_feature_provider->GetFeature(*feature_name);
Feature::Availability result = feature->IsAvailableToManifest(
extension_id_, type_, Feature::ConvertLocation(location_),
GetManifestVersion());
if (!result.is_available())
warnings->push_back(InstallWarning(result.message(), *feature_name));
}
for (base::DictionaryValue::Iterator it(*value_); !it.IsAtEnd();
it.Advance()) {
if (!manifest_feature_provider->GetFeature(it.key())) {
warnings->push_back(InstallWarning(
ErrorUtils::FormatErrorMessage(
manifest_errors::kUnrecognizedManifestKey, it.key()),
it.key()));
}
}
return true;
}
bool Manifest::HasKey(const std::string& key) const {
return CanAccessKey(key) && value_->HasKey(key);
}
bool Manifest::HasPath(const std::string& path) const {
base::Value* ignored = NULL;
return CanAccessPath(path) && value_->Get(path, &ignored);
}
bool Manifest::Get(
const std::string& path, const base::Value** out_value) const {
return CanAccessPath(path) && value_->Get(path, out_value);
}
bool Manifest::GetBoolean(
const std::string& path, bool* out_value) const {
return CanAccessPath(path) && value_->GetBoolean(path, out_value);
}
bool Manifest::GetInteger(
const std::string& path, int* out_value) const {
return CanAccessPath(path) && value_->GetInteger(path, out_value);
}
bool Manifest::GetString(
const std::string& path, std::string* out_value) const {
return CanAccessPath(path) && value_->GetString(path, out_value);
}
bool Manifest::GetString(
const std::string& path, base::string16* out_value) const {
return CanAccessPath(path) && value_->GetString(path, out_value);
}
bool Manifest::GetDictionary(
const std::string& path, const base::DictionaryValue** out_value) const {
return CanAccessPath(path) && value_->GetDictionary(path, out_value);
}
bool Manifest::GetList(
const std::string& path, const base::ListValue** out_value) const {
return CanAccessPath(path) && value_->GetList(path, out_value);
}
Manifest* Manifest::DeepCopy() const {
Manifest* manifest = new Manifest(
location_, scoped_ptr<base::DictionaryValue>(value_->DeepCopy()));
manifest->set_extension_id(extension_id_);
return manifest;
}
bool Manifest::Equals(const Manifest* other) const {
return other && value_->Equals(other->value());
}
int Manifest::GetManifestVersion() const {
int manifest_version = type_ == TYPE_PLATFORM_APP ? 2 : 1;
value_->GetInteger(keys::kManifestVersion, &manifest_version);
return manifest_version;
}
bool Manifest::CanAccessPath(const std::string& path) const {
std::vector<std::string> components;
base::SplitString(path, '.', &components);
std::string key;
for (size_t i = 0; i < components.size(); ++i) {
key += components[i];
if (!CanAccessKey(key))
return false;
key += '.';
}
return true;
}
bool Manifest::CanAccessKey(const std::string& key) const {
Feature* feature = FeatureProvider::GetManifestFeatures()->GetFeature(key);
if (!feature)
return true;
return feature->IsAvailableToManifest(
extension_id_, type_, Feature::ConvertLocation(location_),
GetManifestVersion()).is_available();
}
}