diff options
| -rw-r--r-- | base/BUILD.gn | 1 | ||||
| -rw-r--r-- | base/base.gyp | 1 | ||||
| -rw-r--r-- | base/win/windows_version.cc | 110 | ||||
| -rw-r--r-- | base/win/windows_version.h | 24 | ||||
| -rw-r--r-- | base/win/windows_version_unittest.cc | 22 | ||||
| -rw-r--r-- | chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc | 10 | ||||
| -rw-r--r-- | tools/metrics/histograms/histograms.xml | 33 |
7 files changed, 159 insertions, 42 deletions
diff --git a/base/BUILD.gn b/base/BUILD.gn index 0b41b0e..b3e2707 100644 --- a/base/BUILD.gn +++ b/base/BUILD.gn @@ -1851,6 +1851,7 @@ test("base_unittests") { "win/shortcut_unittest.cc", "win/startup_information_unittest.cc", "win/win_util_unittest.cc", + "win/windows_version_unittest.cc", "win/wrapped_window_proc_unittest.cc", ] diff --git a/base/base.gyp b/base/base.gyp index 5b20cfe..52adb62 100644 --- a/base/base.gyp +++ b/base/base.gyp @@ -599,6 +599,7 @@ 'win/shortcut_unittest.cc', 'win/startup_information_unittest.cc', 'win/win_util_unittest.cc', + 'win/windows_version_unittest.cc', 'win/wrapped_window_proc_unittest.cc', '<@(trace_event_test_sources)', ], diff --git a/base/win/windows_version.cc b/base/win/windows_version.cc index 7a8b8fd..d2f766e 100644 --- a/base/win/windows_version.cc +++ b/base/win/windows_version.cc @@ -6,17 +6,81 @@ #include <windows.h> +#include "base/file_version_info_win.h" +#include "base/files/file_path.h" #include "base/logging.h" +#include "base/memory/scoped_ptr.h" #include "base/strings/utf_string_conversions.h" #include "base/win/registry.h" namespace { typedef BOOL (WINAPI *GetProductInfoPtr)(DWORD, DWORD, DWORD, DWORD, PDWORD); -} +} // namespace namespace base { namespace win { +namespace { + +// Helper to map a major.minor.x.build version (e.g. 6.1) to a Windows release. +Version MajorMinorBuildToVersion(int major, int minor, int build) { + if ((major == 5) && (minor > 0)) { + // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. + return (minor == 1) ? VERSION_XP : VERSION_SERVER_2003; + } else if (major == 6) { + switch (minor) { + case 0: + // Treat Windows Server 2008 the same as Windows Vista. + return VERSION_VISTA; + case 1: + // Treat Windows Server 2008 R2 the same as Windows 7. + return VERSION_WIN7; + case 2: + // Treat Windows Server 2012 the same as Windows 8. + return VERSION_WIN8; + default: + DCHECK_EQ(minor, 3); + return VERSION_WIN8_1; + } + } else if (major == 10) { + if (build < 10586) { + return VERSION_WIN10; + } else { + return VERSION_WIN10_TH2; + } + } else if (major > 6) { + NOTREACHED(); + return VERSION_WIN_LAST; + } + + NOTREACHED(); + return VERSION_WIN_LAST; +} + +// Retrieve a version from kernel32. This is useful because when running in +// compatibility mode for a down-level version of the OS, the file version of +// kernel32 will still be the "real" version. +Version GetVersionFromKernel32() { + scoped_ptr<FileVersionInfoWin> file_version_info( + static_cast<FileVersionInfoWin*>( + FileVersionInfoWin::CreateFileVersionInfo( + base::FilePath(FILE_PATH_LITERAL("kernel32.dll"))))); + if (file_version_info) { + const int major = + HIWORD(file_version_info->fixed_file_info()->dwFileVersionMS); + const int minor = + LOWORD(file_version_info->fixed_file_info()->dwFileVersionMS); + const int build = + HIWORD(file_version_info->fixed_file_info()->dwFileVersionLS); + return MajorMinorBuildToVersion(major, minor, build); + } + + NOTREACHED(); + return VERSION_WIN_LAST; +} + +} // namespace + // static OSInfo* OSInfo::GetInstance() { // Note: we don't use the Singleton class because it depends on AtExitManager, @@ -35,6 +99,8 @@ OSInfo* OSInfo::GetInstance() { OSInfo::OSInfo() : version_(VERSION_PRE_XP), + kernel32_version_(VERSION_PRE_XP), + got_kernel32_version_(false), architecture_(OTHER_ARCHITECTURE), wow64_status_(GetWOW64StatusForProcess(GetCurrentProcess())) { OSVERSIONINFOEX version_info = { sizeof version_info }; @@ -42,38 +108,8 @@ OSInfo::OSInfo() version_number_.major = version_info.dwMajorVersion; version_number_.minor = version_info.dwMinorVersion; version_number_.build = version_info.dwBuildNumber; - if ((version_number_.major == 5) && (version_number_.minor > 0)) { - // Treat XP Pro x64, Home Server, and Server 2003 R2 as Server 2003. - version_ = (version_number_.minor == 1) ? VERSION_XP : VERSION_SERVER_2003; - } else if (version_number_.major == 6) { - switch (version_number_.minor) { - case 0: - // Treat Windows Server 2008 the same as Windows Vista. - version_ = VERSION_VISTA; - break; - case 1: - // Treat Windows Server 2008 R2 the same as Windows 7. - version_ = VERSION_WIN7; - break; - case 2: - // Treat Windows Server 2012 the same as Windows 8. - version_ = VERSION_WIN8; - break; - default: - DCHECK_EQ(version_number_.minor, 3); - version_ = VERSION_WIN8_1; - break; - } - } else if (version_number_.major == 10) { - if (version_number_.build < 10586) { - version_ = VERSION_WIN10; - } else { - version_ = VERSION_WIN10_TH2; - } - } else if (version_number_.major > 6) { - NOTREACHED(); - version_ = VERSION_WIN_LAST; - } + version_ = MajorMinorBuildToVersion( + version_number_.major, version_number_.minor, version_number_.build); service_pack_.major = version_info.wServicePackMajor; service_pack_.minor = version_info.wServicePackMinor; @@ -149,6 +185,14 @@ OSInfo::OSInfo() OSInfo::~OSInfo() { } +Version OSInfo::Kernel32Version() const { + if (!got_kernel32_version_) { + kernel32_version_ = GetVersionFromKernel32(); + got_kernel32_version_ = true; + } + return kernel32_version_; +} + std::string OSInfo::processor_model_name() { if (processor_model_name_.empty()) { const wchar_t kProcessorNameString[] = diff --git a/base/win/windows_version.h b/base/win/windows_version.h index 676bd97..7bc8b6f 100644 --- a/base/win/windows_version.h +++ b/base/win/windows_version.h @@ -21,17 +21,20 @@ namespace win { // syntactic sugar reasons; see the declaration of GetVersion() below. // NOTE: Keep these in order so callers can do things like // "if (base::win::GetVersion() >= base::win::VERSION_VISTA) ...". +// +// This enum is used in metrics histograms, so they shouldn't be reordered or +// removed. New values can be added before VERSION_WIN_LAST. enum Version { VERSION_PRE_XP = 0, // Not supported. - VERSION_XP, - VERSION_SERVER_2003, // Also includes XP Pro x64 and Server 2003 R2. - VERSION_VISTA, // Also includes Windows Server 2008. - VERSION_WIN7, // Also includes Windows Server 2008 R2. - VERSION_WIN8, // Also includes Windows Server 2012. - VERSION_WIN8_1, // Also includes Windows Server 2012 R2. - VERSION_WIN10, // Also includes Windows 10 Server. - VERSION_WIN10_TH2, // Threshold 2: Version 1511, Build 10586. - VERSION_WIN_LAST, // Indicates error condition. + VERSION_XP = 1, + VERSION_SERVER_2003 = 2, // Also includes XP Pro x64 and Server 2003 R2. + VERSION_VISTA = 3, // Also includes Windows Server 2008. + VERSION_WIN7 = 4, // Also includes Windows Server 2008 R2. + VERSION_WIN8 = 5, // Also includes Windows Server 2012. + VERSION_WIN8_1 = 6, // Also includes Windows Server 2012 R2. + VERSION_WIN10 = 7, // Also includes Windows 10 Server. + VERSION_WIN10_TH2 = 8, // Threshold 2: Version 1511, Build 10586. + VERSION_WIN_LAST, // Indicates error condition. }; // A rough bucketing of the available types of versions of Windows. This is used @@ -86,6 +89,7 @@ class BASE_EXPORT OSInfo { static OSInfo* GetInstance(); Version version() const { return version_; } + Version Kernel32Version() const; // The next two functions return arrays of values, [major, minor(, build)]. VersionNumber version_number() const { return version_number_; } VersionType version_type() const { return version_type_; } @@ -105,6 +109,8 @@ class BASE_EXPORT OSInfo { ~OSInfo(); Version version_; + mutable Version kernel32_version_; + mutable bool got_kernel32_version_; VersionNumber version_number_; VersionType version_type_; ServicePack service_pack_; diff --git a/base/win/windows_version_unittest.cc b/base/win/windows_version_unittest.cc new file mode 100644 index 0000000..f0d6d96 --- /dev/null +++ b/base/win/windows_version_unittest.cc @@ -0,0 +1,22 @@ +// Copyright 2016 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "base/win/windows_version.h" + +#include "testing/gtest/include/gtest/gtest.h" + +namespace base { +namespace win { +namespace { + +TEST(WindowsVersion, GetVersionExAndKernelVersionMatch) { + // If this fails, we're running in compatibility mode, or need to update the + // application manifest. + EXPECT_EQ(OSInfo::GetInstance()->version(), + OSInfo::GetInstance()->Kernel32Version()); +} + +} // namespace +} // namespace win +} // namespace base diff --git a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc index 11b1c17..58f4af4 100644 --- a/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc +++ b/chrome/browser/metrics/chrome_browser_main_extra_parts_metrics.cc @@ -51,6 +51,7 @@ #endif // defined(USE_OZONE) || defined(USE_X11) #if defined(OS_WIN) +#include "base/win/windows_version.h" #include "chrome/installer/util/google_update_settings.h" #endif // defined(OS_WIN) @@ -140,6 +141,15 @@ void RecordMicroArchitectureStats() { void RecordStartupMetricsOnBlockingPool() { #if defined(OS_WIN) GoogleUpdateSettings::RecordChromeUpdatePolicyHistograms(); + + const base::win::OSInfo& os_info = *base::win::OSInfo::GetInstance(); + UMA_HISTOGRAM_ENUMERATION("Windows.GetVersionExVersion", os_info.version(), + base::win::VERSION_WIN_LAST); + UMA_HISTOGRAM_ENUMERATION("Windows.Kernel32Version", + os_info.Kernel32Version(), + base::win::VERSION_WIN_LAST); + UMA_HISTOGRAM_BOOLEAN("Windows.InCompatibilityMode", + os_info.version() != os_info.Kernel32Version()); #endif // defined(OS_WIN) #if defined(OS_MACOSX) diff --git a/tools/metrics/histograms/histograms.xml b/tools/metrics/histograms/histograms.xml index 4540b38..1cd4a80 100644 --- a/tools/metrics/histograms/histograms.xml +++ b/tools/metrics/histograms/histograms.xml @@ -58501,6 +58501,31 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. </summary> </histogram> +<histogram name="Windows.GetVersionExVersion" enum="WindowsVersion"> + <owner>scottmg@chromium.org</owner> + <summary> + The Windows version (base::win::Version) as reported by GetVersionEx(). This + is queried shortly after startup. + </summary> +</histogram> + +<histogram name="Windows.InCompatibilityMode" enum="BooleanCompatibilityMode"> + <owner>scottmg@chromium.org</owner> + <summary> + A boolean used to indicate when the Windows version reported by + GetVersionEx() and the Windows version reported by VerQueryValue() on + kernel32 do not match. This is queried shortly after startup. + </summary> +</histogram> + +<histogram name="Windows.Kernel32Version" enum="WindowsVersion"> + <owner>scottmg@chromium.org</owner> + <summary> + The Windows version (base::win::Version) as reported by VeryQueryValue() on + kernel32.dll. This is queried shortly after startup. + </summary> +</histogram> + <histogram name="Windows.Tablet" enum="BooleanTablet"> <owner>zturner@chromium.org</owner> <summary>Count of browser launches from a Windows tablet pc.</summary> @@ -60190,6 +60215,11 @@ http://cs/file:chrome/histograms.xml - but prefer this file for new entries. <int value="1" label="Common Name used"/> </enum> +<enum name="BooleanCompatibilityMode" type="int"> + <int value="0" label="Not in compatibility mode"/> + <int value="1" label="In compatibility mode"/> +</enum> + <enum name="BooleanCompleted" type="int"> <int value="0" label="Not Completed"/> <int value="1" label="Completed"/> @@ -84218,6 +84248,9 @@ To add a new entry, add it with any value and run test to compute valid value. <int value="3" label="Vista"/> <int value="4" label="Windows 7"/> <int value="5" label="Windows 8"/> + <int value="6" label="Windows 8.1"/> + <int value="7" label="Windows 10"/> + <int value="8" label="Windows 10 TH2"/> </enum> <enum name="WindowType" type="int"> |
