// 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.

syntax = "proto2";

option optimize_for = LITE_RUNTIME;

package variations;

// This defines the Protocol Buffer representation of a Chrome Variations study
// as sent to clients of the Variations server.
//
// Next tag: 13
message Study {
  // The name of the study. Should not contain spaces or special characters.
  // Ex: "my_study"
  required string name = 1;

  // DEPRECATED: Prefer end_date instead.
  // The expiry date of the study in Unix time format. (Seconds since midnight
  // January 1, 1970 UTC). See: http://en.wikipedia.org/wiki/Unix_time
  //
  // A study that has expired will be disabled, and users will be assigned
  // groups based on the default_experiment_name. This will take precedence over
  // a corresponding hardcoded field trial in the client.
  //
  // Ex: 1330893974  (corresponds to 2012-03-04 20:46:14Z)
  optional int64 expiry_date = 3;

  // Consistency setting for a study.
  enum Consistency {
    SESSION = 0;  // Can't change within a session.
    PERMANENT = 1;  // Can't change for a given user.
  }

  // Consistency setting for this study. Optional - defaults to SESSION.
  // Ex: PERMANENT
  optional Consistency consistency = 7 [default = SESSION];

  // Name of the experiment that gets the default experience. This experiment
  // must be included in the list below. If not specified, a generic default
  // experiment name is used.
  // Ex: "default"
  optional string default_experiment_name = 8;

  // An experiment within the study.
  //
  // Next tag: 14
  message Experiment {
    // A named parameter value for this experiment.
    //
    // Next tag: 3
    message Param {
      // The name of the parameter.
      optional string name = 1;

      // The value of the parameter.
      optional string value = 2;
    }

    // The name of the experiment within the study.
    // Ex: "bucketA"
    required string name = 1;

    // The cut of the total probability taken for this experiment (the x in
    // x / N, where N is the sum of all x’s).  Ex: "50"
    required uint32 probability_weight = 2;

    // Optional id used to uniquely identify this experiment for Google web
    // properties.
    optional uint64 google_web_experiment_id = 3;

    // Optional id used to allow this experiment to trigger experimental
    // behavior on Google web properties.
    optional uint64 google_web_trigger_experiment_id = 8;

    // Optional id used to uniquely identify this experiment for Chrome Sync.
    optional uint64 chrome_sync_experiment_id = 10;

    // Specifies the feature association parameters for this experiment group.
    //
    // Next tag: 5
    message FeatureAssociation {
      // Optional list of features to enable when this experiment is selected.
      // Command-line overrides take precedence over this setting. No feature
      // listed here should exist in the |disable_feature| list.
      repeated string enable_feature = 1;

      // Optional list of features to disable when this experiment is selected.
      // Command-line overrides take precedence over this setting. No feature
      // listed here should exist in the |enable_feature| list.
      repeated string disable_feature = 2;

      // Similar to |forcing_flag|, this is an optional name of a feature which
      // will cause this experiment to be activated, if that feature is enabled
      // from the command-line. Experiment with this set are not eligible for
      // selection via a random dice roll.
      // Mutually exclusive with |forcing_flag|, |forcing_feature_off| or
      // having a non-zero |probability_weight|.
      optional string forcing_feature_on = 3;

      // Similar to |forcing_flag|, this is an optional name of a feature which
      // will cause this experiment to be activated, if that feature is disabled
      // from the command-line. Experiment with this set are not eligible for
      // selection via a random dice roll.
      // Mutually exclusive with |forcing_flag|, |forcing_feature_on| or having
      // a non-zero |probability_weight|.
      optional string forcing_feature_off = 4;
    }
    optional FeatureAssociation feature_association = 12;

    // Optional name of a Chrome flag that, when present, causes this experiment
    // to be forced. If the forcing_flag field is set, users will not be
    // assigned to this experiment unless that flag is present in Chrome's
    // command line.
    // Mutually exclusive with |forcing_feature_on|, |forcing_feature_off| or
    // having a non-zero |probability_weight|.
    optional string forcing_flag = 5;

    // Parameter values for this experiment.
    repeated Param param = 6;

    enum Type {
      // Regular experiment group. This is the default value and can be omitted.
      NORMAL = 0;

      // Changes to this experiment group are ignored for the purposes of
      // kill-switch triggering. Included to allow the flexibility to not
      // trigger this logic for specific cases (e.g. a group rename without
      // any functionality changes).
      IGNORE_CHANGE = 1;

      // This is a kill-switch group that should be killed at "best effort"
      // priority, e.g. with a hot dog menu badge. The experiment must have a
      // probability_weight of 0.
      KILL_BEST_EFFORT = 2;

      // This is a kill-switch group that should be killed with "critical"
      // priority. Depending on platform this may result in showing a
      // non-dismissible restart prompt with a timer. This should only be used
      // in very serious emergency circumstances. The experiment must have a
      // probability_weight of 0.
      KILL_CRITICAL = 3;
    }
    optional Type type = 7 [default = NORMAL];

    // A UI string to override, and the new value to use.
    message OverrideUIString {
      // The first 32 bits of the MD5 hash digest of the resource name to
      // override.
      // e.g. Hash("IDS_BOOKMARK_BAR_UNDO")
      optional fixed32 name_hash = 1;

      // The new value of the string being overridden.
      // e.g. "Undo"
      optional string value = 2;
    }
    repeated OverrideUIString override_ui_string = 9;
  }

  // List of experiments in this study. This list should include the default /
  // control experiment.
  //
  // For example, to specify that 99% of users get the default behavior, while
  // 0.5% of users get experience "A" and 0.5% of users get experience "B",
  // specify the values below.
  // Ex: { "default": 990, "A": 5, "B": 5 }
  repeated Experiment experiment = 9;

  // Possible Chrome release channels.
  // See: http://dev.chromium.org/getting-involved/dev-channel
  enum Channel {
    // UNKNOWN value is defined here for the benefit of code using this enum
    // type, but is not actually meant to be encoded in the protobuf.
    UNKNOWN = -1;
    CANARY = 0;
    DEV = 1;
    BETA = 2;
    STABLE = 3;
  }

  // Possible Chrome operating system platforms.
  // These names must match those in tools/variations/fieldtrial_to_struct.py.
  enum Platform {
    PLATFORM_WINDOWS         = 0;
    PLATFORM_MAC             = 1;
    PLATFORM_LINUX           = 2;
    PLATFORM_CHROMEOS        = 3;
    PLATFORM_ANDROID         = 4;
    PLATFORM_IOS             = 5;
    PLATFORM_ANDROID_WEBVIEW = 6;
    PLATFORM_FUCHSIA         = 7;
  }

  // Possible form factors Chrome is running on.
  enum FormFactor {
    // Chrome Desktop on Windows, Mac, Linux, or Chrome OS.
    DESKTOP = 0;
    // Phone-based mobile Chrome, e.g. an Android phone or iPhone.
    PHONE   = 1;
    // Tablet-based mobile Chrome, e.g. an Android tablet or iPad.
    TABLET  = 2;
    // Chrome OS running in single-app Kiosk mode.
    KIOSK   = 3;
  }

  // Filtering criteria specifying whether this study is applicable to a given
  // Chrome instance.
  //
  // Next tag: 16
  message Filter {
    // The start date of the study in Unix time format. (Seconds since midnight
    // January 1, 1970 UTC). See: http://en.wikipedia.org/wiki/Unix_time
    // Ex: 1330893974  (corresponds to 2012-03-04 20:46:14Z)
    optional int64 start_date = 1;

    // The end date of the study in Unix time format. (Seconds since midnight
    // January 1, 1970 UTC). See: http://en.wikipedia.org/wiki/Unix_time
    // Ex: 1330893974  (corresponds to 2012-03-04 20:46:14Z)
    // Mutually exclusive with expiry_date. The difference between end_date and
    // expiry_date is that, when end_date is past, the field trial will not be
    // created. When expiry_date is past, the trial is still created, but will
    // be disabled, causing it to select its default group.
    optional int64 end_date = 13;

    // The minimum Chrome version for this study, allowing a trailing '*'
    // character for pattern matching. Inclusive. (To check for a match, iterate
    // over each component checking >= until a * or end of string is reached.)
    // Optional - if not specified, there is no minimum version.
    // Ex: "17.0.963.46", "17.0.963.*", "17.*"
    optional string min_version = 2;

    // The maximum Chrome version for this study; same formatting as
    // |min_version| above. Inclusive. (To check for a match, iterate over each
    // component checking <= until a * or end of string is reached.)
    // Optional - if not specified, there is no maximum version.
    // Ex: "19.*"
    optional string max_version = 3;

    // List of channels that will receive this study. If omitted, the study
    // applies to all channels.
    // Ex: [BETA, STABLE]
    repeated Channel channel = 4;

    // List of platforms that will receive this study. If omitted, the study
    // applies to all platforms.
    // Ex: [PLATFORM_WINDOWS, PLATFORM_MAC]
    repeated Platform platform = 5;

    // List of locales that will receive this study. If omitted, the study
    // applies to all locales, unless |exclude_locale| is specified. Mutually
    // exclusive with |exclude_locale|.
    // Ex: ["en-US", "en-CA"]
    repeated string locale = 6;

    // List of locales that will be excluded from this study. If omitted, the
    // study applies to all locales unless |locale| is specified. Mutually
    // exclusive with |locale|.
    // Ex: ["en-US", "en-CA"]
    repeated string exclude_locale = 12;

    // List of form factors that will receive this study. If omitted, the study
    // applies to all form factors, unless |exclude_form_factor| is specified.
    // Mutually exclusive with |exclude_form_factor|.
    // Ex: [PHONE, TABLET]
    repeated FormFactor form_factor = 7;

    // List of form factors that will be excluded from this study. If omitted,
    // the study applies to all form factors unless |form_factor| is specified.
    // Mutually exclusive with |form_factor|.
    // Takes the same range of values as form_factor, e.g. [PHONE, TABLET].
    repeated FormFactor exclude_form_factor = 14;

    // List of Chrome OS hardware classes that will receive this study.
    //
    // Starting with Chrome M67, this does a case insensitive match on the same
    // hardware class field that is reported to UMA in the SystemProfileProto's
    // |hardware.hardware_class| field.
    //
    // Older versions did a case sensitive substring comparison, which was
    // problematic for short hardware classes like "eve" that existed as
    // substrings of other longer ones.
    //
    // If omitted, the study applies to all hardware classes unless
    // |exclude_hardware_class| is specified. Mutually exclusive with
    // |exclude_hardware_class|.
    // Ex: ["veyron_minnie", "daisy"]
    repeated string hardware_class = 8;

    // List of Chrome OS hardware classes that will be excluded in this study.
    //
    // Starting with Chrome M67, this does a case insensitive match on the same
    // hardware class field that is reported to UMA in the SystemProfileProto's
    // |hardware.hardware_class| field.
    //
    // Older versions did a case sensitive substring comparison, which was
    // problematic for short hardware classes like "eve" that existed as
    // substrings of other longer ones.
    //
    // If omitted, the study applies to all hardware classes unless
    // |hardware_class| is specified. Mutually exclusive with |hardware_class|.
    // Ex: ["veyron_minnie", "daisy"]
    repeated string exclude_hardware_class = 9;

    // List of lowercase ISO 3166-1 alpha-2 country codes that will receive this
    // study. If omitted, the study applies to all countries unless
    // |exclude_country| is specified. Mutually exclusive with
    // |exclude_country|.
    // Ex: ["in", "us"]
    repeated string country = 10;

    // List of lowercase ISO 3166-1 alpha-2 country codes that will be excluded
    // from this study. If omitted, the study applies to all countries unless
    // |country| is specified. Mutually exclusive with |country|.
    // Ex: ["in", "us"]
    repeated string exclude_country = 11;

    // Specifies whether the config should apply to low-end devices only. This
    // is currently only supported on Android.
    optional bool is_low_end_device = 15;
  }

  // Filtering criteria for this study. A study that is filtered out for a given
  // client is equivalent to that study not being sent at all.
  optional Filter filter = 10;

  // Randomization seed to be used when |consistency| is set to PERMANENT. If
  // not specified, randomization will be done using the trial name.
  optional uint32 randomization_seed = 11;

  // Specifies whether the study starts as active initially, or whether it
  // requires the client to query its state before it is marked as active.
  enum ActivationType {
    // The study will be activated when its state is queried by the client.
    // This is recommended for most studies that include client code.
    ACTIVATION_EXPLICIT  = 0;
    // The study will be automatically activated when it is created. This
    // is recommended for studies that do not have any client logic.
    ACTIVATION_AUTO      = 1;
  }

  // Activation type for this study. Defaults to ACTIVATION_EXPLICIT if omitted.
  optional ActivationType activation_type = 12;
}
