blob: 101da61628e7431b71441de97fd066c2230a8ce8 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef FEATURED_SERVICE_H_
#define FEATURED_SERVICE_H_
#include "dbus/exported_object.h"
#include <dbus/object_path.h>
#include <chromeos/dbus/service_constants.h>
#include <base/command_line.h>
#include <base/files/file_util.h>
#include <base/values.h>
#include <brillo/dbus/exported_object_manager.h>
#include <brillo/dbus/exported_property_set.h>
#include <brillo/dbus/dbus_method_response.h>
#include <brillo/errors/error.h>
#include <brillo/syslog_logging.h>
#include <brillo/variant_dictionary.h>
#include <featured/feature_library.h>
#include <memory>
#include <string>
#include <unordered_map>
#include <optional>
#include <utility>
#include <vector>
namespace featured {
class FeatureCommand {
public:
explicit FeatureCommand(const std::string& name) : name_(name) {}
FeatureCommand(FeatureCommand&& other) = default;
// virtual destructor is required because we create a unique pointer
// of an abstract class. See PlatformFeature class definition.
virtual ~FeatureCommand() = default;
std::string name() { return name_; }
virtual bool Execute() = 0;
private:
std::string name_;
};
class WriteFileCommand : public FeatureCommand {
public:
WriteFileCommand(const std::string& file_name, const std::string& value);
WriteFileCommand(WriteFileCommand&& other) = default;
bool Execute() override;
private:
std::string file_name_;
std::string value_;
};
class MkdirCommand : public FeatureCommand {
public:
explicit MkdirCommand(const std::string& path);
MkdirCommand(MkdirCommand&& other) = default;
bool Execute() override;
private:
base::FilePath path_;
};
class FileExistsCommand : public FeatureCommand {
public:
explicit FileExistsCommand(const std::string& file_name);
FileExistsCommand(FileExistsCommand&& other) = default;
bool Execute() override;
private:
std::string file_name_;
};
class FileNotExistsCommand : public FeatureCommand {
public:
explicit FileNotExistsCommand(const std::string& file_name);
FileNotExistsCommand(FileNotExistsCommand&& other) = default;
bool Execute() override;
private:
std::string file_name_;
};
class AlwaysSupportedCommand : public FeatureCommand {
public:
AlwaysSupportedCommand() : FeatureCommand("AlwaysSupported") {}
AlwaysSupportedCommand(AlwaysSupportedCommand&& other) = default;
bool Execute() override { return true; }
};
class PlatformFeature {
public:
PlatformFeature(const std::string& name,
std::vector<std::unique_ptr<FeatureCommand>>&& query_cmds,
std::vector<std::unique_ptr<FeatureCommand>>&& feature_cmds)
: exec_cmds_(std::move(feature_cmds)),
support_check_cmds_(std::move(query_cmds)),
name_(std::make_unique<std::string>(name)),
feature_{name_->c_str(), FEATURE_DISABLED_BY_DEFAULT} {}
PlatformFeature(PlatformFeature&& other) = default;
PlatformFeature(const PlatformFeature& other) = delete;
PlatformFeature& operator=(const PlatformFeature& other) = delete;
const std::string& name() const { return *name_; }
// Don't copy this because address must *not* change across lookups.
const VariationsFeature* const feature() const { return &feature_; }
// Check if feature is supported on the device
bool IsSupported() const;
// Execute a sequence of commands to enable a feature
bool Execute() const;
private:
std::vector<std::unique_ptr<FeatureCommand>> exec_cmds_;
std::vector<std::unique_ptr<FeatureCommand>> support_check_cmds_;
// The string in this unique_ptr must not be modified since feature_ contains
// a pointer to the underlying c_str().
std::unique_ptr<const std::string> name_;
VariationsFeature feature_;
};
class FeatureParserBase {
public:
using FeatureMap = std::unordered_map<std::string, PlatformFeature>;
virtual bool ParseFileContents(const std::string& file_contents) = 0;
virtual ~FeatureParserBase() = default;
bool AreFeaturesParsed() const { return features_parsed_; }
const FeatureMap* GetFeatureMap() { return &feature_map_; }
protected:
std::unordered_map<std::string, PlatformFeature> feature_map_;
// Parse features only once per object
bool features_parsed_ = false;
};
class JsonFeatureParser : public FeatureParserBase {
public:
// Implements the meat of the JSON parsing functionality given a JSON blob
bool ParseFileContents(const std::string& file_contents) override;
private:
// Helper to build a PlatformFeature object by parsing a JSON feature object
std::optional<PlatformFeature> MakeFeatureObject(
const base::Value& feature_obj);
};
class DbusFeaturedService {
public:
DbusFeaturedService() : parser_(std::make_unique<JsonFeatureParser>()) {}
DbusFeaturedService(const DbusFeaturedService&) = delete;
DbusFeaturedService& operator=(const DbusFeaturedService&) = delete;
~DbusFeaturedService() = default;
bool Start(dbus::Bus* bus, std::shared_ptr<DbusFeaturedService> ptr);
private:
// Helpers to invoke a feature parser
bool ParseFeatureList();
// Enable all features that are supported and which Chrome tells us should be
// enabled.
bool EnableFeatures();
// Wraps IsPlatformFeatureEnabled, providing the interface that dbus expects
void IsPlatformFeatureEnabledWrap(
dbus::MethodCall* method_call,
dbus::ExportedObject::ResponseSender sender);
bool IsPlatformFeatureEnabled(const std::string& name);
std::unique_ptr<FeatureParserBase> parser_;
std::unique_ptr<feature::PlatformFeatures> library_;
};
} // namespace featured
#endif // FEATURED_SERVICE_H_