1// Copyright 2014 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/browser/chrome_elf_init_win.h"
6
7#include "base/basictypes.h"
8#include "base/memory/scoped_ptr.h"
9#include "base/metrics/field_trial.h"
10#include "base/strings/string16.h"
11#include "base/strings/utf_string_conversions.h"
12#include "base/test/test_reg_util_win.h"
13#include "chrome/common/chrome_version_info.h"
14#include "chrome_elf/chrome_elf_constants.h"
15#include "components/variations/entropy_provider.h"
16#include "components/variations/variations_associated_data.h"
17#include "testing/gtest/include/gtest/gtest.h"
18#include "version.h"  // NOLINT
19
20namespace {
21
22const char kBrowserBlacklistTrialEnabledGroupName[] = "Enabled";
23
24class ChromeBlacklistTrialTest : public testing::Test {
25 protected:
26  ChromeBlacklistTrialTest() {}
27  virtual ~ChromeBlacklistTrialTest() {}
28
29  virtual void SetUp() OVERRIDE {
30    testing::Test::SetUp();
31
32    override_manager_.OverrideRegistry(HKEY_CURRENT_USER);
33
34    blacklist_registry_key_.reset(
35        new base::win::RegKey(HKEY_CURRENT_USER,
36                              blacklist::kRegistryBeaconPath,
37                              KEY_QUERY_VALUE | KEY_SET_VALUE));
38  }
39
40  DWORD GetBlacklistState() {
41    DWORD blacklist_state = blacklist::BLACKLIST_STATE_MAX;
42    blacklist_registry_key_->ReadValueDW(blacklist::kBeaconState,
43                                         &blacklist_state);
44
45    return blacklist_state;
46  }
47
48  base::string16 GetBlacklistVersion() {
49    base::string16 blacklist_version;
50    blacklist_registry_key_->ReadValue(blacklist::kBeaconVersion,
51                                       &blacklist_version);
52
53    return blacklist_version;
54  }
55
56  scoped_ptr<base::win::RegKey> blacklist_registry_key_;
57  registry_util::RegistryOverrideManager override_manager_;
58
59 private:
60  DISALLOW_COPY_AND_ASSIGN(ChromeBlacklistTrialTest);
61};
62
63// Ensure that the default trial sets up the blacklist beacons.
64TEST_F(ChromeBlacklistTrialTest, DefaultRun) {
65  // Set some dummy values as beacons.
66  blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
67                                      blacklist::BLACKLIST_DISABLED);
68  blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, L"Data");
69
70  // This setup code should result in the default group, which should have
71  // the blacklist set up.
72  InitializeChromeElf();
73
74  // Ensure the beacon values are now correct, indicating the
75  // blacklist beacon was setup.
76  ASSERT_EQ(blacklist::BLACKLIST_ENABLED, GetBlacklistState());
77  chrome::VersionInfo version_info;
78  base::string16 version(base::UTF8ToUTF16(version_info.Version()));
79  ASSERT_EQ(version, GetBlacklistVersion());
80}
81
82// Ensure that the blacklist is disabled for any users in the
83// "BlacklistDisabled" finch group.
84TEST_F(ChromeBlacklistTrialTest, BlacklistDisabledRun) {
85  // Set the beacons to enabled values.
86  blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
87                                      blacklist::BLACKLIST_ENABLED);
88  blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion, L"Data");
89
90  // Create the field trial with the blacklist disabled group.
91  base::FieldTrialList field_trial_list(
92    new metrics::SHA1EntropyProvider("test"));
93
94  scoped_refptr<base::FieldTrial> trial(
95    base::FieldTrialList::CreateFieldTrial(
96      kBrowserBlacklistTrialName, kBrowserBlacklistTrialDisabledGroupName));
97
98  // This setup code should now delete any existing blacklist beacons.
99  InitializeChromeElf();
100
101  // Ensure invalid values are returned to indicate that the beacon
102  // values are indeed gone.
103  ASSERT_EQ(blacklist::BLACKLIST_STATE_MAX, GetBlacklistState());
104  ASSERT_EQ(base::string16(), GetBlacklistVersion());
105}
106
107TEST_F(ChromeBlacklistTrialTest, VerifyFirstRun) {
108  BrowserBlacklistBeaconSetup();
109
110  // Verify the state is properly set after the first run.
111  ASSERT_EQ(blacklist::BLACKLIST_ENABLED, GetBlacklistState());
112
113  chrome::VersionInfo version_info;
114  base::string16 version(base::UTF8ToUTF16(version_info.Version()));
115  ASSERT_EQ(version, GetBlacklistVersion());
116}
117
118TEST_F(ChromeBlacklistTrialTest, BlacklistFailed) {
119  // Ensure when the blacklist set up failed we set the state to disabled for
120  // future runs.
121  blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
122                                      TEXT(CHROME_VERSION_STRING));
123  blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
124                                      blacklist::BLACKLIST_SETUP_FAILED);
125
126  BrowserBlacklistBeaconSetup();
127
128  ASSERT_EQ(blacklist::BLACKLIST_DISABLED, GetBlacklistState());
129}
130
131TEST_F(ChromeBlacklistTrialTest, VersionChanged) {
132  // Mark the blacklist as disabled for an older version, it should
133  // get enabled for this new version.  Also record a non-zero number of
134  // setup failures, which should be reset to zero.
135  blacklist_registry_key_->WriteValue(blacklist::kBeaconVersion,
136                                      L"old_version");
137  blacklist_registry_key_->WriteValue(blacklist::kBeaconState,
138                                      blacklist::BLACKLIST_DISABLED);
139  blacklist_registry_key_->WriteValue(blacklist::kBeaconAttemptCount,
140                                      blacklist::kBeaconMaxAttempts);
141
142  BrowserBlacklistBeaconSetup();
143
144  // The beacon should now be marked as enabled for the current version.
145  ASSERT_EQ(blacklist::BLACKLIST_ENABLED, GetBlacklistState());
146
147  chrome::VersionInfo version_info;
148  base::string16 expected_version(base::UTF8ToUTF16(version_info.Version()));
149  ASSERT_EQ(expected_version, GetBlacklistVersion());
150
151  // The counter should be reset.
152  DWORD attempt_count = blacklist::kBeaconMaxAttempts;
153  blacklist_registry_key_->ReadValueDW(blacklist::kBeaconAttemptCount,
154                                       &attempt_count);
155  ASSERT_EQ(static_cast<DWORD>(0), attempt_count);
156}
157
158TEST_F(ChromeBlacklistTrialTest, AddFinchBlacklistToRegistry) {
159  // Create the field trial with the blacklist enabled group.
160  base::FieldTrialList field_trial_list(
161      new metrics::SHA1EntropyProvider("test"));
162
163  scoped_refptr<base::FieldTrial> trial(base::FieldTrialList::CreateFieldTrial(
164      kBrowserBlacklistTrialName, kBrowserBlacklistTrialEnabledGroupName));
165
166  // Set up the trial with the desired parameters.
167  std::map<std::string, std::string> desired_params;
168  desired_params["TestDllName1"] = "TestDll1.dll";
169  desired_params["TestDllName2"] = "TestDll2.dll";
170
171  variations::AssociateVariationParams(
172      kBrowserBlacklistTrialName,
173      kBrowserBlacklistTrialEnabledGroupName,
174      desired_params);
175
176  // This should add the dlls in those parameters to the registry.
177  AddFinchBlacklistToRegistry();
178
179  // Check that all the values in desired_params were added to the registry.
180  base::win::RegKey finch_blacklist_registry_key(
181      HKEY_CURRENT_USER,
182      blacklist::kRegistryFinchListPath,
183      KEY_QUERY_VALUE | KEY_SET_VALUE);
184
185  ASSERT_EQ(desired_params.size(),
186            finch_blacklist_registry_key.GetValueCount());
187
188  for (std::map<std::string, std::string>::iterator it = desired_params.begin();
189       it != desired_params.end();
190       ++it) {
191    std::wstring name = base::UTF8ToWide(it->first);
192    ASSERT_TRUE(finch_blacklist_registry_key.HasValue(name.c_str()));
193  }
194}
195
196}  // namespace
197