// Copyright (c) 2012 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.

#ifndef CHROME_BROWSER_ABOUT_FLAGS_H_
#define CHROME_BROWSER_ABOUT_FLAGS_H_

#include <stdint.h>

#include <map>
#include <set>
#include <string>

#include "base/command_line.h"
#include "base/metrics/histogram_base.h"
#include "base/strings/string16.h"

class PrefService;

namespace base {
class ListValue;
}

namespace about_flags {

class FlagsStorage;

// This value is reported as switch histogram ID if switch name has unknown
// format.
extern const base::HistogramBase::Sample kBadSwitchFormatHistogramId;

// Enumeration of OSs.
// This is exposed only for testing.
enum { kOsMac = 1 << 0, kOsWin = 1 << 1, kOsLinux = 1 << 2 , kOsCrOS = 1 << 3,
       kOsAndroid = 1 << 4, kOsCrOSOwnerOnly = 1 << 5 };

// Experiment is used internally by about_flags to describe an experiment (and
// for testing).
// This is exposed only for testing.
struct Experiment {
  enum Type {
    // An experiment with a single value. This is typically what you want.
    SINGLE_VALUE,

    // The experiment has multiple values only one of which is ever enabled.
    // The first of the values should correspond to a deactivated state for this
    // lab (i.e. no command line option). For MULTI_VALUE experiments the
    // command_line of the Experiment is not used. If the experiment is enabled
    // the command line of the selected Choice is enabled.
    MULTI_VALUE,

    // The experiment has three possible values: Default, Enabled and Disabled.
    // This should be used for experiments that may have their own logic to
    // decide if the feature should be on when not explicitly specified via
    // about flags - for example via FieldTrials.
    ENABLE_DISABLE_VALUE,
  };

  // Used for MULTI_VALUE types to describe one of the possible values the user
  // can select.
  struct Choice {
    // ID of the message containing the choice name.
    int description_id;

    // Command line switch and value to enabled for this choice.
    const char* command_line_switch;
    // Simple switches that have no value should use "" for command_line_value.
    const char* command_line_value;
  };

  // The internal name of the experiment. This is never shown to the user.
  // It _is_ however stored in the prefs file, so you shouldn't change the
  // name of existing flags.
  const char* internal_name;

  // String id of the message containing the experiment's name.
  int visible_name_id;

  // String id of the message containing the experiment's description.
  int visible_description_id;

  // The platforms the experiment is available on
  // Needs to be more than a compile-time #ifdef because of profile sync.
  unsigned supported_platforms;  // bitmask

  // Type of experiment.
  Type type;

  // The commandline switch and value that are added when this flag is active.
  // This is different from |internal_name| so that the commandline flag can be
  // renamed without breaking the prefs file.
  // This is used if type is SINGLE_VALUE or ENABLE_DISABLE_VALUE.
  const char* command_line_switch;
  // Simple switches that have no value should use "" for command_line_value.
  const char* command_line_value;

  // For ENABLE_DISABLE_VALUE, the command line switch and value to explictly
  // disable the feature.
  const char* disable_command_line_switch;
  const char* disable_command_line_value;

  // This is used if type is MULTI_VALUE.
  const Choice* choices;

  // Number of |choices|.
  // This is used if type is MULTI_VALUE.
  int num_choices;

  // Returns the name used in prefs for the choice at the specified |index|.
  std::string NameForChoice(int index) const;

  // Returns the human readable description for the choice at |index|.
  base::string16 DescriptionForChoice(int index) const;
};

// A flag controlling the behavior of the |ConvertFlagsToSwitches| function -
// whether it should add the sentinel switches around flags.
enum SentinelsMode { kNoSentinels, kAddSentinels };

// Reads the Labs |prefs| (called "Labs" for historical reasons) and adds the
// commandline flags belonging to the active experiments to |command_line|.
void ConvertFlagsToSwitches(FlagsStorage* flags_storage,
                            base::CommandLine* command_line,
                            SentinelsMode sentinels);

// Compares a set of switches of the two provided command line objects and
// returns true if they are the same and false otherwise.
// If |out_difference| is not NULL, it's filled with set_symmetric_difference
// between sets.
bool AreSwitchesIdenticalToCurrentCommandLine(
    const base::CommandLine& new_cmdline,
    const base::CommandLine& active_cmdline,
    std::set<CommandLine::StringType>* out_difference);

// Differentiate between generic flags available on a per session base and flags
// that influence the whole machine and can be said by the admin only. This flag
// is relevant for ChromeOS for now only and dictates whether entries marked
// with the |kOsCrOSOwnerOnly| label should be enabled in the UI or not.
enum FlagAccess { kGeneralAccessFlagsOnly, kOwnerAccessToFlags };

// Get the list of experiments. Experiments that are available on the current
// platform are appended to |supported_experiments|; all other experiments are
// appended to |unsupported_experiments|.
void GetFlagsExperimentsData(FlagsStorage* flags_storage,
                             FlagAccess access,
                             base::ListValue* supported_experiments,
                             base::ListValue* unsupported_experiments);

// Returns true if one of the experiment flags has been flipped since startup.
bool IsRestartNeededToCommitChanges();

// Enables or disables the experiment with id |internal_name|.
void SetExperimentEnabled(FlagsStorage* flags_storage,
                          const std::string& internal_name,
                          bool enable);

// Removes all switches that were added to a command line by a previous call to
// |ConvertFlagsToSwitches()|.
void RemoveFlagsSwitches(
    std::map<std::string, base::CommandLine::StringType>* switch_list);

// Reset all flags to the default state by clearing all flags.
void ResetAllFlags(FlagsStorage* flags_storage);

// Returns the value for the current platform. This is one of the values defined
// by the OS enum above.
// This is exposed only for testing.
int GetCurrentPlatform();

// Sends UMA stats about experimental flag usage. This should be called once per
// startup.
void RecordUMAStatistics(FlagsStorage* flags_storage);

// Returns the UMA id for the specified switch name.
base::HistogramBase::Sample GetSwitchUMAId(const std::string& switch_name);

// Sends stats (as UMA histogram) about command_line_difference.
// This is used on ChromeOS to report flags that lead to browser restart.
// |command_line_difference| is the result of
// AreSwitchesIdenticalToCurrentCommandLine().
void ReportCustomFlags(const std::string& uma_histogram_hame,
                       const std::set<std::string>& command_line_difference);

namespace testing {

// Clears internal global state, for unit tests.
void ClearState();

// Sets the list of experiments. Pass in NULL to use the default set. This does
// NOT take ownership of the supplied Experiments.
void SetExperiments(const Experiment* e, size_t count);

// Returns the current set of experiments.
const Experiment* GetExperiments(size_t* count);

// Separator used for multi values. Multi values are represented in prefs as
// name-of-experiment + kMultiSeparator + selected_index.
extern const char kMultiSeparator[];

}  // namespace testing

}  // namespace about_flags

#endif  // CHROME_BROWSER_ABOUT_FLAGS_H_
