preferences_browsertest.cc revision 4e180b6a0b4720a9b8e9e959a882386f690f08ff
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/options/preferences_browsertest.h" 6 7#include <iostream> 8#include <sstream> 9 10#include "base/callback.h" 11#include "base/json/json_reader.h" 12#include "base/json/json_writer.h" 13#include "base/memory/scoped_ptr.h" 14#include "base/prefs/pref_service.h" 15#include "base/stl_util.h" 16#include "base/values.h" 17#include "chrome/browser/chrome_notification_types.h" 18#include "chrome/browser/policy/browser_policy_connector.h" 19#include "chrome/browser/policy/external_data_fetcher.h" 20#include "chrome/browser/policy/policy_map.h" 21#include "chrome/browser/policy/policy_types.h" 22#include "chrome/browser/profiles/profile.h" 23#include "chrome/browser/ui/browser.h" 24#include "chrome/browser/ui/tabs/tab_strip_model.h" 25#include "chrome/common/pref_names.h" 26#include "chrome/common/url_constants.h" 27#include "chrome/test/base/ui_test_utils.h" 28#include "content/public/browser/notification_details.h" 29#include "content/public/browser/notification_source.h" 30#include "content/public/browser/render_view_host.h" 31#include "content/public/browser/web_contents.h" 32#include "content/public/test/browser_test_utils.h" 33#include "policy/policy_constants.h" 34#include "testing/gtest/include/gtest/gtest.h" 35#include "url/gurl.h" 36 37#if defined(OS_CHROMEOS) 38#include "base/strings/stringprintf.h" 39#include "chrome/browser/browser_process.h" 40#include "chrome/browser/chromeos/net/proxy_config_handler.h" 41#include "chrome/browser/chromeos/proxy_cros_settings_parser.h" 42#include "chrome/browser/chromeos/settings/cros_settings.h" 43#include "chrome/browser/prefs/proxy_config_dictionary.h" 44#include "chromeos/dbus/dbus_thread_manager.h" 45#include "chromeos/dbus/shill_profile_client.h" 46#include "chromeos/dbus/shill_service_client.h" 47#include "chromeos/network/favorite_state.h" 48#include "chromeos/network/network_state.h" 49#include "chromeos/network/network_state_handler.h" 50#include "chromeos/settings/cros_settings_names.h" 51#include "content/public/test/test_utils.h" 52#include "third_party/cros_system_api/dbus/service_constants.h" 53#endif 54 55using testing::AllOf; 56using testing::AnyNumber; 57using testing::Mock; 58using testing::Property; 59using testing::Return; 60using testing::_; 61 62namespace base { 63 64// Helper for using EXPECT_EQ() with base::Value. 65bool operator==(const Value& first, const Value& second) { 66 return first.Equals(&second); 67} 68 69// Helper for pretty-printing the contents of base::Value in case of failures. 70void PrintTo(const Value& value, std::ostream* stream) { 71 std::string json; 72 JSONWriter::Write(&value, &json); 73 *stream << json; 74} 75 76} // namespace base 77 78// Googlemock matcher for base::Value. 79MATCHER_P(EqualsValue, expected, "") { 80 return arg && arg->Equals(expected); 81} 82 83PreferencesBrowserTest::PreferencesBrowserTest() { 84} 85 86PreferencesBrowserTest::~PreferencesBrowserTest() { 87} 88 89// Navigates to the settings page, causing the JavaScript pref handling code to 90// load and injects JavaScript testing code. 91void PreferencesBrowserTest::SetUpOnMainThread() { 92 ui_test_utils::NavigateToURL(browser(), 93 GURL(chrome::kChromeUISettingsFrameURL)); 94 SetUpPrefs(); 95} 96 97void PreferencesBrowserTest::SetUpPrefs() { 98 content::WebContents* web_contents = 99 browser()->tab_strip_model()->GetActiveWebContents(); 100 ASSERT_TRUE(web_contents); 101 render_view_host_ = web_contents->GetRenderViewHost(); 102 ASSERT_TRUE(render_view_host_); 103 pref_service_ = browser()->profile()->GetPrefs(); 104 pref_change_registrar_.Init(pref_service_); 105 ASSERT_TRUE(content::ExecuteScript(render_view_host_, 106 "function TestEnv() {" 107 " this.sentinelName_ = 'download.prompt_for_download';" 108 " this.prefs_ = [];" 109 " TestEnv.instance_ = this;" 110 "}" 111 "" 112 "TestEnv.handleEvent = function(event) {" 113 " var env = TestEnv.instance_;" 114 " var name = event.type;" 115 " env.removePrefListener_(name);" 116 " if (name == TestEnv.sentinelName_)" 117 " env.sentinelValue_ = event.value.value;" 118 " else" 119 " env.reply_[name] = event.value;" 120 " if (env.fetching_ && !--env.fetching_ ||" 121 " !env.fetching_ && name == env.sentinelName_) {" 122 " env.removePrefListeners_();" 123 " window.domAutomationController.send(JSON.stringify(env.reply_));" 124 " delete env.reply_;" 125 " }" 126 "};" 127 "" 128 "TestEnv.prototype = {" 129 " addPrefListener_: function(name) {" 130 " Preferences.getInstance().addEventListener(name," 131 " TestEnv.handleEvent);" 132 " }," 133 "" 134 " addPrefListeners_: function() {" 135 " for (var i in this.prefs_)" 136 " this.addPrefListener_(this.prefs_[i]);" 137 " }," 138 "" 139 " removePrefListener_: function(name) {" 140 " Preferences.getInstance().removeEventListener(name," 141 " TestEnv.handleEvent);" 142 " }," 143 "" 144 " removePrefListeners_: function() {" 145 " for (var i in this.prefs_)" 146 " this.removePrefListener_(this.prefs_[i]);" 147 " }," 148 "" 149 "" 150 " addPref: function(name) {" 151 " this.prefs_.push(name);" 152 " }," 153 "" 154 " setupAndReply: function() {" 155 " this.reply_ = {};" 156 " Preferences.instance_ = new Preferences();" 157 " this.addPref(this.sentinelName_);" 158 " this.fetching_ = this.prefs_.length;" 159 " this.addPrefListeners_();" 160 " Preferences.getInstance().initialize();" 161 " }," 162 "" 163 " runAndReply: function(test) {" 164 " this.reply_ = {};" 165 " this.addPrefListeners_();" 166 " test();" 167 " this.sentinelValue_ = !this.sentinelValue_;" 168 " Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_," 169 " true);" 170 " }," 171 "" 172 " startObserving: function() {" 173 " this.reply_ = {};" 174 " this.addPrefListeners_();" 175 " }," 176 "" 177 " finishObservingAndReply: function() {" 178 " this.sentinelValue_ = !this.sentinelValue_;" 179 " Preferences.setBooleanPref(this.sentinelName_, this.sentinelValue_," 180 " true);" 181 " }" 182 "};")); 183} 184 185// Forwards notifications received when pref values change in the backend. 186void PreferencesBrowserTest::OnPreferenceChanged(const std::string& pref_name) { 187 OnCommit(pref_service_->FindPreference(pref_name.c_str())); 188} 189 190void PreferencesBrowserTest::SetUpInProcessBrowserTestFixture() { 191 // Sets up a mock policy provider for user and device policies. 192 EXPECT_CALL(policy_provider_, IsInitializationComplete(_)) 193 .WillRepeatedly(Return(true)); 194 EXPECT_CALL(policy_provider_, RegisterPolicyDomain(_)) 195 .Times(AnyNumber()); 196 policy::BrowserPolicyConnector::SetPolicyProviderForTesting( 197 &policy_provider_); 198}; 199 200void PreferencesBrowserTest::TearDownInProcessBrowserTestFixture() { 201 STLDeleteElements(&default_values_); 202 STLDeleteElements(&non_default_values_); 203} 204 205void PreferencesBrowserTest::SetUserPolicies( 206 const std::vector<std::string>& names, 207 const std::vector<base::Value*>& values, 208 policy::PolicyLevel level) { 209 policy::PolicyMap map; 210 for (size_t i = 0; i < names.size(); ++i) { 211 map.Set(names[i], level, policy::POLICY_SCOPE_USER, 212 values[i]->DeepCopy(), NULL); 213 } 214 policy_provider_.UpdateChromePolicy(map); 215} 216 217void PreferencesBrowserTest::ClearUserPolicies() { 218 policy::PolicyMap empty_policy_map; 219 policy_provider_.UpdateChromePolicy(empty_policy_map); 220} 221 222void PreferencesBrowserTest::SetUserValues( 223 const std::vector<std::string>& names, 224 const std::vector<base::Value*>& values) { 225 for (size_t i = 0; i < names.size(); ++i) 226 pref_service_->Set(names[i].c_str(), *values[i]); 227} 228 229void PreferencesBrowserTest::VerifyKeyValue(const base::DictionaryValue& dict, 230 const std::string& key, 231 const base::Value& expected) { 232 const base::Value* actual = NULL; 233 EXPECT_TRUE(dict.Get(key, &actual)) << "Was checking key: " << key; 234 if (actual) 235 EXPECT_EQ(expected, *actual) << "Was checking key: " << key; 236} 237 238void PreferencesBrowserTest::VerifyPref(const base::DictionaryValue* prefs, 239 const std::string& name, 240 const base::Value* value, 241 const std::string& controlledBy, 242 bool disabled, 243 bool uncommitted) { 244 const base::Value* pref = NULL; 245 const base::DictionaryValue* dict = NULL; 246 ASSERT_TRUE(prefs->GetWithoutPathExpansion(name, &pref)); 247 ASSERT_TRUE(pref->GetAsDictionary(&dict)); 248 VerifyKeyValue(*dict, "value", *value); 249 if (!controlledBy.empty()) 250 VerifyKeyValue(*dict, "controlledBy", base::StringValue(controlledBy)); 251 else 252 EXPECT_FALSE(dict->HasKey("controlledBy")); 253 254 if (disabled) 255 VerifyKeyValue(*dict, "disabled", base::FundamentalValue(true)); 256 else if (dict->HasKey("disabled")) 257 VerifyKeyValue(*dict, "disabled", base::FundamentalValue(false)); 258 259 if (uncommitted) 260 VerifyKeyValue(*dict, "uncommitted", base::FundamentalValue(true)); 261 else if (dict->HasKey("uncommitted")) 262 VerifyKeyValue(*dict, "uncommitted", base::FundamentalValue(false)); 263} 264 265void PreferencesBrowserTest::VerifyObservedPref(const std::string& json, 266 const std::string& name, 267 const base::Value* value, 268 const std::string& controlledBy, 269 bool disabled, 270 bool uncommitted) { 271 scoped_ptr<base::Value> observed_value_ptr(base::JSONReader::Read(json)); 272 const base::DictionaryValue* observed_dict; 273 ASSERT_TRUE(observed_value_ptr.get()); 274 ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict)); 275 VerifyPref(observed_dict, name, value, controlledBy, disabled, uncommitted); 276} 277 278void PreferencesBrowserTest::VerifyObservedPrefs( 279 const std::string& json, 280 const std::vector<std::string>& names, 281 const std::vector<base::Value*>& values, 282 const std::string& controlledBy, 283 bool disabled, 284 bool uncommitted) { 285 scoped_ptr<base::Value> observed_value_ptr(base::JSONReader::Read(json)); 286 const base::DictionaryValue* observed_dict; 287 ASSERT_TRUE(observed_value_ptr.get()); 288 ASSERT_TRUE(observed_value_ptr->GetAsDictionary(&observed_dict)); 289 for (size_t i = 0; i < names.size(); ++i) 290 VerifyPref(observed_dict, names[i], values[i], controlledBy, disabled, 291 uncommitted); 292} 293 294void PreferencesBrowserTest::ExpectNoCommit(const std::string& name) { 295 pref_change_registrar_.Add( 296 name.c_str(), 297 base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, 298 base::Unretained(this))); 299 EXPECT_CALL(*this, OnCommit(Property(&PrefService::Preference::name, name))) 300 .Times(0); 301} 302 303void PreferencesBrowserTest::ExpectSetCommit(const std::string& name, 304 const base::Value* value) { 305 pref_change_registrar_.Add( 306 name.c_str(), 307 base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, 308 base::Unretained(this))); 309 EXPECT_CALL(*this, OnCommit(AllOf( 310 Property(&PrefService::Preference::name, name), 311 Property(&PrefService::Preference::IsUserControlled, true), 312 Property(&PrefService::Preference::GetValue, EqualsValue(value))))); 313} 314 315void PreferencesBrowserTest::ExpectClearCommit(const std::string& name) { 316 pref_change_registrar_.Add( 317 name.c_str(), 318 base::Bind(&PreferencesBrowserTest::OnPreferenceChanged, 319 base::Unretained(this))); 320 EXPECT_CALL(*this, OnCommit(AllOf( 321 Property(&PrefService::Preference::name, name), 322 Property(&PrefService::Preference::IsUserControlled, false)))); 323} 324 325void PreferencesBrowserTest::VerifyAndClearExpectations() { 326 Mock::VerifyAndClearExpectations(this); 327 pref_change_registrar_.RemoveAll(); 328} 329 330void PreferencesBrowserTest::SetupJavaScriptTestEnvironment( 331 const std::vector<std::string>& pref_names, 332 std::string* observed_json) const { 333 std::stringstream javascript; 334 javascript << "var testEnv = new TestEnv();"; 335 for (std::vector<std::string>::const_iterator name = pref_names.begin(); 336 name != pref_names.end(); ++name) 337 javascript << "testEnv.addPref('" << name->c_str() << "');"; 338 javascript << "testEnv.setupAndReply();"; 339 std::string temp_observed_json; 340 if (!observed_json) 341 observed_json = &temp_observed_json; 342 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 343 render_view_host_, javascript.str(), observed_json)); 344} 345 346void PreferencesBrowserTest::SetPref(const std::string& name, 347 const std::string& type, 348 const base::Value* value, 349 bool commit, 350 std::string* observed_json) { 351 scoped_ptr<base::Value> commit_ptr(new base::FundamentalValue(commit)); 352 std::stringstream javascript; 353 javascript << "testEnv.runAndReply(function() {" 354 << " Preferences.set" << type << "Pref(" 355 << " '" << name << "'," 356 << " " << *value << "," 357 << " " << *commit_ptr << ");" 358 << "});"; 359 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 360 render_view_host_, javascript.str(), observed_json)); 361} 362 363void PreferencesBrowserTest::VerifySetPref(const std::string& name, 364 const std::string& type, 365 const base::Value* value, 366 bool commit) { 367 if (commit) 368 ExpectSetCommit(name, value); 369 else 370 ExpectNoCommit(name); 371 std::string observed_json; 372 SetPref(name, type, value, commit, &observed_json); 373 VerifyObservedPref(observed_json, name, value, std::string(), false, !commit); 374 VerifyAndClearExpectations(); 375} 376 377void PreferencesBrowserTest::VerifyClearPref(const std::string& name, 378 const base::Value* value, 379 bool commit) { 380 if (commit) 381 ExpectClearCommit(name); 382 else 383 ExpectNoCommit(name); 384 scoped_ptr<base::Value> commit_ptr(new base::FundamentalValue(commit)); 385 std::string commit_json; 386 base::JSONWriter::Write(commit_ptr.get(), &commit_json); 387 std::stringstream javascript; 388 javascript << "testEnv.runAndReply(function() {" 389 << " Preferences.clearPref(" 390 << " '" << name.c_str() << "'," 391 << " " << commit_json.c_str() << ");});"; 392 std::string observed_json; 393 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 394 render_view_host_, javascript.str(), &observed_json)); 395 VerifyObservedPref(observed_json, name, value, "recommended", false, !commit); 396 VerifyAndClearExpectations(); 397} 398 399void PreferencesBrowserTest::VerifyCommit(const std::string& name, 400 const base::Value* value, 401 const std::string& controlledBy) { 402 std::stringstream javascript; 403 javascript << "testEnv.runAndReply(function() {" 404 << " Preferences.getInstance().commitPref(" 405 << " '" << name.c_str() << "');});"; 406 std::string observed_json; 407 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 408 render_view_host_, javascript.str(), &observed_json)); 409 VerifyObservedPref(observed_json, name, value, controlledBy, false, false); 410} 411 412void PreferencesBrowserTest::VerifySetCommit(const std::string& name, 413 const base::Value* value) { 414 ExpectSetCommit(name, value); 415 VerifyCommit(name, value, std::string()); 416 VerifyAndClearExpectations(); 417} 418 419void PreferencesBrowserTest::VerifyClearCommit(const std::string& name, 420 const base::Value* value) { 421 ExpectClearCommit(name); 422 VerifyCommit(name, value, "recommended"); 423 VerifyAndClearExpectations(); 424} 425 426void PreferencesBrowserTest::VerifyRollback(const std::string& name, 427 const base::Value* value, 428 const std::string& controlledBy) { 429 ExpectNoCommit(name); 430 std::stringstream javascript; 431 javascript << "testEnv.runAndReply(function() {" 432 << " Preferences.getInstance().rollbackPref(" 433 << " '" << name.c_str() << "');});"; 434 std::string observed_json; 435 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 436 render_view_host_, javascript.str(), &observed_json)); 437 VerifyObservedPref(observed_json, name, value, controlledBy, false, true); 438 VerifyAndClearExpectations(); 439} 440 441void PreferencesBrowserTest::StartObserving() { 442 ASSERT_TRUE(content::ExecuteScript( 443 render_view_host_, "testEnv.startObserving();")); 444} 445 446void PreferencesBrowserTest::FinishObserving(std::string* observed_json) { 447 ASSERT_TRUE(content::ExecuteScriptAndExtractString( 448 render_view_host_, 449 "testEnv.finishObservingAndReply();", 450 observed_json)); 451} 452 453void PreferencesBrowserTest::UseDefaultTestPrefs(bool includeListPref) { 454 // Boolean pref. 455 types_.push_back("Boolean"); 456 pref_names_.push_back(prefs::kAlternateErrorPagesEnabled); 457 policy_names_.push_back(policy::key::kAlternateErrorPagesEnabled); 458 non_default_values_.push_back(new base::FundamentalValue(false)); 459 460 // Integer pref. 461 types_.push_back("Integer"); 462 pref_names_.push_back(prefs::kRestoreOnStartup); 463 policy_names_.push_back(policy::key::kRestoreOnStartup); 464 non_default_values_.push_back(new base::FundamentalValue(4)); 465 466 // List pref. 467 if (includeListPref) { 468 types_.push_back("List"); 469 pref_names_.push_back(prefs::kURLsToRestoreOnStartup); 470 policy_names_.push_back(policy::key::kRestoreOnStartupURLs); 471 base::ListValue* list = new base::ListValue; 472 list->Append(new base::StringValue("http://www.google.com")); 473 list->Append(new base::StringValue("http://example.com")); 474 non_default_values_.push_back(list); 475 } 476 477 // Retrieve default values. 478 for (std::vector<std::string>::const_iterator name = pref_names_.begin(); 479 name != pref_names_.end(); ++name) { 480 default_values_.push_back( 481 pref_service_->GetDefaultPrefValue(name->c_str())->DeepCopy()); 482 } 483} 484 485// Verifies that initializing the JavaScript Preferences class fires the correct 486// notifications in JavaScript. 487IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, FetchPrefs) { 488 UseDefaultTestPrefs(true); 489 std::string observed_json; 490 491 // Verify notifications when default values are in effect. 492 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 493 VerifyObservedPrefs( 494 observed_json, pref_names_, default_values_, std::string(), false, false); 495 496 // Verify notifications when recommended values are in effect. 497 SetUserPolicies(policy_names_, non_default_values_, 498 policy::POLICY_LEVEL_RECOMMENDED); 499 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 500 VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, 501 "recommended", false, false); 502 503 // Verify notifications when mandatory values are in effect. 504 SetUserPolicies(policy_names_, non_default_values_, 505 policy::POLICY_LEVEL_MANDATORY); 506 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 507 VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, 508 "policy", true, false); 509 510 // Verify notifications when user-modified values are in effect. 511 ClearUserPolicies(); 512 SetUserValues(pref_names_, non_default_values_); 513 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 514 VerifyObservedPrefs(observed_json, 515 pref_names_, 516 non_default_values_, 517 std::string(), 518 false, 519 false); 520} 521 522// Verifies that setting a user-modified pref value through the JavaScript 523// Preferences class fires the correct notification in JavaScript and causes the 524// change to be committed to the C++ backend. 525IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, SetPrefs) { 526 UseDefaultTestPrefs(false); 527 528 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 529 for (size_t i = 0; i < pref_names_.size(); ++i) 530 VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], true); 531} 532 533// Verifies that clearing a user-modified pref value through the JavaScript 534// Preferences class fires the correct notification in JavaScript and causes the 535// change to be committed to the C++ backend. 536IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ClearPrefs) { 537 UseDefaultTestPrefs(false); 538 539 SetUserPolicies(policy_names_, default_values_, 540 policy::POLICY_LEVEL_RECOMMENDED); 541 SetUserValues(pref_names_, non_default_values_); 542 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 543 for (size_t i = 0; i < pref_names_.size(); ++i) 544 VerifyClearPref(pref_names_[i], default_values_[i], true); 545} 546 547// Verifies that when the user-modified value of a dialog pref is set and the 548// change then committed through the JavaScript Preferences class, the correct 549// notifications fire and a commit to the C++ backend occurs in the latter step 550// only. 551IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetCommit) { 552 UseDefaultTestPrefs(false); 553 554 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 555 for (size_t i = 0; i < pref_names_.size(); ++i) { 556 VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); 557 VerifySetCommit(pref_names_[i], non_default_values_[i]); 558 } 559} 560 561// Verifies that when the user-modified value of a dialog pref is set and the 562// change then rolled back through the JavaScript Preferences class, the correct 563// notifications fire and no commit to the C++ backend occurs. 564IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsSetRollback) { 565 UseDefaultTestPrefs(false); 566 567 // Verify behavior when default values are in effect. 568 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 569 for (size_t i = 0; i < pref_names_.size(); ++i) { 570 VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); 571 VerifyRollback(pref_names_[i], default_values_[i], std::string()); 572 } 573 574 // Verify behavior when recommended values are in effect. 575 SetUserPolicies(policy_names_, default_values_, 576 policy::POLICY_LEVEL_RECOMMENDED); 577 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 578 for (size_t i = 0; i < pref_names_.size(); ++i) { 579 VerifySetPref(pref_names_[i], types_[i], non_default_values_[i], false); 580 VerifyRollback(pref_names_[i], default_values_[i], "recommended"); 581 } 582} 583 584// Verifies that when the user-modified value of a dialog pref is cleared and 585// the change then committed through the JavaScript Preferences class, the 586// correct notifications fire and a commit to the C++ backend occurs in the 587// latter step only. 588IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearCommit) { 589 UseDefaultTestPrefs(false); 590 591 SetUserPolicies(policy_names_, default_values_, 592 policy::POLICY_LEVEL_RECOMMENDED); 593 SetUserValues(pref_names_, non_default_values_); 594 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 595 for (size_t i = 0; i < pref_names_.size(); ++i) { 596 VerifyClearPref(pref_names_[i], default_values_[i], false); 597 VerifyClearCommit(pref_names_[i], default_values_[i]); 598 } 599} 600 601// Verifies that when the user-modified value of a dialog pref is cleared and 602// the change then rolled back through the JavaScript Preferences class, the 603// correct notifications fire and no commit to the C++ backend occurs. 604IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, DialogPrefsClearRollback) { 605 UseDefaultTestPrefs(false); 606 607 SetUserPolicies(policy_names_, default_values_, 608 policy::POLICY_LEVEL_RECOMMENDED); 609 SetUserValues(pref_names_, non_default_values_); 610 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 611 for (size_t i = 0; i < pref_names_.size(); ++i) { 612 VerifyClearPref(pref_names_[i], default_values_[i], false); 613 VerifyRollback(pref_names_[i], non_default_values_[i], std::string()); 614 } 615} 616 617// Verifies that when preference values change in the C++ backend, the correct 618// notifications fire in JavaScript. 619IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, NotificationsOnBackendChanges) { 620 UseDefaultTestPrefs(false); 621 std::string observed_json; 622 623 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 624 625 // Verify notifications when recommended values come into effect. 626 StartObserving(); 627 SetUserPolicies(policy_names_, non_default_values_, 628 policy::POLICY_LEVEL_RECOMMENDED); 629 FinishObserving(&observed_json); 630 VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, 631 "recommended", false, false); 632 633 // Verify notifications when mandatory values come into effect. 634 StartObserving(); 635 SetUserPolicies(policy_names_, non_default_values_, 636 policy::POLICY_LEVEL_MANDATORY); 637 FinishObserving(&observed_json); 638 VerifyObservedPrefs(observed_json, pref_names_, non_default_values_, 639 "policy", true, false); 640 641 // Verify notifications when default values come into effect. 642 StartObserving(); 643 ClearUserPolicies(); 644 FinishObserving(&observed_json); 645 VerifyObservedPrefs( 646 observed_json, pref_names_, default_values_, std::string(), false, false); 647 648 // Verify notifications when user-modified values come into effect. 649 StartObserving(); 650 SetUserValues(pref_names_, non_default_values_); 651 FinishObserving(&observed_json); 652 VerifyObservedPrefs(observed_json, 653 pref_names_, 654 non_default_values_, 655 std::string(), 656 false, 657 false); 658} 659 660#if defined(OS_CHROMEOS) 661 662// Verifies that initializing the JavaScript Preferences class fires the correct 663// notifications in JavaScript for pref values handled by the 664// CoreChromeOSOptionsHandler class. 665IN_PROC_BROWSER_TEST_F(PreferencesBrowserTest, ChromeOSDeviceFetchPrefs) { 666 std::vector<base::Value*> decorated_non_default_values; 667 std::string observed_json; 668 669 // Boolean pref. 670 pref_names_.push_back(chromeos::kAccountsPrefAllowGuest); 671 default_values_.push_back(new base::FundamentalValue(true)); 672 non_default_values_.push_back(new base::FundamentalValue(false)); 673 decorated_non_default_values.push_back( 674 non_default_values_.back()->DeepCopy()); 675 676 // String pref. 677 pref_names_.push_back(chromeos::kReleaseChannel); 678 default_values_.push_back(new base::StringValue("")); 679 non_default_values_.push_back(new base::StringValue("stable-channel")); 680 decorated_non_default_values.push_back( 681 non_default_values_.back()->DeepCopy()); 682 683 // List pref. 684 pref_names_.push_back(chromeos::kAccountsPrefUsers); 685 default_values_.push_back(new base::ListValue); 686 base::ListValue* list = new base::ListValue; 687 list->Append(new base::StringValue("me@google.com")); 688 list->Append(new base::StringValue("you@google.com")); 689 non_default_values_.push_back(list); 690 list = new base::ListValue; 691 base::DictionaryValue* dict = new base::DictionaryValue; 692 dict->SetString("username", "me@google.com"); 693 dict->SetString("name", "me@google.com"); 694 dict->SetString("email", ""); 695 dict->SetBoolean("owner", false); 696 list->Append(dict); 697 dict = new base::DictionaryValue; 698 dict->SetString("username", "you@google.com"); 699 dict->SetString("name", "you@google.com"); 700 dict->SetString("email", ""); 701 dict->SetBoolean("owner", false); 702 list->Append(dict); 703 decorated_non_default_values.push_back(list); 704 705 // Verify notifications when default values are in effect. 706 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 707 VerifyObservedPrefs(observed_json, pref_names_, default_values_, 708 "owner", true, false); 709 710 // Verify notifications when mandatory values are in effect. 711 chromeos::CrosSettings* cros_settings = chromeos::CrosSettings::Get(); 712 for (size_t i = 0; i < pref_names_.size(); ++i) 713 cros_settings->Set(pref_names_[i], *non_default_values_[i]); 714 // FIXME(bartfab): Find a way to simulate enterprise enrollment in browser 715 // tests. Only if Chrome thinks that it is enrolled will the device prefs be 716 // decorated with "controlledBy: policy". 717 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 718 VerifyObservedPrefs(observed_json, pref_names_, decorated_non_default_values, 719 "owner", true, false); 720 721 STLDeleteElements(&decorated_non_default_values); 722} 723 724namespace { 725 726const char* kUserProfilePath = "user_profile"; 727 728} // namespace 729 730class ProxyPreferencesBrowserTest : public PreferencesBrowserTest { 731 public: 732 virtual void SetUpOnMainThread() OVERRIDE { 733 SetupNetworkEnvironment(); 734 content::RunAllPendingInMessageLoop(); 735 736 scoped_ptr<base::DictionaryValue> proxy_config_dict( 737 ProxyConfigDictionary::CreateFixedServers("127.0.0.1:8080", 738 "*.google.com, 1.2.3.4:22")); 739 740 ProxyConfigDictionary proxy_config(proxy_config_dict.get()); 741 742 const chromeos::FavoriteState* network = GetDefaultFavoriteNetwork(); 743 ASSERT_TRUE(network); 744 chromeos::proxy_config::SetProxyConfigForFavoriteNetwork(proxy_config, 745 *network); 746 747 std::string url = base::StringPrintf("%s?network=%s", 748 chrome::kChromeUIProxySettingsURL, 749 network->path().c_str()); 750 751 ui_test_utils::NavigateToURL(browser(), GURL(url)); 752 SetUpPrefs(); 753 } 754 755 protected: 756 void SetupNetworkEnvironment() { 757 chromeos::ShillProfileClient::TestInterface* profile_test = 758 chromeos::DBusThreadManager::Get()->GetShillProfileClient() 759 ->GetTestInterface(); 760 chromeos::ShillServiceClient::TestInterface* service_test = 761 chromeos::DBusThreadManager::Get()->GetShillServiceClient() 762 ->GetTestInterface(); 763 764 profile_test->AddProfile(kUserProfilePath, "user"); 765 766 service_test->ClearServices(); 767 service_test->AddService("stub_ethernet", 768 "eth0", 769 shill::kTypeEthernet, 770 shill::kStateOnline, 771 true, // add to visible 772 true); // add to watchlist 773 service_test->SetServiceProperty("stub_ethernet", 774 shill::kGuidProperty, 775 base::StringValue("stub_ethernet")); 776 service_test->SetServiceProperty("stub_ethernet", 777 shill::kProfileProperty, 778 base::StringValue(kUserProfilePath)); 779 profile_test->AddService(kUserProfilePath, "stub_wifi2"); 780 } 781 782 void SetONCPolicy(const char* policy_name, policy::PolicyScope scope) { 783 std::string onc_policy = 784 "{ \"NetworkConfigurations\": [" 785 " { \"GUID\": \"stub_ethernet\"," 786 " \"Type\": \"Ethernet\"," 787 " \"Name\": \"My Ethernet\"," 788 " \"Ethernet\": {" 789 " \"Authentication\": \"None\" }," 790 " \"ProxySettings\": {" 791 " \"PAC\": \"http://domain.com/x\"," 792 " \"Type\": \"PAC\" }" 793 " }" 794 " ]," 795 " \"Type\": \"UnencryptedConfiguration\"" 796 "}"; 797 798 policy::PolicyMap map; 799 map.Set(policy_name, 800 policy::POLICY_LEVEL_MANDATORY, 801 scope, 802 new base::StringValue(onc_policy), 803 NULL); 804 policy_provider_.UpdateChromePolicy(map); 805 806 content::RunAllPendingInMessageLoop(); 807 } 808 809 const chromeos::FavoriteState* GetDefaultFavoriteNetwork() { 810 chromeos::NetworkStateHandler* handler = 811 chromeos::NetworkHandler::Get()->network_state_handler(); 812 return handler->DefaultFavoriteNetwork(); 813 } 814 815 void SetProxyPref(const std::string& name, const base::Value& value) { 816 std::string type; 817 switch (value.GetType()) { 818 case base::Value::TYPE_BOOLEAN: 819 type = "Boolean"; 820 break; 821 case base::Value::TYPE_INTEGER: 822 type = "Integer"; 823 break; 824 case base::Value::TYPE_STRING: 825 type = "String"; 826 break; 827 default: 828 ASSERT_TRUE(false); 829 } 830 831 std::string observed_json; 832 SetPref(name, type, &value, true, &observed_json); 833 } 834 835 void VerifyCurrentProxyServer(const std::string& expected_server, 836 onc::ONCSource expected_source) { 837 const chromeos::FavoriteState* network = GetDefaultFavoriteNetwork(); 838 ASSERT_TRUE(network); 839 onc::ONCSource actual_source; 840 scoped_ptr<ProxyConfigDictionary> proxy_dict = 841 chromeos::proxy_config::GetProxyConfigForFavoriteNetwork( 842 pref_service_, 843 g_browser_process->local_state(), 844 *network, 845 &actual_source); 846 ASSERT_TRUE(proxy_dict); 847 std::string actual_proxy_server; 848 EXPECT_TRUE(proxy_dict->GetProxyServer(&actual_proxy_server)); 849 EXPECT_EQ(expected_server, actual_proxy_server); 850 EXPECT_EQ(expected_source, actual_source); 851 } 852}; 853 854// Verifies that proxy settings are correctly pushed to JavaScript during 855// initialization of the proxy settings page. 856IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSInitializeProxy) { 857 // Boolean pref. 858 pref_names_.push_back(chromeos::kProxySingle); 859 non_default_values_.push_back(new base::FundamentalValue(true)); 860 861 // Integer prefs. 862 pref_names_.push_back(chromeos::kProxySingleHttpPort); 863 non_default_values_.push_back(new base::FundamentalValue(8080)); 864 865 // String pref. 866 pref_names_.push_back(chromeos::kProxySingleHttp); 867 non_default_values_.push_back(new base::StringValue("127.0.0.1")); 868 869 // List pref. 870 pref_names_.push_back(chromeos::kProxyIgnoreList); 871 base::ListValue* list = new base::ListValue(); 872 list->Append(new base::StringValue("*.google.com")); 873 list->Append(new base::StringValue("1.2.3.4:22")); 874 non_default_values_.push_back(list); 875 876 // Verify that no policy is presented to the UI. This must be verified on the 877 // kProxyType and the kUseSharedProxies prefs. 878 pref_names_.push_back(chromeos::kProxyType); 879 non_default_values_.push_back(new base::FundamentalValue(2)); 880 881 pref_names_.push_back(prefs::kUseSharedProxies); 882 non_default_values_.push_back(new base::FundamentalValue(false)); 883 884 std::string observed_json; 885 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 886 VerifyObservedPrefs( 887 observed_json, pref_names_, non_default_values_, "", false, false); 888} 889 890IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ONCPolicy) { 891 SetONCPolicy(policy::key::kOpenNetworkConfiguration, 892 policy::POLICY_SCOPE_USER); 893 894 // Verify that per-network policy is presented to the UI. This must be 895 // verified on the kProxyType. 896 pref_names_.push_back(chromeos::kProxyType); 897 non_default_values_.push_back(new base::FundamentalValue(3)); 898 899 std::string observed_json; 900 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 901 VerifyObservedPrefs( 902 observed_json, pref_names_, non_default_values_, "policy", true, false); 903 904 // Verify that 'use-shared-proxies' is not affected by per-network policy. 905 pref_names_.clear(); 906 STLDeleteElements(&non_default_values_); 907 pref_names_.push_back(prefs::kUseSharedProxies); 908 non_default_values_.push_back(new base::FundamentalValue(false)); 909 910 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 911 VerifyObservedPrefs( 912 observed_json, pref_names_, non_default_values_, "", false, false); 913} 914 915IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, DeviceONCPolicy) { 916 SetONCPolicy(policy::key::kDeviceOpenNetworkConfiguration, 917 policy::POLICY_SCOPE_MACHINE); 918 919 // Verify that the policy is presented to the UI. This verification must be 920 // done on the kProxyType pref. 921 pref_names_.push_back(chromeos::kProxyType); 922 non_default_values_.push_back(new base::FundamentalValue(3)); 923 924 std::string observed_json; 925 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 926 VerifyObservedPrefs( 927 observed_json, pref_names_, non_default_values_, "policy", true, false); 928 929 // Verify that 'use-shared-proxies' is not affected by per-network policy. 930 pref_names_.clear(); 931 STLDeleteElements(&non_default_values_); 932 pref_names_.push_back(prefs::kUseSharedProxies); 933 non_default_values_.push_back(new base::FundamentalValue(false)); 934 935 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 936 VerifyObservedPrefs( 937 observed_json, pref_names_, non_default_values_, "", false, false); 938} 939 940IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, UserProxyPolicy) { 941 policy_names_.push_back(policy::key::kProxyMode); 942 default_values_.push_back( 943 new base::StringValue(ProxyPrefs::kAutoDetectProxyModeName)); 944 SetUserPolicies( 945 policy_names_, default_values_, policy::POLICY_LEVEL_MANDATORY); 946 content::RunAllPendingInMessageLoop(); 947 948 // Verify that the policy is presented to the UI. This verification must be 949 // done on the kProxyType pref. 950 pref_names_.push_back(chromeos::kProxyType); 951 non_default_values_.push_back(new base::FundamentalValue(3)); 952 953 // Verify that 'use-shared-proxies' is controlled by the policy. 954 pref_names_.push_back(prefs::kUseSharedProxies); 955 non_default_values_.push_back(new base::FundamentalValue(false)); 956 957 std::string observed_json; 958 SetupJavaScriptTestEnvironment(pref_names_, &observed_json); 959 VerifyObservedPrefs( 960 observed_json, pref_names_, non_default_values_, "policy", true, false); 961} 962 963// Verifies that modifications to the proxy settings are correctly pushed from 964// JavaScript to the ProxyConfig property stored in the network configuration. 965IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSSetProxy) { 966 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 967 968 SetProxyPref(chromeos::kProxySingleHttpPort, base::FundamentalValue(123)); 969 SetProxyPref(chromeos::kProxySingleHttp, base::StringValue("www.adomain.xy")); 970 971 VerifyCurrentProxyServer("www.adomain.xy:123", 972 onc::ONC_SOURCE_NONE); 973} 974 975// Verify that default proxy ports are used and that ports can be updated 976// without affecting the previously set hosts. 977IN_PROC_BROWSER_TEST_F(ProxyPreferencesBrowserTest, ChromeOSProxyDefaultPorts) { 978 ASSERT_NO_FATAL_FAILURE(SetupJavaScriptTestEnvironment(pref_names_, NULL)); 979 980 // Set to manual, per scheme proxy. 981 SetProxyPref(chromeos::kProxySingle, base::FundamentalValue(false)); 982 983 // Set hosts but no ports. 984 SetProxyPref(chromeos::kProxyHttpUrl, base::StringValue("a.com")); 985 SetProxyPref(chromeos::kProxyHttpsUrl, base::StringValue("4.3.2.1")); 986 SetProxyPref(chromeos::kProxyFtpUrl, base::StringValue("c.com")); 987 SetProxyPref(chromeos::kProxySocks, base::StringValue("d.com")); 988 989 // Verify default ports. 990 VerifyCurrentProxyServer( 991 "http=a.com:80;https=4.3.2.1:80;ftp=c.com:80;socks=socks4://d.com:1080", 992 onc::ONC_SOURCE_NONE); 993 994 // Set and verify the ports. 995 SetProxyPref(chromeos::kProxyHttpPort, base::FundamentalValue(1)); 996 SetProxyPref(chromeos::kProxyHttpsPort, base::FundamentalValue(2)); 997 SetProxyPref(chromeos::kProxyFtpPort, base::FundamentalValue(3)); 998 SetProxyPref(chromeos::kProxySocksPort, base::FundamentalValue(4)); 999 1000 VerifyCurrentProxyServer( 1001 "http=a.com:1;https=4.3.2.1:2;ftp=c.com:3;socks=socks4://d.com:4", 1002 onc::ONC_SOURCE_NONE); 1003} 1004 1005#endif 1006