/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ /* vim: set ts=8 sts=2 et sw=2 tw=80: */ /* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at https://mozilla.org/MPL/2.0/. */ #define MOZ_USE_LAUNCHER_ERROR #include "mozilla/LauncherRegistryInfo.h" #include "mozilla/NativeNt.h" #include "mozilla/ScopeExit.h" #include "mozilla/Unused.h" #include "nsWindowsHelpers.h" #include "LauncherRegistryInfo.cpp" #include static const char kMsgStart[] = "TEST-FAILED | LauncherRegistryInfo | "; static const wchar_t kRegKeyPath[] = L"SOFTWARE\\" EXPAND_STRING_MACRO( MOZ_APP_VENDOR) L"\\" EXPAND_STRING_MACRO(MOZ_APP_BASENAME) L"\\Launcher"; static const wchar_t kBrowserSuffix[] = L"|Browser"; static const wchar_t kLauncherSuffix[] = L"|Launcher"; static const wchar_t kImageSuffix[] = L"|Image"; static const wchar_t kTelemetrySuffix[] = L"|Telemetry"; static std::wstring gBrowserValue; static std::wstring gLauncherValue; static std::wstring gImageValue; static std::wstring gTelemetryValue; static DWORD gMyImageTimestamp; #define RUN_TEST(result, fn) \ if ((result = fn()).isErr()) { \ const mozilla::LauncherError& err = result.inspectErr(); \ printf("%s%s | %08lx (%s:%d)\n", kMsgStart, #fn, err.mError.AsHResult(), \ err.mFile, err.mLine); \ return 1; \ } #define EXPECT_COMMIT_IS_OK() \ do { \ mozilla::LauncherVoidResult vr2 = info.Commit(); \ if (vr2.isErr()) { \ return vr2; \ } \ } while (0) #define EXPECT_CHECK_RESULT_IS(desired, expected) \ do { \ mozilla::LauncherResult \ result = info.Check(mozilla::LauncherRegistryInfo::desired); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.unwrap() != mozilla::LauncherRegistryInfo::expected) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_FAIL); \ } \ } while (0) #define EXPECT_ENABLED_STATE_IS(expected) \ do { \ mozilla::LauncherResult \ enabled = info.IsEnabled(); \ if (enabled.isErr()) { \ return enabled.propagateErr(); \ } \ if (enabled.unwrap() != mozilla::LauncherRegistryInfo::expected) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_TELEMETRY_IS_ENABLED(expected) \ do { \ mozilla::LauncherResult enabled = info.IsTelemetryEnabled(); \ if (enabled.isErr()) { \ return enabled.propagateErr(); \ } \ if (enabled.unwrap() != expected) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_REG_DWORD_EXISTS_AND_EQ(name, expected) \ do { \ mozilla::LauncherResult> result = \ ReadRegistryValueData(name, REG_DWORD); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.inspect().isNothing() || \ result.inspect().value() != expected) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_REG_QWORD_EXISTS(name) \ do { \ mozilla::LauncherResult> result = \ ReadRegistryValueData(name, REG_QWORD); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.inspect().isNothing()) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_REG_QWORD_EXISTS_AND_EQ(name, expected) \ do { \ mozilla::LauncherResult> result = \ ReadRegistryValueData(name, REG_QWORD); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.inspect().isNothing() || \ result.inspect().value() != expected) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_REG_DWORD_DOES_NOT_EXIST(name) \ do { \ mozilla::LauncherResult> result = \ ReadRegistryValueData(name, REG_DWORD); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.inspect().isSome()) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) #define EXPECT_REG_QWORD_DOES_NOT_EXIST(name) \ do { \ mozilla::LauncherResult> result = \ ReadRegistryValueData(name, REG_QWORD); \ if (result.isErr()) { \ return result.propagateErr(); \ } \ if (result.inspect().isSome()) { \ return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); \ } \ } while (0) template static mozilla::LauncherResult> ReadRegistryValueData( const std::wstring& name, DWORD expectedType) { T data; DWORD dataLen = sizeof(data); DWORD type; LSTATUS status = ::RegGetValueW(HKEY_CURRENT_USER, kRegKeyPath, name.c_str(), RRF_RT_ANY, &type, &data, &dataLen); if (status == ERROR_FILE_NOT_FOUND) { return mozilla::Maybe(); } if (status != ERROR_SUCCESS) { return LAUNCHER_ERROR_FROM_WIN32(status); } if (type != expectedType) { return LAUNCHER_ERROR_FROM_WIN32(ERROR_DATATYPE_MISMATCH); } return mozilla::Some(data); } template static mozilla::LauncherVoidResult WriteRegistryValueData( const std::wstring& name, DWORD type, T data) { LSTATUS status = ::RegSetKeyValueW(HKEY_CURRENT_USER, kRegKeyPath, name.c_str(), type, &data, sizeof(T)); if (status != ERROR_SUCCESS) { return LAUNCHER_ERROR_FROM_WIN32(status); } return mozilla::Ok(); } static mozilla::LauncherVoidResult DeleteRegistryValueData( const std::wstring& name) { LSTATUS status = ::RegDeleteKeyValueW(HKEY_CURRENT_USER, kRegKeyPath, name.c_str()); if (status == ERROR_SUCCESS || status == ERROR_FILE_NOT_FOUND) { return mozilla::Ok(); } return LAUNCHER_ERROR_FROM_WIN32(status); } static mozilla::LauncherVoidResult DeleteAllRegstryValues() { // Unblock commit via ReflectPrefToRegistry // (We need to set false, and then true to bypass the early return) mozilla::LauncherRegistryInfo info; mozilla::LauncherVoidResult vr = info.ReflectPrefToRegistry(false); vr = info.ReflectPrefToRegistry(true); if (vr.isErr()) { return vr; } vr = DeleteRegistryValueData(gImageValue); if (vr.isErr()) { return vr; } vr = DeleteRegistryValueData(gLauncherValue); if (vr.isErr()) { return vr; } vr = DeleteRegistryValueData(gBrowserValue); if (vr.isErr()) { return vr; } return DeleteRegistryValueData(gTelemetryValue); } static mozilla::LauncherVoidResult SetupEnabledScenario() { // Reset the registry state to an enabled state. First, we delete all existing // registry values (if any). mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } // Now we run Check(Launcher)... mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); EXPECT_COMMIT_IS_OK(); // ...and Check(Browser) EXPECT_CHECK_RESULT_IS(ProcessType::Browser, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); // By this point we are considered to be fully enabled. return mozilla::Ok(); } static mozilla::LauncherVoidResult TestEmptyRegistry() { mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); EXPECT_COMMIT_IS_OK(); // LauncherRegistryInfo should have created Launcher and Image values EXPECT_REG_DWORD_EXISTS_AND_EQ(gImageValue, gMyImageTimestamp); EXPECT_REG_QWORD_EXISTS(gLauncherValue); EXPECT_REG_QWORD_DOES_NOT_EXIST(gBrowserValue); EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestNormal() { mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gImageValue, REG_DWORD, gMyImageTimestamp); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gLauncherValue, REG_QWORD, QPCNowRaw()); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Browser, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); // Make sure the browser timestamp is newer than the launcher's mozilla::LauncherResult> launcherTs = ReadRegistryValueData(gLauncherValue, REG_QWORD); if (launcherTs.isErr()) { return launcherTs.propagateErr(); } mozilla::LauncherResult> browserTs = ReadRegistryValueData(gBrowserValue, REG_QWORD); if (browserTs.isErr()) { return browserTs.propagateErr(); } if (launcherTs.inspect().isNothing() || browserTs.inspect().isNothing() || browserTs.inspect().value() <= launcherTs.inspect().value()) { return LAUNCHER_ERROR_FROM_HRESULT(E_FAIL); } EXPECT_ENABLED_STATE_IS(EnabledState::Enabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestBrowserNoLauncher() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } vr = DeleteRegistryValueData(gLauncherValue); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); // Verify that we still don't have a launcher timestamp EXPECT_REG_QWORD_DOES_NOT_EXIST(gLauncherValue); // Verify that the browser timestamp is now zero EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, 0ULL); EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestLauncherNoBrowser() { constexpr uint64_t launcherTs = 0x77777777; mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gImageValue, REG_DWORD, gMyImageTimestamp); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gLauncherValue, REG_QWORD, launcherTs); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); // Launcher's timestamps is kept intact while browser's is set to 0. EXPECT_REG_QWORD_EXISTS_AND_EQ(gLauncherValue, launcherTs); EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, 0ULL); EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestBrowserLessThanLauncher() { constexpr uint64_t launcherTs = 0x77777777, browserTs = 0x66666666; mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gImageValue, REG_DWORD, gMyImageTimestamp); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gLauncherValue, REG_QWORD, launcherTs); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gBrowserValue, REG_QWORD, browserTs); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); // Launcher's timestamps is kept intact while browser's is set to 0. EXPECT_REG_QWORD_EXISTS_AND_EQ(gLauncherValue, launcherTs); EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, 0ULL); EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestImageTimestampChange() { // This should reset the timestamps and then essentially run like // TestEmptyRegistry mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gImageValue, REG_DWORD, 0x12345678); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gLauncherValue, REG_QWORD, 1ULL); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gBrowserValue, REG_QWORD, 2ULL); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); EXPECT_COMMIT_IS_OK(); EXPECT_REG_DWORD_EXISTS_AND_EQ(gImageValue, gMyImageTimestamp); EXPECT_REG_QWORD_EXISTS(gLauncherValue); EXPECT_REG_QWORD_DOES_NOT_EXIST(gBrowserValue); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestImageTimestampChangeWhenDisabled() { mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gImageValue, REG_DWORD, 0x12345678); if (vr.isErr()) { return vr; } vr = WriteRegistryValueData(gBrowserValue, REG_QWORD, 0ULL); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); EXPECT_REG_DWORD_EXISTS_AND_EQ(gImageValue, gMyImageTimestamp); EXPECT_REG_QWORD_DOES_NOT_EXIST(gLauncherValue); EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, 0); EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestDisableDueToFailure() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } // Check that we are indeed enabled. mozilla::LauncherRegistryInfo info; EXPECT_ENABLED_STATE_IS(EnabledState::Enabled); // Now call DisableDueToFailure mozilla::LauncherVoidResult lvr = info.DisableDueToFailure(); if (lvr.isErr()) { return lvr.propagateErr(); } // We should now be FailDisabled EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); // If we delete the launcher timestamp, IsEnabled should then return // ForceDisabled. vr = DeleteRegistryValueData(gLauncherValue); if (vr.isErr()) { return vr; } EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestPrefReflection() { // Reset the registry to a known good state. mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } // Let's see what happens when we flip the pref to OFF. mozilla::LauncherRegistryInfo info; mozilla::LauncherVoidResult reflectOk = info.ReflectPrefToRegistry(false); if (reflectOk.isErr()) { return reflectOk.propagateErr(); } // Launcher timestamp should be non-existent. EXPECT_REG_QWORD_DOES_NOT_EXIST(gLauncherValue); // Browser timestamp should be zero EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, 0ULL); // IsEnabled should give us ForceDisabled EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); // Now test to see what happens when the pref is set to ON. reflectOk = info.ReflectPrefToRegistry(true); if (reflectOk.isErr()) { return reflectOk.propagateErr(); } // Launcher and browser timestamps should be non-existent. EXPECT_REG_QWORD_DOES_NOT_EXIST(gLauncherValue); EXPECT_REG_QWORD_DOES_NOT_EXIST(gBrowserValue); // IsEnabled should give us Enabled. EXPECT_ENABLED_STATE_IS(EnabledState::Enabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestTelemetryConfig() { mozilla::LauncherVoidResult vr = DeleteAllRegstryValues(); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_TELEMETRY_IS_ENABLED(false); mozilla::LauncherVoidResult reflectOk = info.ReflectTelemetryPrefToRegistry(false); if (reflectOk.isErr()) { return reflectOk.propagateErr(); } EXPECT_TELEMETRY_IS_ENABLED(false); reflectOk = info.ReflectTelemetryPrefToRegistry(true); if (reflectOk.isErr()) { return reflectOk.propagateErr(); } EXPECT_TELEMETRY_IS_ENABLED(true); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestCommitAbort() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } // Retrieve the current timestamps to compare later mozilla::LauncherResult> launcherValue = ReadRegistryValueData(gLauncherValue, REG_QWORD); if (launcherValue.isErr() || launcherValue.inspect().isNothing()) { return launcherValue.propagateErr(); } mozilla::LauncherResult> browserValue = ReadRegistryValueData(gBrowserValue, REG_QWORD); if (browserValue.isErr() || browserValue.inspect().isNothing()) { return browserValue.propagateErr(); } uint64_t launcherTs = launcherValue.inspect().value(); uint64_t browserTs = browserValue.inspect().value(); vr = []() -> mozilla::LauncherVoidResult { mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); // No commit return mozilla::Ok(); }(); if (vr.isErr()) { return vr; } // Exiting the scope discards the change. mozilla::LauncherRegistryInfo info; EXPECT_REG_DWORD_EXISTS_AND_EQ(gImageValue, gMyImageTimestamp); EXPECT_REG_QWORD_EXISTS_AND_EQ(gLauncherValue, launcherTs); EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, browserTs); // Commit -> Check -> Abort -> Commit EXPECT_COMMIT_IS_OK(); EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); info.Abort(); EXPECT_COMMIT_IS_OK(); // Nothing is changed. EXPECT_REG_DWORD_EXISTS_AND_EQ(gImageValue, gMyImageTimestamp); EXPECT_REG_QWORD_EXISTS_AND_EQ(gLauncherValue, launcherTs); EXPECT_REG_QWORD_EXISTS_AND_EQ(gBrowserValue, browserTs); EXPECT_ENABLED_STATE_IS(EnabledState::Enabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestDisableDuringLauncherLaunch() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } mozilla::LauncherResult> launcherTs = ReadRegistryValueData(gLauncherValue, REG_QWORD); if (launcherTs.isErr()) { return launcherTs.propagateErr(); } if (launcherTs.inspect().isNothing()) { return LAUNCHER_ERROR_FROM_HRESULT(E_UNEXPECTED); } vr = []() -> mozilla::LauncherVoidResult { mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); // Call DisableDueToFailure with a different instance mozilla::LauncherVoidResult vr = []() -> mozilla::LauncherVoidResult { mozilla::LauncherRegistryInfo info; mozilla::LauncherVoidResult vr = info.DisableDueToFailure(); if (vr.isErr()) { return vr.propagateErr(); } return mozilla::Ok(); }(); if (vr.isErr()) { return vr; } // Commit after disable. EXPECT_COMMIT_IS_OK(); return mozilla::Ok(); }(); if (vr.isErr()) { return vr; } // Make sure we're still FailDisabled and the launcher's timestamp is not // updated mozilla::LauncherRegistryInfo info; EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); EXPECT_REG_QWORD_EXISTS_AND_EQ(gLauncherValue, launcherTs.inspect().value()); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestDisableDuringBrowserLaunch() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); EXPECT_COMMIT_IS_OK(); vr = []() -> mozilla::LauncherVoidResult { mozilla::LauncherRegistryInfo info; EXPECT_CHECK_RESULT_IS(ProcessType::Browser, ProcessType::Browser); // Call DisableDueToFailure with a different instance mozilla::LauncherVoidResult vr = []() -> mozilla::LauncherVoidResult { mozilla::LauncherRegistryInfo info; mozilla::LauncherVoidResult vr = info.DisableDueToFailure(); if (vr.isErr()) { return vr.propagateErr(); } return mozilla::Ok(); }(); if (vr.isErr()) { return vr; } // Commit after disable. EXPECT_COMMIT_IS_OK(); return mozilla::Ok(); }(); if (vr.isErr()) { return vr; } // Make sure we're still FailDisabled EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); return mozilla::Ok(); } static mozilla::LauncherVoidResult TestReEnable() { mozilla::LauncherVoidResult vr = SetupEnabledScenario(); if (vr.isErr()) { return vr; } // Make FailDisabled mozilla::LauncherRegistryInfo info; vr = info.DisableDueToFailure(); if (vr.isErr()) { return vr.propagateErr(); } EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); // Attempt to launch when FailDisabled: Still be FailDisabled EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); EXPECT_ENABLED_STATE_IS(EnabledState::FailDisabled); // Change the timestamp vr = WriteRegistryValueData(gImageValue, REG_DWORD, 0x12345678); if (vr.isErr()) { return vr; } // Attempt to launch again: Launcher comes back EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Launcher); EXPECT_COMMIT_IS_OK(); // Make ForceDisabled vr = info.ReflectPrefToRegistry(false); if (vr.isErr()) { return vr.propagateErr(); } EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); // Attempt to launch when ForceDisabled: Still be ForceDisabled EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); // Change the timestamp vr = WriteRegistryValueData(gImageValue, REG_DWORD, 0x12345678); if (vr.isErr()) { return vr; } // Attempt to launch again: Still be ForceDisabled EXPECT_CHECK_RESULT_IS(ProcessType::Launcher, ProcessType::Browser); EXPECT_COMMIT_IS_OK(); EXPECT_ENABLED_STATE_IS(EnabledState::ForceDisabled); return mozilla::Ok(); } int main(int argc, char* argv[]) { auto fullPath = mozilla::GetFullBinaryPath(); if (!fullPath) { return 1; } // Global setup for all tests gBrowserValue = fullPath.get(); gBrowserValue += kBrowserSuffix; gLauncherValue = fullPath.get(); gLauncherValue += kLauncherSuffix; gImageValue = fullPath.get(); gImageValue += kImageSuffix; gTelemetryValue = fullPath.get(); gTelemetryValue += kTelemetrySuffix; mozilla::LauncherResult timestamp = 0; RUN_TEST(timestamp, GetCurrentImageTimestamp); gMyImageTimestamp = timestamp.unwrap(); auto onExit = mozilla::MakeScopeExit( []() { mozilla::Unused << DeleteAllRegstryValues(); }); mozilla::LauncherVoidResult vr = mozilla::Ok(); // All testcases should call SetupEnabledScenario() or // DeleteAllRegstryValues() to be order-independent RUN_TEST(vr, TestEmptyRegistry); RUN_TEST(vr, TestNormal); RUN_TEST(vr, TestBrowserNoLauncher); RUN_TEST(vr, TestLauncherNoBrowser); RUN_TEST(vr, TestBrowserLessThanLauncher); RUN_TEST(vr, TestImageTimestampChange); RUN_TEST(vr, TestImageTimestampChangeWhenDisabled); RUN_TEST(vr, TestDisableDueToFailure); RUN_TEST(vr, TestPrefReflection); RUN_TEST(vr, TestTelemetryConfig); RUN_TEST(vr, TestCommitAbort); RUN_TEST(vr, TestDisableDuringLauncherLaunch); RUN_TEST(vr, TestDisableDuringBrowserLaunch); RUN_TEST(vr, TestReEnable); return 0; }