install_worker_unittest.cc revision 5d1f7b1de12d16ceb2c938c56701a3e8bfa558f7
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/installer/setup/install_worker.h" 6 7#include "base/win/registry.h" 8#include "base/version.h" 9#include "chrome/common/chrome_constants.h" 10#include "chrome/installer/setup/setup_util.h" 11#include "chrome/installer/util/delete_reg_key_work_item.h" 12#include "chrome/installer/util/create_reg_key_work_item.h" 13#include "chrome/installer/util/helper.h" 14#include "chrome/installer/util/google_update_constants.h" 15#include "chrome/installer/util/installation_state.h" 16#include "chrome/installer/util/installer_state.h" 17#include "chrome/installer/util/set_reg_value_work_item.h" 18#include "chrome/installer/util/util_constants.h" 19#include "chrome/installer/util/work_item_list.h" 20 21#include "testing/gtest/include/gtest/gtest.h" 22#include "testing/gmock/include/gmock/gmock.h" 23 24using base::win::RegKey; 25using installer::InstallationState; 26using installer::InstallerState; 27using installer::Product; 28using installer::ProductState; 29 30using ::testing::_; 31using ::testing::AtLeast; 32using ::testing::AtMost; 33using ::testing::Bool; 34using ::testing::Combine; 35using ::testing::HasSubstr; 36using ::testing::Eq; 37using ::testing::Return; 38using ::testing::StrCaseEq; 39using ::testing::StrEq; 40using ::testing::StrictMock; 41using ::testing::Values; 42 43// Mock classes to help with testing 44//------------------------------------------------------------------------------ 45 46class MockWorkItemList : public WorkItemList { 47 public: 48 MockWorkItemList() {} 49 50 MOCK_METHOD4(AddCopyRegKeyWorkItem, WorkItem* (HKEY, 51 const std::wstring&, 52 const std::wstring&, 53 CopyOverWriteOption)); 54 MOCK_METHOD5(AddCopyTreeWorkItem, WorkItem*(const std::wstring&, 55 const std::wstring&, 56 const std::wstring&, 57 CopyOverWriteOption, 58 const std::wstring&)); 59 MOCK_METHOD1(AddCreateDirWorkItem, WorkItem* (const base::FilePath&)); 60 MOCK_METHOD2(AddCreateRegKeyWorkItem, WorkItem* (HKEY, const std::wstring&)); 61 MOCK_METHOD2(AddDeleteRegKeyWorkItem, WorkItem* (HKEY, const std::wstring&)); 62 MOCK_METHOD3(AddDeleteRegValueWorkItem, WorkItem* (HKEY, 63 const std::wstring&, 64 const std::wstring&)); 65 MOCK_METHOD2(AddDeleteTreeWorkItem, WorkItem* ( 66 const base::FilePath&, 67 const std::vector<base::FilePath>&)); 68 MOCK_METHOD1(AddDeleteTreeWorkItem, WorkItem* (const base::FilePath&)); 69 MOCK_METHOD3(AddMoveTreeWorkItem, WorkItem* (const std::wstring&, 70 const std::wstring&, 71 const std::wstring&)); 72 // Workaround for gmock problems with disambiguating between string pointers 73 // and DWORD. 74 virtual WorkItem* AddSetRegValueWorkItem(HKEY a1, const std::wstring& a2, 75 const std::wstring& a3, const std::wstring& a4, bool a5) { 76 return AddSetRegStringValueWorkItem(a1, a2, a3, a4, a5); 77 } 78 79 virtual WorkItem* AddSetRegValueWorkItem(HKEY a1, const std::wstring& a2, 80 const std::wstring& a3, 81 DWORD a4, bool a5) { 82 return AddSetRegDwordValueWorkItem(a1, a2, a3, a4, a5); 83 } 84 85 MOCK_METHOD5(AddSetRegStringValueWorkItem, WorkItem*(HKEY, 86 const std::wstring&, 87 const std::wstring&, 88 const std::wstring&, 89 bool)); 90 MOCK_METHOD5(AddSetRegDwordValueWorkItem, WorkItem* (HKEY, 91 const std::wstring&, 92 const std::wstring&, 93 DWORD, 94 bool)); 95 MOCK_METHOD3(AddSelfRegWorkItem, WorkItem* (const std::wstring&, 96 bool, 97 bool)); 98}; 99 100class MockProductState : public ProductState { 101 public: 102 // Takes ownership of |version|. 103 void set_version(Version* version) { version_.reset(version); } 104 void set_multi_install(bool multi) { multi_install_ = multi; } 105 void set_brand(const std::wstring& brand) { brand_ = brand; } 106 void set_eula_accepted(DWORD eula_accepted) { 107 has_eula_accepted_ = true; 108 eula_accepted_ = eula_accepted; 109 } 110 void clear_eula_accepted() { has_eula_accepted_ = false; } 111 void set_usagestats(DWORD usagestats) { 112 has_usagestats_ = true; 113 usagestats_ = usagestats; 114 } 115 void clear_usagestats() { has_usagestats_ = false; } 116 void set_oem_install(const std::wstring& oem_install) { 117 has_oem_install_ = true; 118 oem_install_ = oem_install; 119 } 120 void clear_oem_install() { has_oem_install_ = false; } 121 void SetUninstallProgram(const base::FilePath& setup_exe) { 122 uninstall_command_ = CommandLine(setup_exe); 123 } 124 void AddUninstallSwitch(const std::string& option) { 125 uninstall_command_.AppendSwitch(option); 126 } 127}; 128 129// Okay, so this isn't really a mock as such, but it does add setter methods 130// to make it easier to build custom InstallationStates. 131class MockInstallationState : public InstallationState { 132 public: 133 // Included for testing. 134 void SetProductState(bool system_install, 135 BrowserDistribution::Type type, 136 const ProductState& product_state) { 137 ProductState& target = (system_install ? system_products_ : 138 user_products_)[IndexFromDistType(type)]; 139 target.CopyFrom(product_state); 140 } 141}; 142 143class MockInstallerState : public InstallerState { 144 public: 145 void set_level(Level level) { 146 InstallerState::set_level(level); 147 } 148 149 void set_operation(Operation operation) { operation_ = operation; } 150 151 void set_state_key(const std::wstring& state_key) { 152 state_key_ = state_key; 153 } 154 155 void set_state_type(BrowserDistribution::Type state_type) { 156 state_type_ = state_type; 157 } 158 159 void set_package_type(PackageType type) { 160 InstallerState::set_package_type(type); 161 } 162}; 163 164// The test fixture 165//------------------------------------------------------------------------------ 166 167class InstallWorkerTest : public testing::Test { 168 public: 169 virtual void SetUp() { 170 current_version_.reset(new Version("1.0.0.0")); 171 new_version_.reset(new Version("42.0.0.0")); 172 173 // Don't bother ensuring that these paths exist. Since we're just 174 // building the work item lists and not running them, they shouldn't 175 // actually be touched. 176 archive_path_ = 177 base::FilePath(L"C:\\UnlikelyPath\\Temp\\chrome_123\\chrome.7z"); 178 // TODO(robertshield): Take this from the BrowserDistribution once that 179 // no longer depends on MasterPreferences. 180 installation_path_ = 181 base::FilePath(L"C:\\Program Files\\Google\\Chrome\\"); 182 src_path_ = base::FilePath( 183 L"C:\\UnlikelyPath\\Temp\\chrome_123\\source\\Chrome-bin"); 184 setup_path_ = base::FilePath( 185 L"C:\\UnlikelyPath\\Temp\\CR_123.tmp\\setup.exe"); 186 temp_dir_ = base::FilePath(L"C:\\UnlikelyPath\\Temp\\chrome_123"); 187 } 188 189 virtual void TearDown() { 190 } 191 192 void MaybeAddBinariesToInstallationState( 193 bool system_level, 194 MockInstallationState* installation_state) { 195 if (installation_state->GetProductState( 196 system_level, BrowserDistribution::CHROME_BINARIES) == NULL) { 197 MockProductState product_state; 198 product_state.set_version(new Version(*current_version_)); 199 product_state.set_brand(L"TEST"); 200 product_state.set_multi_install(true); 201 BrowserDistribution* dist = 202 BrowserDistribution::GetSpecificDistribution( 203 BrowserDistribution::CHROME_BINARIES); 204 base::FilePath install_path = 205 installer::GetChromeInstallPath(system_level, dist); 206 product_state.SetUninstallProgram( 207 install_path.AppendASCII(current_version_->GetString()) 208 .Append(installer::kInstallerDir) 209 .Append(installer::kSetupExe)); 210 product_state.AddUninstallSwitch(installer::switches::kUninstall); 211 product_state.AddUninstallSwitch(installer::switches::kMultiInstall); 212 if (system_level) 213 product_state.AddUninstallSwitch(installer::switches::kSystemLevel); 214 installation_state->SetProductState(system_level, 215 BrowserDistribution::CHROME_BINARIES, 216 product_state); 217 } 218 } 219 220 void AddChromeToInstallationState( 221 bool system_level, 222 bool multi_install, 223 MockInstallationState* installation_state) { 224 if (multi_install) 225 MaybeAddBinariesToInstallationState(system_level, installation_state); 226 MockProductState product_state; 227 product_state.set_version(new Version(*current_version_)); 228 product_state.set_multi_install(multi_install); 229 product_state.set_brand(L"TEST"); 230 product_state.set_eula_accepted(1); 231 BrowserDistribution* dist = 232 BrowserDistribution::GetSpecificDistribution( 233 BrowserDistribution::CHROME_BROWSER); 234 base::FilePath install_path = 235 installer::GetChromeInstallPath(system_level, dist); 236 product_state.SetUninstallProgram( 237 install_path.AppendASCII(current_version_->GetString()) 238 .Append(installer::kInstallerDir) 239 .Append(installer::kSetupExe)); 240 product_state.AddUninstallSwitch(installer::switches::kUninstall); 241 if (system_level) 242 product_state.AddUninstallSwitch(installer::switches::kSystemLevel); 243 if (multi_install) { 244 product_state.AddUninstallSwitch(installer::switches::kMultiInstall); 245 product_state.AddUninstallSwitch(installer::switches::kChrome); 246 } 247 248 installation_state->SetProductState(system_level, 249 BrowserDistribution::CHROME_BROWSER, 250 product_state); 251 } 252 253 void AddChromeFrameToInstallationState( 254 bool system_level, 255 bool multi_install, 256 MockInstallationState* installation_state) { 257 if (multi_install) 258 MaybeAddBinariesToInstallationState(system_level, installation_state); 259 MockProductState product_state; 260 product_state.set_version(new Version(*current_version_)); 261 product_state.set_multi_install(multi_install); 262 BrowserDistribution* dist = 263 BrowserDistribution::GetSpecificDistribution( 264 multi_install ? BrowserDistribution::CHROME_BINARIES : 265 BrowserDistribution::CHROME_FRAME); 266 base::FilePath install_path = 267 installer::GetChromeInstallPath(system_level, dist); 268 product_state.SetUninstallProgram( 269 install_path.AppendASCII(current_version_->GetString()) 270 .Append(installer::kInstallerDir) 271 .Append(installer::kSetupExe)); 272 product_state.AddUninstallSwitch(installer::switches::kUninstall); 273 product_state.AddUninstallSwitch(installer::switches::kChromeFrame); 274 if (system_level) 275 product_state.AddUninstallSwitch(installer::switches::kSystemLevel); 276 if (multi_install) 277 product_state.AddUninstallSwitch(installer::switches::kMultiInstall); 278 279 installation_state->SetProductState(system_level, 280 BrowserDistribution::CHROME_FRAME, 281 product_state); 282 } 283 284 MockInstallationState* BuildChromeInstallationState(bool system_level, 285 bool multi_install) { 286 scoped_ptr<MockInstallationState> installation_state( 287 new MockInstallationState()); 288 AddChromeToInstallationState(system_level, multi_install, 289 installation_state.get()); 290 return installation_state.release(); 291 } 292 293 static MockInstallerState* BuildBasicInstallerState( 294 bool system_install, 295 bool multi_install, 296 const InstallationState& machine_state, 297 InstallerState::Operation operation) { 298 scoped_ptr<MockInstallerState> installer_state(new MockInstallerState()); 299 300 InstallerState::Level level = system_install ? 301 InstallerState::SYSTEM_LEVEL : InstallerState::USER_LEVEL; 302 installer_state->set_level(level); 303 installer_state->set_operation(operation); 304 // Hope this next one isn't checked for now. 305 installer_state->set_state_key(L"PROBABLY_INVALID_REG_PATH"); 306 installer_state->set_state_type(BrowserDistribution::CHROME_BROWSER); 307 installer_state->set_package_type(multi_install ? 308 InstallerState::MULTI_PACKAGE : 309 InstallerState::SINGLE_PACKAGE); 310 return installer_state.release(); 311 } 312 313 static void AddChromeBinariesToInstallerState( 314 const InstallationState& machine_state, 315 MockInstallerState* installer_state) { 316 if (!installer_state->is_multi_install()) { 317 NOTREACHED(); 318 return; 319 } 320 if (installer_state->FindProduct(BrowserDistribution::CHROME_BINARIES)) 321 return; 322 323 // Fresh install or upgrade? 324 const ProductState* chrome_binaries = 325 machine_state.GetProductState(installer_state->system_install(), 326 BrowserDistribution::CHROME_BINARIES); 327 if (chrome_binaries != NULL) { 328 installer_state->AddProductFromState(BrowserDistribution::CHROME_BINARIES, 329 *chrome_binaries); 330 } else { 331 BrowserDistribution* dist = 332 BrowserDistribution::GetSpecificDistribution( 333 BrowserDistribution::CHROME_BINARIES); 334 scoped_ptr<Product> product(new Product(dist)); 335 product->SetOption(installer::kOptionMultiInstall, true); 336 installer_state->AddProduct(&product); 337 } 338 } 339 340 static void AddChromeToInstallerState( 341 const InstallationState& machine_state, 342 MockInstallerState* installer_state) { 343 // Fresh install or upgrade? 344 const ProductState* chrome = 345 machine_state.GetProductState(installer_state->system_install(), 346 BrowserDistribution::CHROME_BROWSER); 347 if (chrome != NULL && 348 chrome->is_multi_install() == installer_state->is_multi_install()) { 349 installer_state->AddProductFromState(BrowserDistribution::CHROME_BROWSER, 350 *chrome); 351 } else { 352 BrowserDistribution* dist = 353 BrowserDistribution::GetSpecificDistribution( 354 BrowserDistribution::CHROME_BROWSER); 355 scoped_ptr<Product> product(new Product(dist)); 356 if (installer_state->is_multi_install()) 357 product->SetOption(installer::kOptionMultiInstall, true); 358 installer_state->AddProduct(&product); 359 } 360 } 361 362 static void AddChromeFrameToInstallerState( 363 const InstallationState& machine_state, 364 MockInstallerState* installer_state) { 365 // Fresh install or upgrade? 366 const ProductState* cf = 367 machine_state.GetProductState(installer_state->system_install(), 368 BrowserDistribution::CHROME_FRAME); 369 if (cf != NULL) { 370 installer_state->AddProductFromState(BrowserDistribution::CHROME_FRAME, 371 *cf); 372 } else { 373 BrowserDistribution* dist = 374 BrowserDistribution::GetSpecificDistribution( 375 BrowserDistribution::CHROME_FRAME); 376 scoped_ptr<Product> product(new Product(dist)); 377 if (installer_state->is_multi_install()) 378 product->SetOption(installer::kOptionMultiInstall, true); 379 installer_state->AddProduct(&product); 380 } 381 } 382 383 static MockInstallerState* BuildChromeInstallerState( 384 bool system_install, 385 bool multi_install, 386 const InstallationState& machine_state, 387 InstallerState::Operation operation) { 388 scoped_ptr<MockInstallerState> installer_state( 389 BuildBasicInstallerState(system_install, multi_install, machine_state, 390 operation)); 391 if (multi_install) { 392 // We don't want to include Chrome Binaries for uninstall if the machine 393 // has other products. For simplicity, we check Chrome Frame only. 394 bool machine_has_other_products = 395 machine_state.GetProductState(system_install, 396 BrowserDistribution::CHROME_FRAME) != NULL; 397 if (operation != InstallerState::UNINSTALL || !machine_has_other_products) 398 AddChromeBinariesToInstallerState(machine_state, installer_state.get()); 399 } 400 AddChromeToInstallerState(machine_state, installer_state.get()); 401 return installer_state.release(); 402 } 403 404 static MockInstallerState* BuildChromeFrameInstallerState( 405 bool system_install, 406 bool multi_install, 407 const InstallationState& machine_state, 408 InstallerState::Operation operation) { 409 // This method only works for installation/upgrade. 410 DCHECK(operation != InstallerState::UNINSTALL); 411 scoped_ptr<MockInstallerState> installer_state( 412 BuildBasicInstallerState(system_install, multi_install, machine_state, 413 operation)); 414 if (multi_install) 415 AddChromeBinariesToInstallerState(machine_state, installer_state.get()); 416 AddChromeFrameToInstallerState(machine_state, installer_state.get()); 417 return installer_state.release(); 418 } 419 420 protected: 421 scoped_ptr<Version> current_version_; 422 scoped_ptr<Version> new_version_; 423 base::FilePath archive_path_; 424 base::FilePath installation_path_; 425 base::FilePath setup_path_; 426 base::FilePath src_path_; 427 base::FilePath temp_dir_; 428}; 429 430// Tests 431//------------------------------------------------------------------------------ 432 433TEST_F(InstallWorkerTest, TestInstallChromeSingleSystem) { 434 const bool system_level = true; 435 const bool multi_install = false; 436 MockWorkItemList work_item_list; 437 438 const HKEY kRegRoot = system_level ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 439 static const wchar_t kRegKeyPath[] = L"Software\\Chromium\\test"; 440 scoped_ptr<CreateRegKeyWorkItem> create_reg_key_work_item( 441 WorkItem::CreateCreateRegKeyWorkItem(kRegRoot, kRegKeyPath)); 442 scoped_ptr<SetRegValueWorkItem> set_reg_value_work_item( 443 WorkItem::CreateSetRegValueWorkItem(kRegRoot, kRegKeyPath, L"", L"", 444 false)); 445 446 scoped_ptr<InstallationState> installation_state( 447 BuildChromeInstallationState(system_level, multi_install)); 448 449 scoped_ptr<InstallerState> installer_state( 450 BuildChromeInstallerState(system_level, multi_install, 451 *installation_state, 452 InstallerState::SINGLE_INSTALL_OR_UPDATE)); 453 454 // Set up some expectations. 455 // TODO(robertshield): Set up some real expectations. 456 EXPECT_CALL(work_item_list, AddCopyTreeWorkItem(_, _, _, _, _)) 457 .Times(AtLeast(1)); 458 EXPECT_CALL(work_item_list, AddCreateRegKeyWorkItem(_, _)) 459 .WillRepeatedly(Return(create_reg_key_work_item.get())); 460 EXPECT_CALL(work_item_list, AddSetRegStringValueWorkItem(_, _, _, _, _)) 461 .WillRepeatedly(Return(set_reg_value_work_item.get())); 462 463 AddInstallWorkItems(*installation_state.get(), 464 *installer_state.get(), 465 setup_path_, 466 archive_path_, 467 src_path_, 468 temp_dir_, 469 current_version_.get(), 470 *new_version_.get(), 471 &work_item_list); 472} 473 474namespace { 475 476const wchar_t elevation_key[] = 477 L"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\" 478 L"{E0A900DF-9611-4446-86BD-4B1D47E7DB2A}"; 479const wchar_t old_elevation_key[] = 480 L"SOFTWARE\\Microsoft\\Internet Explorer\\Low Rights\\ElevationPolicy\\" 481 L"{6C288DD7-76FB-4721-B628-56FAC252E199}"; 482 483} // namespace 484 485// A test class for worker functions that manipulate the old IE low rights 486// policies. 487// Parameters: 488// bool : system_level_ 489// bool : multi_install_ 490class OldIELowRightsTests : public InstallWorkerTest, 491 public ::testing::WithParamInterface<std::tr1::tuple<bool, bool> > { 492 protected: 493 virtual void SetUp() OVERRIDE { 494 InstallWorkerTest::SetUp(); 495 496 const ParamType& param = GetParam(); 497 system_level_ = std::tr1::get<0>(param); 498 multi_install_ = std::tr1::get<1>(param); 499 root_key_ = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 500 501 installation_state_.reset(new MockInstallationState()); 502 AddChromeFrameToInstallationState(system_level_, multi_install_, 503 installation_state_.get()); 504 installer_state_.reset(BuildBasicInstallerState( 505 system_level_, multi_install_, *installation_state_, 506 multi_install_ ? InstallerState::MULTI_UPDATE : 507 InstallerState::SINGLE_INSTALL_OR_UPDATE)); 508 if (multi_install_) 509 AddChromeBinariesToInstallerState(*installation_state_, 510 installer_state_.get()); 511 AddChromeFrameToInstallerState(*installation_state_, 512 installer_state_.get()); 513 } 514 515 scoped_ptr<MockInstallationState> installation_state_; 516 scoped_ptr<MockInstallerState> installer_state_; 517 bool system_level_; 518 bool multi_install_; 519 HKEY root_key_; 520}; 521 522TEST_P(OldIELowRightsTests, AddDeleteOldIELowRightsPolicyWorkItems) { 523 StrictMock<MockWorkItemList> work_item_list; 524 525 EXPECT_CALL(work_item_list, 526 AddDeleteRegKeyWorkItem(root_key_, StrEq(old_elevation_key))) 527 .Times(1); 528 529 AddDeleteOldIELowRightsPolicyWorkItems(*installer_state_.get(), 530 &work_item_list); 531} 532 533INSTANTIATE_TEST_CASE_P(Variations, OldIELowRightsTests, 534 Combine(Bool(), Bool())); 535 536TEST_F(InstallWorkerTest, GoogleUpdateWorkItemsTest) { 537 const bool system_level = true; 538 const bool multi_install = true; 539 MockWorkItemList work_item_list; 540 541 scoped_ptr<MockInstallationState> installation_state( 542 BuildChromeInstallationState(system_level, false)); 543 544 MockProductState cf_state; 545 cf_state.set_version(new Version(*current_version_)); 546 cf_state.set_multi_install(false); 547 548 installation_state->SetProductState(system_level, 549 BrowserDistribution::CHROME_FRAME, cf_state); 550 551 scoped_ptr<MockInstallerState> installer_state( 552 BuildChromeInstallerState(system_level, multi_install, 553 *installation_state, 554 InstallerState::MULTI_INSTALL)); 555 556 // Expect the multi Client State key to be created. 557 BrowserDistribution* multi_dist = 558 BrowserDistribution::GetSpecificDistribution( 559 BrowserDistribution::CHROME_BINARIES); 560 std::wstring multi_app_guid(multi_dist->GetAppGuid()); 561 std::wstring multi_client_state_suffix(L"ClientState\\" + multi_app_guid); 562 EXPECT_CALL(work_item_list, 563 AddCreateRegKeyWorkItem(_, HasSubstr(multi_client_state_suffix))) 564 .Times(testing::AnyNumber()); 565 566 // Expect ClientStateMedium to be created for system-level installs. 567 EXPECT_CALL(work_item_list, 568 AddCreateRegKeyWorkItem(_, HasSubstr(L"ClientStateMedium\\" + 569 multi_app_guid))) 570 .Times(system_level ? 1 : 0); 571 572 // Expect to see a set value for the "TEST" brand code in the multi Client 573 // State key. 574 EXPECT_CALL(work_item_list, 575 AddSetRegStringValueWorkItem(_, 576 HasSubstr(multi_client_state_suffix), 577 StrEq(google_update::kRegBrandField), 578 StrEq(L"TEST"), 579 _)).Times(1); 580 581 // There may also be some calls to set 'ap' values. 582 EXPECT_CALL(work_item_list, 583 AddSetRegStringValueWorkItem(_, _, 584 StrEq(google_update::kRegApField), 585 _, _)).Times(testing::AnyNumber()); 586 587 // Expect "oeminstall" to be cleared. 588 EXPECT_CALL(work_item_list, 589 AddDeleteRegValueWorkItem( 590 _, 591 HasSubstr(multi_client_state_suffix), 592 StrEq(google_update::kRegOemInstallField))).Times(1); 593 594 // Expect "eulaaccepted" to set. 595 EXPECT_CALL(work_item_list, 596 AddSetRegDwordValueWorkItem( 597 _, 598 HasSubstr(multi_client_state_suffix), 599 StrEq(google_update::kRegEULAAceptedField), 600 Eq(static_cast<DWORD>(1)), 601 _)).Times(1); 602 603 AddGoogleUpdateWorkItems(*installation_state.get(), 604 *installer_state.get(), 605 &work_item_list); 606} 607 608// Test that usagestats values are migrated properly. 609TEST_F(InstallWorkerTest, AddUsageStatsWorkItems) { 610 const bool system_level = true; 611 const bool multi_install = true; 612 MockWorkItemList work_item_list; 613 614 scoped_ptr<MockInstallationState> installation_state( 615 BuildChromeInstallationState(system_level, multi_install)); 616 617 MockProductState chrome_state; 618 chrome_state.set_version(new Version(*current_version_)); 619 chrome_state.set_multi_install(false); 620 chrome_state.set_usagestats(1); 621 622 installation_state->SetProductState(system_level, 623 BrowserDistribution::CHROME_BROWSER, chrome_state); 624 625 scoped_ptr<MockInstallerState> installer_state( 626 BuildChromeInstallerState(system_level, multi_install, 627 *installation_state, 628 InstallerState::MULTI_INSTALL)); 629 630 // Expect the multi Client State key to be created. 631 BrowserDistribution* multi_dist = 632 BrowserDistribution::GetSpecificDistribution( 633 BrowserDistribution::CHROME_BINARIES); 634 std::wstring multi_app_guid(multi_dist->GetAppGuid()); 635 EXPECT_CALL(work_item_list, 636 AddCreateRegKeyWorkItem(_, HasSubstr(multi_app_guid))).Times(1); 637 638 // Expect to see a set value for the usagestats in the multi Client State key. 639 EXPECT_CALL(work_item_list, 640 AddSetRegDwordValueWorkItem( 641 _, 642 HasSubstr(multi_app_guid), 643 StrEq(google_update::kRegUsageStatsField), 644 Eq(static_cast<DWORD>(1)), 645 Eq(true))).Times(1); 646 647 // Expect to see some values cleaned up from Chrome's keys. 648 BrowserDistribution* chrome_dist = 649 BrowserDistribution::GetSpecificDistribution( 650 BrowserDistribution::CHROME_BROWSER); 651 if (system_level) { 652 EXPECT_CALL(work_item_list, 653 AddDeleteRegValueWorkItem( 654 _, 655 StrEq(chrome_dist->GetStateMediumKey()), 656 StrEq(google_update::kRegUsageStatsField))).Times(1); 657 EXPECT_CALL(work_item_list, 658 AddDeleteRegValueWorkItem( 659 Eq(HKEY_CURRENT_USER), 660 StrEq(chrome_dist->GetStateKey()), 661 StrEq(google_update::kRegUsageStatsField))).Times(1); 662 } 663 EXPECT_CALL(work_item_list, 664 AddDeleteRegValueWorkItem( 665 Eq(installer_state->root_key()), 666 StrEq(chrome_dist->GetStateKey()), 667 StrEq(google_update::kRegUsageStatsField))).Times(1); 668 669 AddUsageStatsWorkItems(*installation_state.get(), 670 *installer_state.get(), 671 &work_item_list); 672} 673 674// The Quick Enable tests only make sense for the Google Chrome build as it 675// interacts with registry values that are specific to Google Update. 676#if defined(GOOGLE_CHROME_BUILD) 677 678// Test scenarios under which the quick-enable-cf command should not exist after 679// the run. We're permissive in that we allow the DeleteRegKeyWorkItem even if 680// it isn't strictly needed. 681class QuickEnableAbsentTest : public InstallWorkerTest { 682 public: 683 virtual void SetUp() { 684 InstallWorkerTest::SetUp(); 685 root_key_ = system_level_ ? HKEY_LOCAL_MACHINE : HKEY_CURRENT_USER; 686 delete_reg_key_item_.reset( 687 WorkItem::CreateDeleteRegKeyWorkItem(root_key_, kRegKeyPath)); 688 machine_state_.reset(new MockInstallationState()); 689 EXPECT_CALL(work_item_list_, 690 AddDeleteRegKeyWorkItem(Eq(root_key_), StrCaseEq(kRegKeyPath))) 691 .Times(AtMost(1)) 692 .WillRepeatedly(Return(delete_reg_key_item_.get())); 693 } 694 virtual void TearDown() { 695 machine_state_.reset(); 696 delete_reg_key_item_.reset(); 697 root_key_ = NULL; 698 InstallWorkerTest::TearDown(); 699 } 700 protected: 701 static const bool system_level_ = false; 702 static const wchar_t kRegKeyPath[]; 703 HKEY root_key_; 704 scoped_ptr<DeleteRegKeyWorkItem> delete_reg_key_item_; 705 scoped_ptr<MockInstallationState> machine_state_; 706 StrictMock<MockWorkItemList> work_item_list_; 707}; 708 709const wchar_t QuickEnableAbsentTest::kRegKeyPath[] = 710 L"Software\\Google\\Update\\Clients\\" 711 L"{4DC8B4CA-1BDA-483e-B5FA-D3C12E15B62D}\\Commands\\quick-enable-cf"; 712 713TEST_F(QuickEnableAbsentTest, CleanInstallSingleChrome) { 714 // Install single Chrome on a clean system. 715 scoped_ptr<MockInstallerState> installer_state( 716 BuildBasicInstallerState(system_level_, true, *machine_state_, 717 InstallerState::MULTI_UPDATE)); 718 AddQuickEnableChromeFrameWorkItems(*installer_state, &work_item_list_); 719} 720 721TEST_F(InstallWorkerTest, WillProductBePresentAfterSetup) { 722 BrowserDistribution::Type prod_type_list[] = { 723 BrowserDistribution::CHROME_BROWSER, 724 BrowserDistribution::CHROME_FRAME, 725 // Excluding BrowserDistribution::CHROME_BINARIES, since it is installed 726 // along with other products. 727 }; 728 enum { // Index into prod_type_list[]. 729 TYPE_BROWSER = 0, 730 TYPE_CF, 731 NUM_TYPE // This must appear last. 732 }; 733 DCHECK(arraysize(prod_type_list) == NUM_TYPE); 734 InstallerState::Operation op_list[] = { 735 InstallerState::UNINSTALL, 736 InstallerState::SINGLE_INSTALL_OR_UPDATE 737 }; 738 739 const bool system_level = false; 740 const bool multi_install = true; 741 742 // Loop over machine states: {No product, Chrome, CF, Chrome + CF}. 743 for (int i_mach = 0; i_mach < (1 << NUM_TYPE); ++i_mach) { 744 // i_mach is the machine state before operation, as bit mask. 745 scoped_ptr<MockInstallationState> machine_state( 746 new MockInstallationState()); 747 if ((i_mach & (1 << TYPE_BROWSER)) != 0) { // Add Chrome. 748 AddChromeToInstallationState(system_level, multi_install, 749 machine_state.get()); 750 } 751 if ((i_mach & (1 << TYPE_CF)) != 0) { // Add Chrome Frame. 752 AddChromeFrameToInstallationState(system_level, multi_install, 753 machine_state.get()); 754 } 755 756 // Loop over operations: {uninstall, install/update}. 757 for (int i_op = 0; i_op < arraysize(op_list); ++i_op) { 758 759 // Loop over product types to operate on: {TYPE_BROWSER, TYPE_CF}. 760 for (int i_type_op = 0; i_type_op < NUM_TYPE; ++i_type_op) { 761 scoped_ptr<InstallerState> installer_state; 762 if (i_type_op == TYPE_BROWSER) { 763 installer_state.reset(BuildChromeInstallerState( 764 system_level, multi_install, *machine_state, op_list[i_op])); 765 } else if (i_type_op == TYPE_CF) { 766 // Skip the CF uninstall case due to limitations in 767 // BuildChromeFrameInstallerState(). 768 if (op_list[i_op] == InstallerState::UNINSTALL) 769 continue; 770 771 installer_state.reset(BuildChromeFrameInstallerState( 772 system_level, multi_install, *machine_state, op_list[i_op])); 773 } else { 774 NOTREACHED(); 775 } 776 777 // Calculate the machine state after operation, as bit mask. 778 // If uninstall, remove product with bitwise AND; else add with OR. 779 int mach_after = (op_list[i_op] == InstallerState::UNINSTALL) ? 780 i_mach & ~(1 << i_type_op) : i_mach | (1 << i_type_op); 781 782 // Verify predicted presence of Chrome Binaries. 783 bool bin_res = installer::WillProductBePresentAfterSetup( 784 *installer_state, 785 *machine_state, 786 BrowserDistribution::CHROME_BINARIES); 787 // Binaries are expected to be present iff any product is installed. 788 bool bin_expect = mach_after != 0; 789 EXPECT_EQ(bin_expect, bin_res); 790 791 // Loop over product types to check: {TYPE_BROWSER, TYPE_CF}. 792 for (int i_type_check = 0; i_type_check < NUM_TYPE; ++i_type_check) { 793 // Verify predicted presence of product. 794 bool prod_res = installer::WillProductBePresentAfterSetup( 795 *installer_state, 796 *machine_state, 797 prod_type_list[i_type_check]); 798 bool prod_expect = (mach_after & (1 << i_type_check)) != 0; 799 EXPECT_EQ(prod_expect, prod_res); 800 } 801 } 802 } 803 } 804} 805 806#endif // defined(GOOGLE_CHROME_BUILD) 807