1// Copyright 2014 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/features/chrome_channel_feature_filter.h"
6
7#include <map>
8#include <string>
9
10#include "base/lazy_instance.h"
11#include "base/strings/stringprintf.h"
12#include "chrome/common/extensions/features/feature_channel.h"
13#include "extensions/common/features/simple_feature.h"
14
15namespace extensions {
16
17namespace {
18
19static const char kFeatureChannelKey[] = "channel";
20
21struct Mappings {
22  Mappings() {
23    channels["trunk"] = chrome::VersionInfo::CHANNEL_UNKNOWN;
24    channels["canary"] = chrome::VersionInfo::CHANNEL_CANARY;
25    channels["dev"] = chrome::VersionInfo::CHANNEL_DEV;
26    channels["beta"] = chrome::VersionInfo::CHANNEL_BETA;
27    channels["stable"] = chrome::VersionInfo::CHANNEL_STABLE;
28  }
29
30  std::map<std::string, chrome::VersionInfo::Channel> channels;
31};
32
33base::LazyInstance<Mappings> g_mappings = LAZY_INSTANCE_INITIALIZER;
34
35std::string GetChannelName(chrome::VersionInfo::Channel channel) {
36  typedef std::map<std::string, chrome::VersionInfo::Channel> ChannelsMap;
37  ChannelsMap channels = g_mappings.Get().channels;
38  for (ChannelsMap::iterator i = channels.begin(); i != channels.end(); ++i) {
39    if (i->second == channel)
40      return i->first;
41  }
42  NOTREACHED();
43  return "unknown";
44}
45
46chrome::VersionInfo::Channel GetChannelValue(const std::string& name) {
47  typedef std::map<std::string, chrome::VersionInfo::Channel> ChannelsMap;
48  ChannelsMap channels = g_mappings.Get().channels;
49  ChannelsMap::const_iterator iter = channels.find(name);
50  CHECK(iter != channels.end());
51  return iter->second;
52}
53
54}  // namespace
55
56ChromeChannelFeatureFilter::ChromeChannelFeatureFilter(SimpleFeature* feature)
57    : SimpleFeatureFilter(feature),
58      channel_has_been_set_(false),
59      channel_(chrome::VersionInfo::CHANNEL_UNKNOWN) {
60}
61
62ChromeChannelFeatureFilter::~ChromeChannelFeatureFilter() {}
63
64std::string ChromeChannelFeatureFilter::Parse(
65    const base::DictionaryValue* value) {
66  std::string channel_name;
67  if (value->GetString(kFeatureChannelKey, &channel_name)) {
68    channel_ = GetChannelValue(channel_name);
69  }
70
71  // The "trunk" channel uses VersionInfo::CHANNEL_UNKNOWN, so we need to keep
72  // track of whether the channel has been set or not separately.
73  channel_has_been_set_ |= value->HasKey(kFeatureChannelKey);
74
75  if (!channel_has_been_set_ && !feature()->HasDependencies()) {
76    return feature()->name() +
77           ": Must supply a value for channel or dependencies.";
78  }
79
80  return std::string();
81}
82
83Feature::Availability ChromeChannelFeatureFilter::IsAvailableToManifest(
84    const std::string& extension_id,
85    Manifest::Type type,
86    Manifest::Location location,
87    int manifest_version,
88    Feature::Platform platfortm) const {
89  if (channel_has_been_set_ && channel_ < GetCurrentChannel()) {
90    return Feature::CreateAvailability(
91        Feature::UNSUPPORTED_CHANNEL,
92        base::StringPrintf(
93            "'%s' requires Google Chrome %s channel or newer, but this is the "
94            "%s channel.",
95            feature()->name().c_str(),
96            GetChannelName(channel_).c_str(),
97            GetChannelName(GetCurrentChannel()).c_str()));
98  }
99  return Feature::CreateAvailability(Feature::IS_AVAILABLE, std::string());
100}
101
102}  // namespace extensions
103