# Copyright 2015 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. import json import sys import fieldtrial_to_struct def _hex(ch): hv = hex(ord(ch)).replace('0x', '') hv.zfill(2) return hv.upper() # URL escapes the delimiter characters from the output. urllib.quote is not # used because it cannot escape '.'. def _escape(str): result = str # Must perform replace on '%' first before the others. for c in '%:/.,': result = result.replace(c, '%' + _hex(c)) return result def _FindDuplicates(entries): seen = set() duplicates = set() for entry in entries: if entry in seen: duplicates.add(entry) else: seen.add(entry) return duplicates def _CheckForDuplicateFeatures(enable_features, disable_features): enable_features = [f.split('<')[0] for f in enable_features] enable_features_set = set(enable_features) if len(enable_features_set) != len(enable_features): raise Exception('Duplicate feature(s) in enable_features: ' + ', '.join(_FindDuplicates(enable_features))) disable_features = [f.split('<')[0] for f in disable_features] disable_features_set = set(disable_features) if len(disable_features_set) != len(disable_features): raise Exception('Duplicate feature(s) in disable_features: ' + ', '.join(_FindDuplicates(disable_features))) features_in_both = enable_features_set.intersection(disable_features_set) if len(features_in_both) > 0: raise Exception('Conflicting features set as both enabled and disabled: ' + ', '.join(features_in_both)) # Generate a list of command-line switches to enable field trials for the # provided config_path and platform. def GenerateArgs(config_path, platform): try: with open(config_path, 'r') as config_file: config = json.load(config_file) except (IOError, ValueError): return [] platform_studies = fieldtrial_to_struct.ConfigToStudies(config, platform) studies = [] params = [] enable_features = [] disable_features = [] for study in platform_studies: study_name = study['name'] experiments = study['experiments'] # For now, only take the first experiment. experiment = experiments[0] selected_study = [study_name, experiment['name']] studies.extend(selected_study) param_list = [] if 'params' in experiment: for param in experiment['params']: param_list.append(param['key']) param_list.append(param['value']) if len(param_list): # Escape the variables for the command-line. selected_study = [_escape(x) for x in selected_study] param_list = [_escape(x) for x in param_list] param = '%s:%s' % ('.'.join(selected_study), '/'.join(param_list)) params.append(param) for feature in experiment.get('enable_features', []): enable_features.append(feature + '<' + study_name) for feature in experiment.get('disable_features', []): disable_features.append(feature + '<' + study_name) if not len(studies): return [] _CheckForDuplicateFeatures(enable_features, disable_features) args = ['--force-fieldtrials=%s' % '/'.join(studies)] if len(params): args.append('--force-fieldtrial-params=%s' % ','.join(params)) if len(enable_features): args.append('--enable-features=%s' % ','.join(enable_features)) if len(disable_features): args.append('--disable-features=%s' % ','.join(disable_features)) return args def main(): if len(sys.argv) < 3: print 'Usage: fieldtrial_util.py [config_path] [platform]' print 'Optionally pass \'shell_cmd\' as an extra argument to print' print 'quoted command line arguments.' exit(-1) print_shell_cmd = len(sys.argv) >= 4 and sys.argv[3] == 'shell_cmd' supported_platforms = ['android', 'chromeos', 'ios', 'linux', 'mac', 'win'] if sys.argv[2] not in supported_platforms: print ('\'%s\' is an unknown platform. Supported platforms: %s' % (sys.argv[2], supported_platforms)) exit(-1) generated_args = GenerateArgs(sys.argv[1], sys.argv[2]) if print_shell_cmd: print " ".join(map((lambda arg: '"{0}"'.format(arg)), generated_args)) else: print generated_args if __name__ == '__main__': main()