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