/* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */ /* 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 http://mozilla.org/MPL/2.0/. */ const { UpdateUtils } = ChromeUtils.importESModule( "resource://gre/modules/UpdateUtils.sys.mjs" ); const { AppConstants } = ChromeUtils.importESModule( "resource://gre/modules/AppConstants.sys.mjs" ); const { getAppInfo, updateAppInfo } = ChromeUtils.importESModule( "resource://testing-common/AppInfo.sys.mjs" ); const { ctypes } = ChromeUtils.importESModule( "resource://gre/modules/ctypes.sys.mjs" ); ChromeUtils.defineESModuleGetters(this, { WindowsRegistry: "resource://gre/modules/WindowsRegistry.sys.mjs", }); const PREF_APP_UPDATE_CHANNEL = "app.update.channel"; const PREF_APP_PARTNER_BRANCH = "app.partner."; const PREF_DISTRIBUTION_ID = "distribution.id"; const PREF_DISTRIBUTION_VERSION = "distribution.version"; const URL_PREFIX = "http://localhost/"; const MSG_SHOULD_EQUAL = " should equal the expected value"; updateAppInfo(); const gAppInfo = getAppInfo(); const gDefaultPrefBranch = Services.prefs.getDefaultBranch(null); function setUpdateChannel(aChannel) { gDefaultPrefBranch.setCharPref(PREF_APP_UPDATE_CHANNEL, aChannel); } function getServicePack() { // NOTE: This function is a helper function and not a test. Thus, // it uses throw() instead of do_throw(). Any tests that use this function // should catch exceptions thrown in this function and deal with them // appropriately (usually by calling do_throw). const BYTE = ctypes.uint8_t; const WORD = ctypes.uint16_t; const DWORD = ctypes.uint32_t; const WCHAR = ctypes.char16_t; const BOOL = ctypes.int; // This structure is described at: // http://msdn.microsoft.com/en-us/library/ms724833%28v=vs.85%29.aspx const SZCSDVERSIONLENGTH = 128; const OSVERSIONINFOEXW = new ctypes.StructType("OSVERSIONINFOEXW", [ { dwOSVersionInfoSize: DWORD }, { dwMajorVersion: DWORD }, { dwMinorVersion: DWORD }, { dwBuildNumber: DWORD }, { dwPlatformId: DWORD }, { szCSDVersion: ctypes.ArrayType(WCHAR, SZCSDVERSIONLENGTH) }, { wServicePackMajor: WORD }, { wServicePackMinor: WORD }, { wSuiteMask: WORD }, { wProductType: BYTE }, { wReserved: BYTE }, ]); let kernel32 = ctypes.open("kernel32"); try { let GetVersionEx = kernel32.declare( "GetVersionExW", ctypes.winapi_abi, BOOL, OSVERSIONINFOEXW.ptr ); let winVer = OSVERSIONINFOEXW(); winVer.dwOSVersionInfoSize = OSVERSIONINFOEXW.size; if (0 === GetVersionEx(winVer.address())) { // Using "throw" instead of "do_throw" (see NOTE above) throw new Error("Failure in GetVersionEx (returned 0)"); } return ( winVer.wServicePackMajor + "." + winVer.wServicePackMinor + "." + winVer.dwBuildNumber ); } finally { kernel32.close(); } } function getProcArchitecture() { // NOTE: This function is a helper function and not a test. Thus, // it uses throw() instead of do_throw(). Any tests that use this function // should catch exceptions thrown in this function and deal with them // appropriately (usually by calling do_throw). const WORD = ctypes.uint16_t; const DWORD = ctypes.uint32_t; // This structure is described at: // http://msdn.microsoft.com/en-us/library/ms724958%28v=vs.85%29.aspx const SYSTEM_INFO = new ctypes.StructType("SYSTEM_INFO", [ { wProcessorArchitecture: WORD }, { wReserved: WORD }, { dwPageSize: DWORD }, { lpMinimumApplicationAddress: ctypes.voidptr_t }, { lpMaximumApplicationAddress: ctypes.voidptr_t }, { dwActiveProcessorMask: DWORD.ptr }, { dwNumberOfProcessors: DWORD }, { dwProcessorType: DWORD }, { dwAllocationGranularity: DWORD }, { wProcessorLevel: WORD }, { wProcessorRevision: WORD }, ]); let kernel32 = ctypes.open("kernel32"); try { let GetNativeSystemInfo = kernel32.declare( "GetNativeSystemInfo", ctypes.winapi_abi, ctypes.void_t, SYSTEM_INFO.ptr ); let sysInfo = SYSTEM_INFO(); // Default to unknown sysInfo.wProcessorArchitecture = 0xffff; GetNativeSystemInfo(sysInfo.address()); switch (sysInfo.wProcessorArchitecture) { case 12: return "aarch64"; case 9: return "x64"; case 6: return "IA64"; case 0: return "x86"; default: // Using "throw" instead of "do_throw" (see NOTE above) throw new Error( "Unknown architecture returned from GetNativeSystemInfo: " + sysInfo.wProcessorArchitecture ); } } finally { kernel32.close(); } } // Gets the supported CPU instruction set. function getInstructionSet() { const CPU_EXTENSIONS = [ "hasSSE4_2", "hasSSE4_1", "hasSSE4A", "hasSSSE3", "hasSSE3", "hasSSE2", "hasSSE", "hasMMX", "hasNEON", "hasARMv7", "hasARMv6", ]; for (let ext of CPU_EXTENSIONS) { if (Services.sysinfo.getProperty(ext)) { return ext.substring(3); } } return "error"; } // Gets the RAM size in megabytes. This will round the value because sysinfo // doesn't always provide RAM in multiples of 1024. function getMemoryMB() { let memoryMB = "unknown"; try { memoryMB = Services.sysinfo.getProperty("memsize"); if (memoryMB) { memoryMB = Math.round(memoryMB / 1024 / 1024); } } catch (e) { do_throw("Error getting system info memsize property. Exception: " + e); } return memoryMB; } // Helper function for formatting a url and getting the result we're // interested in async function getResult(url) { url = await UpdateUtils.formatUpdateURL(url); return url.substr(URL_PREFIX.length).split("/")[0]; } // url constructed with %PRODUCT% add_task(async function test_product() { let url = URL_PREFIX + "%PRODUCT%/"; Assert.equal( await getResult(url), gAppInfo.name, "the url param for %PRODUCT%" + MSG_SHOULD_EQUAL ); }); // url constructed with %VERSION% add_task(async function test_version() { let url = URL_PREFIX + "%VERSION%/"; Assert.equal( await getResult(url), gAppInfo.version, "the url param for %VERSION%" + MSG_SHOULD_EQUAL ); }); // url constructed with %BUILD_ID% add_task(async function test_build_id() { let url = URL_PREFIX + "%BUILD_ID%/"; Assert.equal( await getResult(url), gAppInfo.appBuildID, "the url param for %BUILD_ID%" + MSG_SHOULD_EQUAL ); }); // url constructed with %BUILD_TARGET% // XXX TODO - it might be nice if we tested the actual ABI add_task(async function test_build_target() { let url = URL_PREFIX + "%BUILD_TARGET%/"; let abi; try { abi = gAppInfo.XPCOMABI; } catch (e) { do_throw("nsIXULAppInfo:XPCOMABI not defined\n"); } if (AppConstants.platform == "win") { // Windows build should report the CPU architecture that it's running on. abi += "-" + getProcArchitecture(); } if (AppConstants.ASAN) { // Allow ASan builds to receive their own updates abi += "-asan"; } Assert.equal( await getResult(url), gAppInfo.OS + "_" + abi, "the url param for %BUILD_TARGET%" + MSG_SHOULD_EQUAL ); }); // url constructed with %LOCALE% // Bug 488936 added the update.locale file that stores the update locale add_task(async function test_locale() { // The code that gets the locale accesses the profile which is only available // after calling do_get_profile in xpcshell tests. This prevents an error from // being logged. do_get_profile(); let url = URL_PREFIX + "%LOCALE%/"; Assert.equal( await getResult(url), "en-US", "Assuming we are built with en-US, the url param for %LOCALE%" + MSG_SHOULD_EQUAL ); }); // url constructed with %CHANNEL% add_task(async function test_channel() { let url = URL_PREFIX + "%CHANNEL%/"; setUpdateChannel("test_channel"); Assert.equal( await getResult(url), "test_channel", "the url param for %CHANNEL%" + MSG_SHOULD_EQUAL ); }); // url constructed with %CHANNEL% with distribution partners add_task(async function test_channel_distribution() { let url = URL_PREFIX + "%CHANNEL%/"; gDefaultPrefBranch.setCharPref( PREF_APP_PARTNER_BRANCH + "test_partner1", "test_partner1" ); gDefaultPrefBranch.setCharPref( PREF_APP_PARTNER_BRANCH + "test_partner2", "test_partner2" ); Assert.equal( await getResult(url), "test_channel-cck-test_partner1-test_partner2", "the url param for %CHANNEL%" + MSG_SHOULD_EQUAL ); }); // url constructed with %PLATFORM_VERSION% add_task(async function test_platform_version() { let url = URL_PREFIX + "%PLATFORM_VERSION%/"; Assert.equal( await getResult(url), gAppInfo.platformVersion, "the url param for %PLATFORM_VERSION%" + MSG_SHOULD_EQUAL ); }); // url constructed with %OS_VERSION% add_task(async function test_os_version() { let url = URL_PREFIX + "%OS_VERSION%/"; let osVersion = Services.sysinfo.getProperty("name") + " " + Services.sysinfo.getProperty("version"); if (AppConstants.platform == "win") { try { let servicePack = getServicePack(); osVersion += "." + servicePack; } catch (e) { do_throw("Failure obtaining service pack: " + e); } if ( Services.vc.compare(Services.sysinfo.getProperty("version"), "10") >= 0 ) { const WINDOWS_UBR_KEY_PATH = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"; let ubr = WindowsRegistry.readRegKey( Ci.nsIWindowsRegKey.ROOT_KEY_LOCAL_MACHINE, WINDOWS_UBR_KEY_PATH, "UBR", Ci.nsIWindowsRegKey.WOW64_64 ); osVersion += ubr !== undefined ? "." + ubr : ".unknown"; } try { osVersion += " (" + getProcArchitecture() + ")"; } catch (e) { do_throw("Failed to obtain processor architecture: " + e); } } if (osVersion) { try { osVersion += " (" + Services.sysinfo.getProperty("secondaryLibrary") + ")"; } catch (e) { // Not all platforms have a secondary widget library, so an error is // nothing to worry about. } osVersion = encodeURIComponent(osVersion); } Assert.equal( await getResult(url), osVersion, "the url param for %OS_VERSION%" + MSG_SHOULD_EQUAL ); }); // url constructed with %DISTRIBUTION% add_task(async function test_distribution() { let url = URL_PREFIX + "%DISTRIBUTION%/"; gDefaultPrefBranch.setCharPref(PREF_DISTRIBUTION_ID, "test_distro"); Assert.equal( await getResult(url), "test_distro", "the url param for %DISTRIBUTION%" + MSG_SHOULD_EQUAL ); }); // url constructed with %DISTRIBUTION_VERSION% add_task(async function test_distribution_version() { let url = URL_PREFIX + "%DISTRIBUTION_VERSION%/"; gDefaultPrefBranch.setCharPref( PREF_DISTRIBUTION_VERSION, "test_distro_version" ); Assert.equal( await getResult(url), "test_distro_version", "the url param for %DISTRIBUTION_VERSION%" + MSG_SHOULD_EQUAL ); }); // url constructed with %SYSTEM_CAPABILITIES% add_task(async function test_systemCapabilities() { let url = URL_PREFIX + "%SYSTEM_CAPABILITIES%/"; let systemCapabilities = "ISET:" + getInstructionSet() + ",MEM:" + getMemoryMB(); Assert.equal( await getResult(url), systemCapabilities, "the url param for %SYSTEM_CAPABILITIES%" + MSG_SHOULD_EQUAL ); });