OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/metrics/field_trial.h" | 5 #include "base/metrics/field_trial.h" |
6 | 6 |
7 #include <algorithm> | 7 #include <algorithm> |
8 #include <utility> | 8 #include <utility> |
9 | 9 |
10 #include "base/base_switches.h" | 10 #include "base/base_switches.h" |
11 #include "base/build_time.h" | 11 #include "base/build_time.h" |
12 #include "base/command_line.h" | 12 #include "base/command_line.h" |
13 #include "base/feature_list.h" | |
14 #include "base/logging.h" | 13 #include "base/logging.h" |
15 #include "base/pickle.h" | 14 #include "base/pickle.h" |
16 #include "base/process/memory.h" | 15 #include "base/process/memory.h" |
17 #include "base/rand_util.h" | 16 #include "base/rand_util.h" |
18 #include "base/strings/string_number_conversions.h" | 17 #include "base/strings/string_number_conversions.h" |
19 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
20 #include "base/strings/stringprintf.h" | 19 #include "base/strings/stringprintf.h" |
21 #include "base/strings/utf_string_conversions.h" | 20 #include "base/strings/utf_string_conversions.h" |
22 | 21 |
23 // On systems that use the zygote process to spawn child processes, we must | 22 // On systems that use the zygote process to spawn child processes, we must |
(...skipping 153 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
177 trials_string_piece.substr(next_item, name_end - next_item); | 176 trials_string_piece.substr(next_item, name_end - next_item); |
178 entry.group_name = | 177 entry.group_name = |
179 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1); | 178 trials_string_piece.substr(name_end + 1, group_name_end - name_end - 1); |
180 next_item = group_name_end + 1; | 179 next_item = group_name_end + 1; |
181 | 180 |
182 entries->push_back(std::move(entry)); | 181 entries->push_back(std::move(entry)); |
183 } | 182 } |
184 return true; | 183 return true; |
185 } | 184 } |
186 | 185 |
187 void AddForceFieldTrialsFlag(CommandLine* cmd_line) { | 186 void AddFeatureAndFieldTrialFlags(CommandLine* cmd_line, |
Alexei Svitkine (slow)
2016/12/01 19:39:22
Nit: Non-const params should be last.
lawrencewu
2016/12/02 19:24:46
Done.
| |
187 const char* enable_features_switch, | |
188 const char* disable_features_switch) { | |
189 std::string enabled_features; | |
190 std::string disabled_features; | |
191 FeatureList::GetInstance()->GetFeatureOverrides(&enabled_features, | |
192 &disabled_features); | |
193 | |
194 if (!enabled_features.empty()) | |
195 cmd_line->AppendSwitchASCII(enable_features_switch, enabled_features); | |
196 if (!disabled_features.empty()) | |
197 cmd_line->AppendSwitchASCII(disable_features_switch, disabled_features); | |
198 | |
188 std::string field_trial_states; | 199 std::string field_trial_states; |
189 FieldTrialList::AllStatesToString(&field_trial_states); | 200 FieldTrialList::AllStatesToString(&field_trial_states); |
190 if (!field_trial_states.empty()) { | 201 if (!field_trial_states.empty()) { |
191 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, | 202 cmd_line->AppendSwitchASCII(switches::kForceFieldTrials, |
192 field_trial_states); | 203 field_trial_states); |
193 } | 204 } |
194 } | 205 } |
195 | 206 |
196 #if defined(OS_WIN) | 207 #if defined(OS_WIN) |
197 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { | 208 HANDLE CreateReadOnlyHandle(FieldTrialList::FieldTrialAllocator* allocator) { |
(...skipping 536 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
734 #endif | 745 #endif |
735 | 746 |
736 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { | 747 if (cmd_line.HasSwitch(switches::kForceFieldTrials)) { |
737 bool result = FieldTrialList::CreateTrialsFromString( | 748 bool result = FieldTrialList::CreateTrialsFromString( |
738 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), | 749 cmd_line.GetSwitchValueASCII(switches::kForceFieldTrials), |
739 std::set<std::string>()); | 750 std::set<std::string>()); |
740 DCHECK(result); | 751 DCHECK(result); |
741 } | 752 } |
742 } | 753 } |
743 | 754 |
755 // static | |
756 void FieldTrialList::CreateFeaturesFromCommandLine( | |
757 const base::CommandLine& command_line, | |
758 const char* enable_features_switch, | |
759 const char* disable_features_switch, | |
760 std::unique_ptr<FeatureList>& feature_list) { | |
Alexei Svitkine (slow)
2016/12/01 19:39:22
Don't pass non const refs.
You can pass as a Feat
lawrencewu
2016/12/02 19:24:46
Done.
| |
761 // Fallback to command line if not using shared memory. | |
762 if (!kUseSharedMemoryForFieldTrials || !global_->field_trial_allocator_.get()) | |
Alexei Svitkine (slow)
2016/12/01 19:39:22
Nit: {}'s
| |
763 return feature_list->InitializeFromCommandLine( | |
764 command_line.GetSwitchValueASCII(enable_features_switch), | |
765 command_line.GetSwitchValueASCII(disable_features_switch)); | |
766 | |
767 feature_list->InitializeFromSharedMemory( | |
768 global_->field_trial_allocator_.get()); | |
769 } | |
770 | |
744 #if defined(POSIX_WITH_ZYGOTE) | 771 #if defined(POSIX_WITH_ZYGOTE) |
745 // static | 772 // static |
746 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { | 773 bool FieldTrialList::CreateTrialsFromDescriptor(int fd_key) { |
747 if (!kUseSharedMemoryForFieldTrials) | 774 if (!kUseSharedMemoryForFieldTrials) |
748 return false; | 775 return false; |
749 | 776 |
750 if (fd_key == -1) | 777 if (fd_key == -1) |
751 return false; | 778 return false; |
752 | 779 |
753 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); | 780 int fd = GlobalDescriptors::GetInstance()->MaybeGet(fd_key); |
(...skipping 29 matching lines...) Expand all Loading... | |
783 // We check for an invalid handle where this gets called. | 810 // We check for an invalid handle where this gets called. |
784 return global_->readonly_allocator_handle_; | 811 return global_->readonly_allocator_handle_; |
785 } | 812 } |
786 return kInvalidPlatformFile; | 813 return kInvalidPlatformFile; |
787 } | 814 } |
788 #endif | 815 #endif |
789 | 816 |
790 // static | 817 // static |
791 void FieldTrialList::CopyFieldTrialStateToFlags( | 818 void FieldTrialList::CopyFieldTrialStateToFlags( |
792 const char* field_trial_handle_switch, | 819 const char* field_trial_handle_switch, |
820 const char* enable_features_switch, | |
821 const char* disable_features_switch, | |
793 CommandLine* cmd_line) { | 822 CommandLine* cmd_line) { |
794 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, | 823 // TODO(lawrencewu): Ideally, having the global would be guaranteed. However, |
795 // content browser tests currently don't create a FieldTrialList because they | 824 // content browser tests currently don't create a FieldTrialList because they |
796 // don't run ChromeBrowserMainParts code where it's done for Chrome. | 825 // don't run ChromeBrowserMainParts code where it's done for Chrome. |
797 if (!global_) | 826 if (!global_) |
798 return; | 827 return; |
799 | 828 |
800 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) | 829 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) |
801 // Use shared memory to pass the state if the feature is enabled, otherwise | 830 // Use shared memory to pass the state if the feature is enabled, otherwise |
802 // fallback to passing it via the command line as a string. | 831 // fallback to passing it via the command line as a string. |
803 if (kUseSharedMemoryForFieldTrials) { | 832 if (kUseSharedMemoryForFieldTrials) { |
804 InstantiateFieldTrialAllocatorIfNeeded(); | 833 InstantiateFieldTrialAllocatorIfNeeded(); |
805 // If the readonly handle didn't get duplicated properly, then fallback to | 834 // If the readonly handle didn't get duplicated properly, then fallback to |
806 // original behavior. | 835 // original behavior. |
807 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { | 836 if (global_->readonly_allocator_handle_ == kInvalidPlatformFile) { |
808 AddForceFieldTrialsFlag(cmd_line); | 837 AddFeatureAndFieldTrialFlags(cmd_line, enable_features_switch, |
838 disable_features_switch); | |
809 return; | 839 return; |
810 } | 840 } |
811 | 841 |
812 global_->field_trial_allocator_->UpdateTrackingHistograms(); | 842 global_->field_trial_allocator_->UpdateTrackingHistograms(); |
813 | 843 |
814 #if defined(OS_WIN) | 844 #if defined(OS_WIN) |
815 // We need to pass a named anonymous handle to shared memory over the | 845 // We need to pass a named anonymous handle to shared memory over the |
816 // command line on Windows, since the child doesn't know which of the | 846 // command line on Windows, since the child doesn't know which of the |
817 // handles it inherited it should open. On POSIX, we don't need to do this | 847 // handles it inherited it should open. On POSIX, we don't need to do this |
818 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just | 848 // -- we dup the fd into a fixed fd kFieldTrialDescriptor, so we can just |
819 // look it up there. | 849 // look it up there. |
820 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We | 850 // PlatformFile is typedef'd to HANDLE which is typedef'd to void *. We |
821 // basically cast the handle into an int (uintptr_t, to be exact), stringify | 851 // basically cast the handle into an int (uintptr_t, to be exact), stringify |
822 // the int, and pass it as a command-line flag. The child process will do | 852 // the int, and pass it as a command-line flag. The child process will do |
823 // the reverse conversions to retrieve the handle. See | 853 // the reverse conversions to retrieve the handle. See |
824 // http://stackoverflow.com/a/153077 | 854 // http://stackoverflow.com/a/153077 |
825 auto uintptr_handle = | 855 auto uintptr_handle = |
826 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); | 856 reinterpret_cast<uintptr_t>(global_->readonly_allocator_handle_); |
827 std::string field_trial_handle = std::to_string(uintptr_handle); | 857 std::string field_trial_handle = std::to_string(uintptr_handle); |
828 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); | 858 cmd_line->AppendSwitchASCII(field_trial_handle_switch, field_trial_handle); |
829 #endif | 859 #endif |
830 return; | 860 return; |
831 } | 861 } |
832 #endif | 862 #endif |
833 | 863 |
834 AddForceFieldTrialsFlag(cmd_line); | 864 AddFeatureAndFieldTrialFlags(cmd_line, enable_features_switch, |
865 disable_features_switch); | |
835 } | 866 } |
836 | 867 |
837 // static | 868 // static |
838 FieldTrial* FieldTrialList::CreateFieldTrial( | 869 FieldTrial* FieldTrialList::CreateFieldTrial( |
839 const std::string& name, | 870 const std::string& name, |
840 const std::string& group_name) { | 871 const std::string& group_name) { |
841 DCHECK(global_); | 872 DCHECK(global_); |
842 DCHECK_GE(name.size(), 0u); | 873 DCHECK_GE(name.size(), 0u); |
843 DCHECK_GE(group_name.size(), 0u); | 874 DCHECK_GE(group_name.size(), 0u); |
844 if (name.empty() || group_name.empty() || !global_) | 875 if (name.empty() || group_name.empty() || !global_) |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1000 | 1031 |
1001 global_->field_trial_allocator_.reset( | 1032 global_->field_trial_allocator_.reset( |
1002 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); | 1033 new FieldTrialAllocator(std::move(shm), 0, kAllocatorName, false)); |
1003 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); | 1034 global_->field_trial_allocator_->CreateTrackingHistograms(kAllocatorName); |
1004 | 1035 |
1005 // Add all existing field trials. | 1036 // Add all existing field trials. |
1006 for (const auto& registered : global_->registered_) { | 1037 for (const auto& registered : global_->registered_) { |
1007 AddToAllocatorWhileLocked(registered.second); | 1038 AddToAllocatorWhileLocked(registered.second); |
1008 } | 1039 } |
1009 | 1040 |
1041 // Add all existing features. | |
1042 FeatureList::GetInstance()->AddFeaturesToAllocator( | |
1043 global_->field_trial_allocator_.get()); | |
1044 | |
1010 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) | 1045 #if defined(OS_WIN) || defined(POSIX_WITH_ZYGOTE) |
1011 // Set |readonly_allocator_handle_| so we can pass it to be inherited and | 1046 // Set |readonly_allocator_handle_| so we can pass it to be inherited and |
1012 // via the command line. | 1047 // via the command line. |
1013 global_->readonly_allocator_handle_ = | 1048 global_->readonly_allocator_handle_ = |
1014 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); | 1049 CreateReadOnlyHandle(global_->field_trial_allocator_.get()); |
1015 #endif | 1050 #endif |
1016 } | 1051 } |
1017 #endif | 1052 #endif |
1018 | 1053 |
1019 // static | 1054 // static |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1111 return; | 1146 return; |
1112 } | 1147 } |
1113 AutoLock auto_lock(global_->lock_); | 1148 AutoLock auto_lock(global_->lock_); |
1114 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); | 1149 CHECK(!global_->PreLockedFind(trial->trial_name())) << trial->trial_name(); |
1115 trial->AddRef(); | 1150 trial->AddRef(); |
1116 trial->SetTrialRegistered(); | 1151 trial->SetTrialRegistered(); |
1117 global_->registered_[trial->trial_name()] = trial; | 1152 global_->registered_[trial->trial_name()] = trial; |
1118 } | 1153 } |
1119 | 1154 |
1120 } // namespace base | 1155 } // namespace base |
OLD | NEW |