|
OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "chrome/app/breakpad_field_trial_win.h" | |
6 | |
7 #include "base/metrics/field_trial.h" | |
8 #include "base/string_util.h" | |
9 #include "base/string16.h" | |
10 #include "base/stringprintf.h" | |
11 #include "breakpad/src/client/windows/common/ipc_protocol.h" | |
12 #include "chrome/app/breakpad_win.h" | |
13 #include "chrome/common/child_process_logging.h" | |
14 | |
15 namespace { | |
16 | |
17 // Allocated in InitExperimentList and destroyed in TermExperimentList. | |
18 base::FieldTrialList* g_field_trial_list = NULL; | |
robertshield
2012/03/23 15:42:10
Thinking about this a bit more, would a base::Lazy
MAD
2012/03/23 18:24:23
Done.
Good idea, I didn't think of it...
Now I wil
| |
19 | |
20 } | |
21 | |
22 extern "C" void __declspec(dllexport) __cdecl InitExperimentList( | |
23 const std::string& state) { | |
24 DCHECK(!g_field_trial_list); | |
25 g_field_trial_list = new base::FieldTrialList(EmptyString()); | |
26 base::FieldTrialList::CreateTrialsInChildProcess(state); | |
27 UpdateExperiments(); | |
28 } | |
29 | |
30 extern "C" void __declspec(dllexport) __cdecl AddFieldTrialGroup( | |
31 const std::string& field_trial_name, const std::string& group_name) { | |
32 base::FieldTrialList::CreateFieldTrial(field_trial_name, group_name); | |
33 // TODO(mad): Find a way to just add the |field_trial_name| and |group_name| | |
34 // instead of starting over each time. | |
35 UpdateExperiments(); | |
36 } | |
37 | |
38 extern "C" void __declspec(dllexport) __cdecl TermExperimentList() { | |
39 DCHECK(g_field_trial_list); | |
40 delete g_field_trial_list; | |
41 g_field_trial_list = NULL; | |
42 } | |
43 | |
44 void UpdateExperiments() { | |
45 // Make sure we were initialized before we start writing data | |
46 if (breakpad_win::g_experiment_chunks_offset == 0) | |
47 return; | |
48 | |
49 std::vector<base::FieldTrial::NameGroupId> name_group_ids; | |
50 base::FieldTrialList::GetFieldTrialNameGroupIds(&name_group_ids); | |
51 | |
52 std::vector<string16> experiment_strings(name_group_ids.size()); | |
53 for (size_t i = 0; i < name_group_ids.size(); ++i) { | |
54 experiment_strings[i] = base::StringPrintf( | |
55 L"%x-%x", name_group_ids[i].name, name_group_ids[i].group); | |
56 } | |
57 | |
58 size_t num_chunks = 0; | |
59 size_t current_experiment = 0; | |
60 string16 current_chunk; | |
61 // Preallocate the string... | |
62 current_chunk.resize(google_breakpad::CustomInfoEntry::kValueMaxLength); | |
robertshield
2012/03/23 15:42:10
The above can be simplified to:
string16 current_c
MAD
2012/03/23 18:24:23
Done.
| |
63 current_chunk.erase(); // But start empty... This won't force a realloc. | |
64 while (current_experiment < experiment_strings.size() && | |
65 num_chunks < kMaxReportedExperimentChunks) { | |
66 // Check if we have enough room to add another experiment to the current | |
67 // chunk string. If not, we commit the current chunk string and start over. | |
68 if (current_chunk.size() + experiment_strings[current_experiment].size() > | |
69 google_breakpad::CustomInfoEntry::kValueMaxLength) { | |
70 base::wcslcpy( | |
71 (*breakpad_win::g_custom_entries)[ | |
72 breakpad_win::g_experiment_chunks_offset + num_chunks].value, | |
73 current_chunk.c_str(), | |
74 current_chunk.size() + 1); // This must include the NULL termination. | |
75 ++num_chunks; | |
76 current_chunk = experiment_strings[current_experiment]; | |
77 } else { | |
78 if (!current_chunk.empty()) | |
79 current_chunk += L","; | |
80 current_chunk += experiment_strings[current_experiment]; | |
81 } | |
82 ++current_experiment; | |
83 } | |
84 | |
85 // Commit the last chunk that didn't get big enough yet. | |
86 if (!current_chunk.empty() && num_chunks < kMaxReportedExperimentChunks) { | |
87 base::wcslcpy( | |
88 (*breakpad_win::g_custom_entries)[ | |
89 breakpad_win::g_experiment_chunks_offset + num_chunks].value, | |
90 current_chunk.c_str(), | |
91 current_chunk.size() + 1); // This must include the NULL termination. | |
92 } | |
93 | |
94 // Make note of the total number of experiments, | |
95 // even if it's > kMaxReportedExperimentChunks. This is useful when | |
96 // correlating stability with the number of experiments running | |
97 // simultaneously. | |
98 base::wcslcpy( | |
99 (*breakpad_win::g_custom_entries)[ | |
100 breakpad_win::g_num_of_experiments_offset].value, | |
101 base::StringPrintf(L"%d", name_group_ids.size()).c_str(), | |
102 google_breakpad::CustomInfoEntry::kValueMaxLength); | |
103 } | |
OLD | NEW |