setup_util_unittest.cc revision 868fa2fe829687343ffae624259930155e16dbd8
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "chrome/installer/setup/setup_util_unittest.h"
6868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <windows.h>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <string>
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
11868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/command_line.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/file_util.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/files/scoped_temp_dir.h"
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/memory/scoped_ptr.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/path_service.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/process_util.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/threading/platform_thread.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/time.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/win/scoped_handle.h"
20868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/win/windows_version.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_paths.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/installer/setup/setup_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "testing/gtest/include/gtest/gtest.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class SetupUtilTestWithDir : public testing::Test {
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) protected:
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void SetUp() {
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(PathService::Get(chrome::DIR_TEST_DATA, &data_dir_));
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    data_dir_ = data_dir_.AppendASCII("installer");
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(file_util::PathExists(data_dir_));
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Create a temp directory for testing.
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(test_dir_.CreateUniqueTempDir());
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual void TearDown() {
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Clean up test directory manually so we can fail if it leaks.
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(test_dir_.Delete());
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The temporary directory used to contain the test operations.
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ScopedTempDir test_dir_;
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The path to input data used in tests.
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath data_dir_;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// The privilege tested in ScopeTokenPrivilege tests below.
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use SE_RESTORE_NAME as it is one of the many privileges that is available,
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// but not enabled by default on processes running at high integrity.
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)static const wchar_t kTestedPrivilege[] = SE_RESTORE_NAME;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the current process' token has privilege |privilege_name|
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// enabled.
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool CurrentProcessHasPrivilege(const wchar_t* privilege_name) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::win::ScopedHandle token;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::OpenProcessToken(::GetCurrentProcess(), TOKEN_QUERY,
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                          token.Receive())) {
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // First get the size of the buffer needed for |privileges| below.
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DWORD size;
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(::GetTokenInformation(token, TokenPrivileges, NULL, 0, &size));
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
69c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<BYTE[]> privileges_bytes(new BYTE[size]);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  TOKEN_PRIVILEGES* privileges =
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      reinterpret_cast<TOKEN_PRIVILEGES*>(privileges_bytes.get());
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!::GetTokenInformation(token, TokenPrivileges, privileges, size, &size)) {
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ADD_FAILURE();
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // There is no point getting a buffer to store more than |privilege_name|\0 as
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // anything longer will obviously not be equal to |privilege_name|.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD desired_size = wcslen(privilege_name);
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const DWORD buffer_size = desired_size + 1;
82c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  scoped_ptr<wchar_t[]> name_buffer(new wchar_t[buffer_size]);
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (int i = privileges->PrivilegeCount - 1; i >= 0 ; --i) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    LUID_AND_ATTRIBUTES& luid_and_att = privileges->Privileges[i];
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DWORD size = buffer_size;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ::LookupPrivilegeName(NULL, &luid_and_att.Luid, name_buffer.get(), &size);
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (size == desired_size &&
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        wcscmp(name_buffer.get(), privilege_name) == 0) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return luid_and_att.Attributes == SE_PRIVILEGE_ENABLED;
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return false;
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we are parsing Chrome version correctly.
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SetupUtilTestWithDir, ApplyDiffPatchTest) {
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath work_dir(test_dir_.path());
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  work_dir = work_dir.AppendASCII("ApplyDiffPatchTest");
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(file_util::PathExists(work_dir));
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(file_util::CreateDirectory(work_dir));
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(work_dir));
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath src = data_dir_.AppendASCII("archive1.7z");
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath patch = data_dir_.AppendASCII("archive.diff");
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath dest = work_dir.AppendASCII("archive2.7z");
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_EQ(installer::ApplyDiffPatch(src, patch, dest, NULL), 0);
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath base = data_dir_.AppendASCII("archive2.7z");
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(file_util::ContentsEqual(dest, base));
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  EXPECT_EQ(installer::ApplyDiffPatch(base::FilePath(), base::FilePath(),
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                      base::FilePath(), NULL),
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            6);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Test that we are parsing Chrome version correctly.
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SetupUtilTestWithDir, GetMaxVersionFromArchiveDirTest) {
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create a version dir
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath chrome_dir = test_dir_.path().AppendASCII("1.0.0.0");
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateDirectory(chrome_dir);
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(chrome_dir));
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  scoped_ptr<Version> version(
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      installer::GetMaxVersionFromArchiveDir(test_dir_.path()));
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(version->GetString(), "1.0.0.0");
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::Delete(chrome_dir, true);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(file_util::PathExists(chrome_dir));
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(installer::GetMaxVersionFromArchiveDir(test_dir_.path()) == NULL);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_dir = test_dir_.path().AppendASCII("ABC");
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateDirectory(chrome_dir);
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(chrome_dir));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(installer::GetMaxVersionFromArchiveDir(test_dir_.path()) == NULL);
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_dir = test_dir_.path().AppendASCII("2.3.4.5");
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateDirectory(chrome_dir);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(chrome_dir));
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version.reset(installer::GetMaxVersionFromArchiveDir(test_dir_.path()));
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(version->GetString(), "2.3.4.5");
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Create multiple version dirs, ensure that we select the greatest.
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_dir = test_dir_.path().AppendASCII("9.9.9.9");
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateDirectory(chrome_dir);
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(chrome_dir));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome_dir = test_dir_.path().AppendASCII("1.1.1.1");
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateDirectory(chrome_dir);
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(chrome_dir));
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  version.reset(installer::GetMaxVersionFromArchiveDir(test_dir_.path()));
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_EQ(version->GetString(), "9.9.9.9");
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST_F(SetupUtilTestWithDir, DeleteFileFromTempProcess) {
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::FilePath test_file;
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::CreateTemporaryFileInDir(test_dir_.path(), &test_file);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_TRUE(file_util::PathExists(test_file));
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  file_util::WriteFile(test_file, "foo", 3);
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_TRUE(installer::DeleteFileFromTempProcess(test_file, 0));
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  base::PlatformThread::Sleep(base::TimeDelta::FromMilliseconds(200));
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  EXPECT_FALSE(file_util::PathExists(test_file));
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: This test is only valid when run at high integrity (i.e. it will fail
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at medium integrity).
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SetupUtilTest, ScopedTokenPrivilegeBasic) {
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    installer::ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(test_scoped_privilege.is_enabled());
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Note: This test is only valid when run at high integrity (i.e. it will fail
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// at medium integrity).
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)TEST(SetupUtilTest, ScopedTokenPrivilegeAlreadyEnabled) {
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  {
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    installer::ScopedTokenPrivilege test_scoped_privilege(kTestedPrivilege);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(test_scoped_privilege.is_enabled());
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      installer::ScopedTokenPrivilege dup_scoped_privilege(kTestedPrivilege);
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(dup_scoped_privilege.is_enabled());
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ASSERT_TRUE(CurrentProcessHasPrivilege(kTestedPrivilege));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ASSERT_FALSE(CurrentProcessHasPrivilege(kTestedPrivilege));
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
197868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
198868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)const char kAdjustProcessPriority[] = "adjust-process-priority";
199868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
200868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PriorityClassChangeResult DoProcessPriorityAdjustment() {
201868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return installer::AdjustProcessPriority() ? PCCR_CHANGED : PCCR_UNCHANGED;
202868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
203868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
204868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)namespace {
205868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
206868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// A scoper that sets/resets the current process's priority class.
207868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)class ScopedPriorityClass {
208868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) public:
209868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Applies |priority_class|, returning an instance if a change was made.
210868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  // Otherwise, returns an empty scoped_ptr.
211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  static scoped_ptr<ScopedPriorityClass> Create(DWORD priority_class);
212868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ~ScopedPriorityClass();
213868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
214868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) private:
215868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  explicit ScopedPriorityClass(DWORD original_priority_class);
216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DWORD original_priority_class_;
217868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(ScopedPriorityClass);
218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)};
219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
220868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)scoped_ptr<ScopedPriorityClass> ScopedPriorityClass::Create(
221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    DWORD priority_class) {
222868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  HANDLE this_process = ::GetCurrentProcess();
223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DWORD original_priority_class = ::GetPriorityClass(this_process);
224868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_NE(0U, original_priority_class);
225868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (original_priority_class && original_priority_class != priority_class) {
226868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    BOOL result = ::SetPriorityClass(this_process, priority_class);
227868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_NE(FALSE, result);
228868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    if (result) {
229868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      return scoped_ptr<ScopedPriorityClass>(
230868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)          new ScopedPriorityClass(original_priority_class));
231868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    }
232868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
233868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return scoped_ptr<ScopedPriorityClass>();
234868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
235868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
236868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScopedPriorityClass::ScopedPriorityClass(DWORD original_priority_class)
237868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    : original_priority_class_(original_priority_class) {}
238868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
239868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)ScopedPriorityClass::~ScopedPriorityClass() {
240868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  BOOL result = ::SetPriorityClass(::GetCurrentProcess(),
241868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                                   original_priority_class_);
242868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_NE(FALSE, result);
243868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
244868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
245868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)PriorityClassChangeResult RelaunchAndDoProcessPriorityAdjustment() {
246868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CommandLine cmd_line(*CommandLine::ForCurrentProcess());
247868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  cmd_line.AppendSwitch(kAdjustProcessPriority);
248868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  base::ProcessHandle process_handle = NULL;
249868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  int exit_code = 0;
250868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (!base::LaunchProcess(cmd_line, base::LaunchOptions(),
251868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)                           &process_handle)) {
252868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ADD_FAILURE() << " to launch subprocess.";
253868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else if (!base::WaitForExitCode(process_handle, &exit_code)) {
254868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    ADD_FAILURE() << " to wait for subprocess to exit.";
255868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  } else {
256868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    return static_cast<PriorityClassChangeResult>(exit_code);
257868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  }
258868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  return PCCR_UNKNOWN;
259868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
260868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
261868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}  // namespace
262868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
263868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Launching a subprocess at normal priority class is a noop.
264868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST(SetupUtilTest, AdjustFromNormalPriority) {
265868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_EQ(NORMAL_PRIORITY_CLASS, ::GetPriorityClass(::GetCurrentProcess()));
266868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  EXPECT_EQ(PCCR_UNCHANGED, RelaunchAndDoProcessPriorityAdjustment());
267868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
268868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)
269868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// Launching a subprocess below normal priority class drops it to bg mode for
270868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)// sufficiently recent operating systems.
271868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)TEST(SetupUtilTest, AdjustFromBelowNormalPriority) {
272868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  scoped_ptr<ScopedPriorityClass> below_normal =
273868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)      ScopedPriorityClass::Create(BELOW_NORMAL_PRIORITY_CLASS);
274868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  ASSERT_TRUE(below_normal);
275868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  if (base::win::GetVersion() > base::win::VERSION_SERVER_2003)
276868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(PCCR_CHANGED, RelaunchAndDoProcessPriorityAdjustment());
277868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  else
278868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)    EXPECT_EQ(PCCR_UNCHANGED, RelaunchAndDoProcessPriorityAdjustment());
279868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)}
280