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 <gtest/gtest.h>
6
7#include "base/command_line.h"
8#include "base/memory/ref_counted.h"
9#include "base/strings/string_util.h"
10#include "base/values.h"
11#include "chrome/browser/prefs/command_line_pref_store.h"
12#include "chrome/browser/prefs/proxy_config_dictionary.h"
13#include "chrome/common/chrome_switches.h"
14#include "chrome/common/pref_names.h"
15#include "ui/base/ui_base_switches.h"
16
17namespace {
18
19const char unknown_bool[] = "unknown_switch";
20const char unknown_string[] = "unknown_other_switch";
21
22}  // namespace
23
24class TestCommandLinePrefStore : public CommandLinePrefStore {
25 public:
26  explicit TestCommandLinePrefStore(CommandLine* cl)
27      : CommandLinePrefStore(cl) {}
28
29  bool ProxySwitchesAreValid() {
30    return ValidateProxySwitches();
31  }
32
33  void VerifyProxyMode(ProxyPrefs::ProxyMode expected_mode) {
34    const base::Value* value = NULL;
35    ASSERT_TRUE(GetValue(prefs::kProxy, &value));
36    ASSERT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
37    ProxyConfigDictionary dict(
38        static_cast<const base::DictionaryValue*>(value));
39    ProxyPrefs::ProxyMode actual_mode;
40    ASSERT_TRUE(dict.GetMode(&actual_mode));
41    EXPECT_EQ(expected_mode, actual_mode);
42  }
43
44  void VerifySSLCipherSuites(const char* const* ciphers,
45                             size_t cipher_count) {
46    const base::Value* value = NULL;
47    ASSERT_TRUE(GetValue(prefs::kCipherSuiteBlacklist, &value));
48    ASSERT_EQ(base::Value::TYPE_LIST, value->GetType());
49    const base::ListValue* list_value =
50        static_cast<const base::ListValue*>(value);
51    ASSERT_EQ(cipher_count, list_value->GetSize());
52
53    std::string cipher_string;
54    for (base::ListValue::const_iterator it = list_value->begin();
55         it != list_value->end(); ++it, ++ciphers) {
56      ASSERT_TRUE((*it)->GetAsString(&cipher_string));
57      EXPECT_EQ(*ciphers, cipher_string);
58    }
59  }
60
61 private:
62  virtual ~TestCommandLinePrefStore() {}
63};
64
65// Tests a simple string pref on the command line.
66TEST(CommandLinePrefStoreTest, SimpleStringPref) {
67  CommandLine cl(CommandLine::NO_PROGRAM);
68  cl.AppendSwitchASCII(switches::kLang, "hi-MOM");
69  scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
70
71  const base::Value* actual = NULL;
72  EXPECT_TRUE(store->GetValue(prefs::kApplicationLocale, &actual));
73  std::string result;
74  EXPECT_TRUE(actual->GetAsString(&result));
75  EXPECT_EQ("hi-MOM", result);
76}
77
78// Tests a simple boolean pref on the command line.
79TEST(CommandLinePrefStoreTest, SimpleBooleanPref) {
80  CommandLine cl(CommandLine::NO_PROGRAM);
81  cl.AppendSwitch(switches::kNoProxyServer);
82  scoped_refptr<TestCommandLinePrefStore> store =
83      new TestCommandLinePrefStore(&cl);
84
85  store->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
86}
87
88// Tests a command line with no recognized prefs.
89TEST(CommandLinePrefStoreTest, NoPrefs) {
90  CommandLine cl(CommandLine::NO_PROGRAM);
91  cl.AppendSwitch(unknown_string);
92  cl.AppendSwitchASCII(unknown_bool, "a value");
93  scoped_refptr<CommandLinePrefStore> store = new CommandLinePrefStore(&cl);
94
95  const base::Value* actual = NULL;
96  EXPECT_FALSE(store->GetValue(unknown_bool, &actual));
97  EXPECT_FALSE(store->GetValue(unknown_string, &actual));
98}
99
100// Tests a complex command line with multiple known and unknown switches.
101TEST(CommandLinePrefStoreTest, MultipleSwitches) {
102  CommandLine cl(CommandLine::NO_PROGRAM);
103  cl.AppendSwitch(unknown_string);
104  cl.AppendSwitchASCII(switches::kProxyServer, "proxy");
105  cl.AppendSwitchASCII(switches::kProxyBypassList, "list");
106  cl.AppendSwitchASCII(unknown_bool, "a value");
107  scoped_refptr<TestCommandLinePrefStore> store =
108      new TestCommandLinePrefStore(&cl);
109
110  const base::Value* actual = NULL;
111  EXPECT_FALSE(store->GetValue(unknown_bool, &actual));
112  EXPECT_FALSE(store->GetValue(unknown_string, &actual));
113
114  store->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
115
116  const base::Value* value = NULL;
117  ASSERT_TRUE(store->GetValue(prefs::kProxy, &value));
118  ASSERT_EQ(base::Value::TYPE_DICTIONARY, value->GetType());
119  ProxyConfigDictionary dict(static_cast<const base::DictionaryValue*>(value));
120
121  std::string string_result;
122
123  ASSERT_TRUE(dict.GetProxyServer(&string_result));
124  EXPECT_EQ("proxy", string_result);
125
126  ASSERT_TRUE(dict.GetBypassList(&string_result));
127  EXPECT_EQ("list", string_result);
128}
129
130// Tests proxy switch validation.
131TEST(CommandLinePrefStoreTest, ProxySwitchValidation) {
132  CommandLine cl(CommandLine::NO_PROGRAM);
133
134  // No switches.
135  scoped_refptr<TestCommandLinePrefStore> store =
136      new TestCommandLinePrefStore(&cl);
137  EXPECT_TRUE(store->ProxySwitchesAreValid());
138
139  // Only no-proxy.
140  cl.AppendSwitch(switches::kNoProxyServer);
141  scoped_refptr<TestCommandLinePrefStore> store2 =
142      new TestCommandLinePrefStore(&cl);
143  EXPECT_TRUE(store2->ProxySwitchesAreValid());
144
145  // Another proxy switch too.
146  cl.AppendSwitch(switches::kProxyAutoDetect);
147  scoped_refptr<TestCommandLinePrefStore> store3 =
148      new TestCommandLinePrefStore(&cl);
149  EXPECT_FALSE(store3->ProxySwitchesAreValid());
150
151  // All proxy switches except no-proxy.
152  CommandLine cl2(CommandLine::NO_PROGRAM);
153  cl2.AppendSwitch(switches::kProxyAutoDetect);
154  cl2.AppendSwitchASCII(switches::kProxyServer, "server");
155  cl2.AppendSwitchASCII(switches::kProxyPacUrl, "url");
156  cl2.AppendSwitchASCII(switches::kProxyBypassList, "list");
157  scoped_refptr<TestCommandLinePrefStore> store4 =
158      new TestCommandLinePrefStore(&cl2);
159  EXPECT_TRUE(store4->ProxySwitchesAreValid());
160}
161
162TEST(CommandLinePrefStoreTest, ManualProxyModeInference) {
163  CommandLine cl1(CommandLine::NO_PROGRAM);
164  cl1.AppendSwitch(unknown_string);
165  cl1.AppendSwitchASCII(switches::kProxyServer, "proxy");
166  scoped_refptr<TestCommandLinePrefStore> store1 =
167      new TestCommandLinePrefStore(&cl1);
168  store1->VerifyProxyMode(ProxyPrefs::MODE_FIXED_SERVERS);
169
170  CommandLine cl2(CommandLine::NO_PROGRAM);
171  cl2.AppendSwitchASCII(switches::kProxyPacUrl, "proxy");
172  scoped_refptr<TestCommandLinePrefStore> store2 =
173        new TestCommandLinePrefStore(&cl2);
174  store2->VerifyProxyMode(ProxyPrefs::MODE_PAC_SCRIPT);
175
176  CommandLine cl3(CommandLine::NO_PROGRAM);
177  cl3.AppendSwitchASCII(switches::kProxyServer, std::string());
178  scoped_refptr<TestCommandLinePrefStore> store3 =
179      new TestCommandLinePrefStore(&cl3);
180  store3->VerifyProxyMode(ProxyPrefs::MODE_DIRECT);
181}
182
183TEST(CommandLinePrefStoreTest, DisableSSLCipherSuites) {
184  CommandLine cl1(CommandLine::NO_PROGRAM);
185  cl1.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
186                        "0x0004,0x0005");
187  scoped_refptr<TestCommandLinePrefStore> store1 =
188      new TestCommandLinePrefStore(&cl1);
189  const char* const expected_ciphers1[] = {
190    "0x0004",
191    "0x0005",
192  };
193  store1->VerifySSLCipherSuites(expected_ciphers1,
194                                arraysize(expected_ciphers1));
195
196  CommandLine cl2(CommandLine::NO_PROGRAM);
197  cl2.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
198                        "0x0004, WHITESPACE_IGNORED TEST , 0x0005");
199  scoped_refptr<TestCommandLinePrefStore> store2 =
200      new TestCommandLinePrefStore(&cl2);
201  const char* const expected_ciphers2[] = {
202    "0x0004",
203    "WHITESPACE_IGNORED TEST",
204    "0x0005",
205  };
206  store2->VerifySSLCipherSuites(expected_ciphers2,
207                                arraysize(expected_ciphers2));
208
209  CommandLine cl3(CommandLine::NO_PROGRAM);
210  cl3.AppendSwitchASCII(switches::kCipherSuiteBlacklist,
211                        "0x0004;MOAR;0x0005");
212  scoped_refptr<TestCommandLinePrefStore> store3 =
213      new TestCommandLinePrefStore(&cl3);
214  const char* const expected_ciphers3[] = {
215    "0x0004;MOAR;0x0005"
216  };
217  store3->VerifySSLCipherSuites(expected_ciphers3,
218                                arraysize(expected_ciphers3));
219}
220