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/browser/ui/webui/options2/preferences_browsertest.h" |
| 6 |
| 7 #include <iostream> |
| 8 #include <sstream> |
| 9 |
| 10 #include "base/json/json_reader.h" |
| 11 #include "base/json/json_writer.h" |
| 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/values.h" |
| 14 #include "chrome/browser/policy/browser_policy_connector.h" |
| 15 #include "chrome/browser/policy/policy_map.h" |
| 16 #include "chrome/browser/profiles/profile.h" |
| 17 #include "chrome/browser/ui/browser.h" |
| 18 #include "chrome/browser/ui/browser_tabstrip.h" |
| 19 #include "chrome/common/pref_names.h" |
| 20 #include "chrome/common/url_constants.h" |
| 21 #include "chrome/test/base/ui_test_utils.h" |
| 22 #include "content/public/browser/render_view_host.h" |
| 23 #include "content/public/browser/web_contents.h" |
| 24 #include "content/public/common/content_client.h" |
| 25 #include "content/public/test/browser_test_utils.h" |
| 26 #include "googleurl/src/gurl.h" |
| 27 #include "policy/policy_constants.h" |
| 28 #include "testing/gmock/include/gmock/gmock.h" |
| 29 #include "testing/gtest/include/gtest/gtest.h" |
| 30 |
| 31 #if defined(OS_CHROMEOS) |
| 32 #include "chrome/browser/chromeos/settings/cros_settings_names.h" |
| 33 #include "chrome/browser/chromeos/settings/cros_settings.h" |
| 34 #include "chrome/browser/chromeos/proxy_cros_settings_parser.h" |
| 35 #endif |
| 36 |
| 37 using testing::Return; |
| 38 |
| 39 namespace base { |
| 40 |
| 41 // Helper for using EXPECT_EQ() with base::Value. |
| 42 bool operator==(const base::Value& first, const base::Value& second) { |
| 43 return first.Equals(&second); |
| 44 } |
| 45 |
| 46 // Helper for pretty-printing the contents of base::Value in case of failures. |
| 47 void PrintTo(const Value& value, std::ostream* stream) { |
| 48 std::string json; |
| 49 JSONWriter::Write(&value, &json); |
| 50 *stream << json; |
| 51 } |
| 52 |
| 53 } // namespace base |
| 54 |
| 55 PreferencesBrowserTest::PreferencesBrowserTest() { |
| 56 } |
| 57 |
| 58 // Sets up a mock user policy provider. |
| 59 void PreferencesBrowserTest::SetUpInProcessBrowserTestFixture() { |
| 60 EXPECT_CALL(policy_provider_, IsInitializationComplete()) |
| 61 .WillRepeatedly(Return(true)); |
| 62 policy::BrowserPolicyConnector::SetPolicyProviderForTesting( |
| 63 &policy_provider_); |
| 64 }; |
| 65 |
| 66 // Navigates to the settings page, causing the JS preference handling classes to |
| 67 // be loaded and initialized. |
| 68 void PreferencesBrowserTest::SetUpOnMainThread() { |
| 69 ui_test_utils::NavigateToURL(browser(), |
| 70 GURL(chrome::kChromeUISettingsFrameURL)); |
| 71 content::WebContents* web_contents = chrome::GetActiveWebContents(browser()); |
| 72 ASSERT_TRUE(web_contents); |
| 73 render_view_host_ = web_contents->GetRenderViewHost(); |
| 74 ASSERT_TRUE(render_view_host_); |
| 75 } |
| 76 |
| 77 void PreferencesBrowserTest::VerifyValue(const base::DictionaryValue* dict, |
| 78 const std::string& key, |
| 79 base::Value* expected) { |
| 80 const base::Value* actual = NULL; |
| 81 EXPECT_TRUE(dict->Get(key, &actual)) << "Was checking key: " << key; |
| 82 EXPECT_EQ(*expected, *actual) << "Was checking key: " << key; |
| 83 delete expected; |
| 84 } |
| 85 |
| 86 void PreferencesBrowserTest::VerifyDict(const base::DictionaryValue* dict, |
| 87 const base::Value* value, |
| 88 const std::string& controlledBy, |
| 89 bool disabled) { |
| 90 VerifyValue(dict, "value", value->DeepCopy()); |
| 91 if (!controlledBy.empty()) { |
| 92 VerifyValue(dict, "controlledBy", |
| 93 base::Value::CreateStringValue(controlledBy)); |
| 94 } else { |
| 95 EXPECT_FALSE(dict->HasKey("controlledBy")); |
| 96 } |
| 97 |
| 98 if (disabled) |
| 99 VerifyValue(dict, "disabled", base::Value::CreateBooleanValue(true)); |
| 100 else if (dict->HasKey("disabled")) |
| 101 VerifyValue(dict, "disabled", base::Value::CreateBooleanValue(false)); |
| 102 } |
| 103 |
| 104 void PreferencesBrowserTest::VerifyPref(const base::DictionaryValue* prefs, |
| 105 const std::string& name, |
| 106 const base::Value* value, |
| 107 const std::string& controlledBy, |
| 108 bool disabled) { |
| 109 const base::Value* pref; |
| 110 const base::DictionaryValue* dict; |
| 111 ASSERT_TRUE(prefs->Get(name, &pref)); |
| 112 ASSERT_TRUE(pref->GetAsDictionary(&dict)); |
| 113 VerifyDict(dict, value, controlledBy, disabled); |
| 114 } |
| 115 |
| 116 void PreferencesBrowserTest::VerifyPrefs( |
| 117 const base::DictionaryValue* prefs, |
| 118 const std::vector<std::string>& names, |
| 119 const std::vector<base::Value*>& values, |
| 120 const std::string& controlledBy, |
| 121 bool disabled) { |
| 122 ASSERT_EQ(names.size(), values.size()); |
| 123 for (size_t i = 0; i < names.size(); ++i) |
| 124 VerifyPref(prefs, names[i], values[i], controlledBy, disabled); |
| 125 } |
| 126 |
| 127 void PreferencesBrowserTest::VerifySetPref(const std::string& name, |
| 128 const std::string& type, |
| 129 base::Value* set_value, |
| 130 base::Value* expected_value) { |
| 131 scoped_ptr<base::Value> set_value_ptr(set_value); |
| 132 scoped_ptr<base::Value> expected_value_ptr(expected_value); |
| 133 std::string set_value_json; |
| 134 base::JSONWriter::Write(set_value, &set_value_json); |
| 135 std::wstringstream javascript; |
| 136 javascript << "pref_changed_callback = function(notification) {" |
| 137 << " if (notification[0] == '" << name.c_str() << "') {" |
| 138 << " pref_changed_callback = function() {};" |
| 139 << " window.domAutomationController.send(" |
| 140 << " JSON.stringify(notification[1]));" |
| 141 << " }" |
| 142 << "};" |
| 143 << "chrome.send('observePrefs', ['pref_changed_callback'," |
| 144 << " '" << name.c_str() << "']);" |
| 145 << "Preferences.set" << type.c_str() << "Pref(" |
| 146 << " '" << name.c_str() << "'," |
| 147 << " " << set_value_json.c_str() << ");"; |
| 148 std::string actual_json; |
| 149 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString( |
| 150 render_view_host_, L"", javascript.str(), &actual_json)); |
| 151 |
| 152 base::Value* actual_value = base::JSONReader::Read(actual_json); |
| 153 const base::DictionaryValue* actual_dict; |
| 154 ASSERT_TRUE(actual_value); |
| 155 ASSERT_TRUE(actual_value->GetAsDictionary(&actual_dict)); |
| 156 VerifyDict(actual_dict, expected_value ? expected_value : set_value, |
| 157 "", false); |
| 158 } |
| 159 |
| 160 void PreferencesBrowserTest::FetchPrefs(const std::vector<std::string>& names, |
| 161 base::DictionaryValue** prefs) { |
| 162 *prefs = NULL; |
| 163 base::ListValue args_list; |
| 164 args_list.Append(base::Value::CreateStringValue("prefs_fetched_callback")); |
| 165 for (std::vector<std::string>::const_iterator name = names.begin(); |
| 166 name != names.end(); ++name) |
| 167 args_list.Append(base::Value::CreateStringValue(*name)); |
| 168 std::string args_json; |
| 169 base::JSONWriter::Write(&args_list, &args_json); |
| 170 std::wstringstream javascript; |
| 171 javascript << "prefs_fetched_callback = function(dict) {" |
| 172 << " window.domAutomationController.send(JSON.stringify(dict));" |
| 173 << "};" |
| 174 << "chrome.send('fetchPrefs', " << args_json.c_str() << ");"; |
| 175 |
| 176 std::string fetched_json; |
| 177 ASSERT_TRUE(content::ExecuteJavaScriptAndExtractString( |
| 178 render_view_host_, L"", javascript.str(), &fetched_json)); |
| 179 base::Value* fetched_value = base::JSONReader::Read(fetched_json); |
| 180 base::DictionaryValue* fetched_dict; |
| 181 ASSERT_TRUE(fetched_value); |
| 182 ASSERT_TRUE(fetched_value->GetAsDictionary(&fetched_dict)); |
| 183 *prefs = fetched_dict; |
| 184 } |
| 185 |
| 186 void PreferencesBrowserTest::SetUserPolicies( |
| 187 const std::vector<std::string>& names, |
| 188 const std::vector<base::Value*>& values, |
| 189 policy::PolicyLevel level) { |
| 190 ASSERT_TRUE(names.size() == values.size()); |
| 191 policy::PolicyMap map; |
| 192 for (size_t i = 0; i < names.size(); ++i) |
| 193 map.Set(names[i], level, policy::POLICY_SCOPE_USER, values[i]->DeepCopy()); |
| 194 policy_provider_.UpdateChromePolicy(map); |
| 195 } |
| 196 |
| 197 void PreferencesBrowserTest::DeleteValues(std::vector<base::Value*>& values){ |
| 198 for (std::vector<base::Value*>::iterator value = values.begin(); |
| 199 value != values.end(); ++value) |
| 200 delete *value; |
| 201 values.clear(); |
| 202 } |
| 203 |
| 204 // Verifies that pref values received by observer callbacks are decorated |
| 205 // correctly when the prefs are set from JavaScript. |
| 206 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, SetPrefs) { |
| 207 // Prefs handled by CoreOptionsHandler. |
| 208 VerifySetPref(prefs::kAlternateErrorPagesEnabled, "Boolean", |
| 209 base::Value::CreateBooleanValue(false), NULL); |
| 210 VerifySetPref(prefs::kRestoreOnStartup, "Integer", |
| 211 base::Value::CreateIntegerValue(4), NULL); |
| 212 VerifySetPref(prefs::kEnterpriseWebStoreName, "String", |
| 213 base::Value::CreateStringValue("Store"), NULL); |
| 214 VerifySetPref(prefs::kEnterpriseWebStoreURL, "URL", |
| 215 base::Value::CreateStringValue("http://www.google.com"), |
| 216 base::Value::CreateStringValue("http://www.google.com/")); |
| 217 } |
| 218 |
| 219 // Verifies that pref values are decorated correctly when fetched from |
| 220 // JavaScript. |
| 221 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, FetchPrefs) { |
| 222 // Pref names. |
| 223 std::vector<std::string> pref_names; |
| 224 // Boolean pref. |
| 225 pref_names.push_back(prefs::kAlternateErrorPagesEnabled); |
| 226 // Integer pref. |
| 227 pref_names.push_back(prefs::kRestoreOnStartup); |
| 228 // String pref. |
| 229 pref_names.push_back(prefs::kEnterpriseWebStoreName); |
| 230 // URL pref. |
| 231 pref_names.push_back(prefs::kEnterpriseWebStoreURL); |
| 232 // List pref. |
| 233 pref_names.push_back(prefs::kURLsToRestoreOnStartup); |
| 234 |
| 235 // Corresponding policy names. |
| 236 std::vector<std::string> policy_names; |
| 237 policy_names.push_back(policy::key::kAlternateErrorPagesEnabled); |
| 238 policy_names.push_back(policy::key::kRestoreOnStartup); |
| 239 policy_names.push_back(policy::key::kEnterpriseWebStoreName); |
| 240 policy_names.push_back(policy::key::kEnterpriseWebStoreURL); |
| 241 policy_names.push_back(policy::key::kRestoreOnStartupURLs); |
| 242 |
| 243 // Default values. |
| 244 std::vector<base::Value*> values; |
| 245 values.push_back(base::Value::CreateBooleanValue(true)); |
| 246 #if defined(OS_CHROMEOS) |
| 247 values.push_back(base::Value::CreateIntegerValue(1)); |
| 248 #else |
| 249 values.push_back(base::Value::CreateIntegerValue(5)); |
| 250 #endif |
| 251 values.push_back(base::Value::CreateStringValue("")); |
| 252 values.push_back(base::Value::CreateStringValue("")); |
| 253 values.push_back(new base::ListValue); |
| 254 |
| 255 // Verify default values are fetched and decorated correctly. |
| 256 base::DictionaryValue* fetched; |
| 257 FetchPrefs(pref_names, &fetched); |
| 258 if (fetched) |
| 259 VerifyPrefs(fetched, pref_names, values, "", false); |
| 260 delete fetched; |
| 261 |
| 262 // Set recommended values. |
| 263 DeleteValues(values); |
| 264 values.push_back(base::Value::CreateBooleanValue(false)); |
| 265 values.push_back(base::Value::CreateIntegerValue(4)); |
| 266 values.push_back(base::Value::CreateStringValue("Store")); |
| 267 values.push_back(base::Value::CreateStringValue("http://www.google.com")); |
| 268 base::ListValue* list = new base::ListValue; |
| 269 list->Append(base::Value::CreateStringValue("http://www.google.com")); |
| 270 list->Append(base::Value::CreateStringValue("http://example.com")); |
| 271 values.push_back(list); |
| 272 SetUserPolicies(policy_names, values, policy::POLICY_LEVEL_RECOMMENDED); |
| 273 |
| 274 // Verify recommended values are fetched and decorated correctly. |
| 275 FetchPrefs(pref_names, &fetched); |
| 276 if (fetched) |
| 277 VerifyPrefs(fetched, pref_names, values, "recommended", false); |
| 278 delete fetched; |
| 279 |
| 280 // Set mandatory values. |
| 281 SetUserPolicies(policy_names, values, policy::POLICY_LEVEL_MANDATORY); |
| 282 |
| 283 // Verify mandatory values are fetched and decorated correctly. |
| 284 FetchPrefs(pref_names, &fetched); |
| 285 if (fetched) |
| 286 VerifyPrefs(fetched, pref_names, values, "policy", true); |
| 287 delete fetched; |
| 288 |
| 289 DeleteValues(values); |
| 290 } |
| 291 |
| 292 #if defined(OS_CHROMEOS) |
| 293 // Verifies that pref values handled by the CoreChromeOSOptionsHandler class |
| 294 // are decorated correctly when requested from JavaScript. |
| 295 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ChromeOSDeviceFetchPrefs) { |
| 296 // Pref names. |
| 297 std::vector<std::string> names; |
| 298 // Boolean pref. |
| 299 names.push_back(chromeos::kAccountsPrefAllowGuest); |
| 300 // String pref. |
| 301 names.push_back(chromeos::kReleaseChannel); |
| 302 // List pref. |
| 303 names.push_back(chromeos::kAccountsPrefUsers); |
| 304 |
| 305 // Default pref values. |
| 306 std::vector<base::Value*> values; |
| 307 values.push_back(base::Value::CreateBooleanValue(true)); |
| 308 values.push_back(base::Value::CreateStringValue("")); |
| 309 values.push_back(new base::ListValue); |
| 310 |
| 311 // Verify default values are fetched and decorated correctly. |
| 312 base::DictionaryValue* fetched; |
| 313 FetchPrefs(names, &fetched); |
| 314 if (fetched) |
| 315 VerifyPrefs(fetched, names, values, "", true); |
| 316 delete fetched; |
| 317 |
| 318 // Set mandatory values. |
| 319 DeleteValues(values); |
| 320 values.push_back(base::Value::CreateBooleanValue(false)); |
| 321 values.push_back(base::Value::CreateStringValue("stable-channel")); |
| 322 base::ListValue* list = new base::ListValue; |
| 323 list->Append(base::Value::CreateStringValue("me@google.com")); |
| 324 list->Append(base::Value::CreateStringValue("you@google.com")); |
| 325 values.push_back(list); |
| 326 ASSERT_EQ(names.size(), values.size()); |
| 327 chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); |
| 328 for (size_t i = 0; i < names.size(); ++i) |
| 329 cros_settings->Set(names[i], *values[i]); |
| 330 |
| 331 // Verify mandatory values are fetched and decorated correctly. |
| 332 DeleteValues(values); |
| 333 values.push_back(base::Value::CreateBooleanValue(false)); |
| 334 values.push_back(base::Value::CreateStringValue("stable-channel")); |
| 335 list = new base::ListValue; |
| 336 base::DictionaryValue* dict = new base::DictionaryValue; |
| 337 dict->SetString("username", "me@google.com"); |
| 338 dict->SetString("name", "me@google.com"); |
| 339 dict->SetString("email", ""); |
| 340 dict->SetBoolean("owner", false); |
| 341 list->Append(dict); |
| 342 dict = new base::DictionaryValue; |
| 343 dict->SetString("username", "you@google.com"); |
| 344 dict->SetString("name", "you@google.com"); |
| 345 dict->SetString("email", ""); |
| 346 dict->SetBoolean("owner", false); |
| 347 list->Append(dict); |
| 348 values.push_back(list); |
| 349 FetchPrefs(names, &fetched); |
| 350 // FIXME(bartfab): Find a way to simulate enterprise enrollment in browser |
| 351 // tests. Only if Chrome thinks that it is enrolled will the device prefs be |
| 352 // decorated with "controlledBy: policy". |
| 353 if (fetched) |
| 354 VerifyPrefs(fetched, names, values, "", true); |
| 355 delete fetched; |
| 356 |
| 357 DeleteValues(values); |
| 358 } |
| 359 |
| 360 // Verifies that pref values handled by the Chrome OS proxy settings parser are |
| 361 // decorated correctly when requested from JavaScript. |
| 362 IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ChromeOSProxyFetchPrefs) { |
| 363 // Pref names. |
| 364 std::vector<std::string> names; |
| 365 // Boolean pref. |
| 366 names.push_back(chromeos::kProxySingle); |
| 367 // Integer pref. |
| 368 names.push_back(chromeos::kProxySingleHttpPort); |
| 369 // String pref. |
| 370 names.push_back(chromeos::kProxySingleHttp); |
| 371 // List pref. |
| 372 names.push_back(chromeos::kProxyIgnoreList); |
| 373 |
| 374 // Default values. |
| 375 std::vector<base::Value*> values; |
| 376 values.push_back(base::Value::CreateBooleanValue(false)); |
| 377 values.push_back(base::Value::CreateStringValue("")); |
| 378 values.push_back(base::Value::CreateStringValue("")); |
| 379 values.push_back(new base::ListValue()); |
| 380 |
| 381 // Verify default values are fetched and decorated correctly. |
| 382 base::DictionaryValue* fetched; |
| 383 FetchPrefs(names, &fetched); |
| 384 if (fetched) |
| 385 VerifyPrefs(fetched, names, values, "", false); |
| 386 delete fetched; |
| 387 |
| 388 // Set user-modified values. |
| 389 DeleteValues(values); |
| 390 values.push_back(base::Value::CreateBooleanValue(true)); |
| 391 values.push_back(base::Value::CreateIntegerValue(8080)); |
| 392 values.push_back(base::Value::CreateStringValue("127.0.0.1")); |
| 393 base::ListValue* list = new base::ListValue(); |
| 394 list->Append(base::Value::CreateStringValue("www.google.com")); |
| 395 list->Append(base::Value::CreateStringValue("example.com")); |
| 396 values.push_back(list); |
| 397 ASSERT_EQ(names.size(), values.size()); |
| 398 Profile* profile = browser()->profile(); |
| 399 // Do not set the Boolean pref. It will toogle automatically. |
| 400 for (size_t i = 1; i < names.size(); ++i) |
| 401 chromeos::proxy_cros_settings_parser::SetProxyPrefValue( |
| 402 profile, names[i], values[i]->DeepCopy()); |
| 403 |
| 404 // Verify user-modified values are fetched and decorated correctly. |
| 405 FetchPrefs(names, &fetched); |
| 406 if (fetched) |
| 407 VerifyPrefs(fetched, names, values, "", false); |
| 408 delete fetched; |
| 409 |
| 410 DeleteValues(values); |
| 411 } |
| 412 #endif |
OLD | NEW |