diff options
Diffstat (limited to 'chromium/base')
-rw-r--r-- | chromium/base/BUILD.gn | 1 | ||||
-rw-r--r-- | chromium/base/base.gyp | 1 | ||||
-rw-r--r-- | chromium/base/win/win_util.cc | 95 | ||||
-rw-r--r-- | chromium/base/win/windows_version.cc | 105 | ||||
-rw-r--r-- | chromium/base/win/windows_version.h | 23 | ||||
-rw-r--r-- | chromium/base/win/windows_version_unittest.cc | 22 |
6 files changed, 207 insertions, 40 deletions
diff --git a/chromium/base/BUILD.gn b/chromium/base/BUILD.gn index 1265df839b5..8f21b5825ca 100644 --- a/chromium/base/BUILD.gn +++ b/chromium/base/BUILD.gn @@ -1856,6 +1856,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/chromium/base/base.gyp b/chromium/base/base.gyp index 94a1d492585..dc794be5064 100644 --- a/chromium/base/base.gyp +++ b/chromium/base/base.gyp @@ -669,6 +669,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/chromium/base/win/win_util.cc b/chromium/base/win/win_util.cc index 57bee8a57a7..85612a247dd 100644 --- a/chromium/base/win/win_util.cc +++ b/chromium/base/win/win_util.cc @@ -12,13 +12,20 @@ #include <shlobj.h> #include <shobjidl.h> // Must be before propkey. #include <initguid.h> +#include <inspectable.h> #include <propkey.h> #include <propvarutil.h> +#include <psapi.h> +#include <roapi.h> #include <sddl.h> #include <setupapi.h> #include <signal.h> #include <stddef.h> #include <stdlib.h> +#include <uiviewsettingsinterop.h> +#include <windows.ui.viewmanagement.h> +#include <winstring.h> +#include <wrl/wrappers/corewrappers.h> #include "base/base_switches.h" #include "base/command_line.h" @@ -32,6 +39,7 @@ #include "base/threading/thread_restrictions.h" #include "base/win/registry.h" #include "base/win/scoped_co_mem.h" +#include "base/win/scoped_comptr.h" #include "base/win/scoped_handle.h" #include "base/win/scoped_propvariant.h" #include "base/win/windows_version.h" @@ -106,6 +114,82 @@ POWER_PLATFORM_ROLE GetPlatformRole() { return PowerDeterminePlatformRoleEx(POWER_PLATFORM_ROLE_V2); } +// Uses the Windows 10 WRL API's to query the current system state. The API's +// we are using in the function below are supported in Win32 apps as per msdn. +// It looks like the API implementation is buggy at least on Surface 4 causing +// it to always return UserInteractionMode_Touch which as per documentation +// indicates tablet mode. +bool IsWindows10TabletDevice() { + if (GetVersion() < VERSION_WIN10) + return false; + + using RoGetActivationFactoryFunction = decltype(&RoGetActivationFactory); + using WindowsCreateStringFunction = decltype(&WindowsCreateString); + + static RoGetActivationFactoryFunction get_factory = nullptr; + static WindowsCreateStringFunction create_string = nullptr; + + if (!get_factory) { + DCHECK_EQ(create_string, static_cast<WindowsCreateStringFunction>( + nullptr)); + + HMODULE combase_dll = ::LoadLibrary(L"combase.dll"); + if (!combase_dll) + return false; + + get_factory = reinterpret_cast<RoGetActivationFactoryFunction>( + ::GetProcAddress(combase_dll, "RoGetActivationFactory")); + if (!get_factory) { + CHECK(false); + return false; + } + + create_string = reinterpret_cast<WindowsCreateStringFunction>( + ::GetProcAddress(combase_dll, "WindowsCreateString")); + if (!create_string) { + CHECK(false); + return false; + } + } + + HRESULT hr = E_FAIL; + // This HSTRING is allocated on the heap and is leaked. + static HSTRING view_settings_guid = NULL; + if (!view_settings_guid) { + hr = create_string( + RuntimeClass_Windows_UI_ViewManagement_UIViewSettings, + static_cast<UINT32>( + wcslen(RuntimeClass_Windows_UI_ViewManagement_UIViewSettings)), + &view_settings_guid); + if (FAILED(hr)) + return false; + } + + base::win::ScopedComPtr<IUIViewSettingsInterop> view_settings_interop; + hr = get_factory(view_settings_guid, + __uuidof(IUIViewSettingsInterop), + view_settings_interop.ReceiveVoid()); + if (FAILED(hr)) + return false; + + base::win::ScopedComPtr<ABI::Windows::UI::ViewManagement::IUIViewSettings> + view_settings; + // TODO(ananta) + // Avoid using GetForegroundWindow here and pass in the HWND of the window + // intiating the request to display the keyboard. + hr = view_settings_interop->GetForWindow( + ::GetForegroundWindow(), + __uuidof(ABI::Windows::UI::ViewManagement::IUIViewSettings), + view_settings.ReceiveVoid()); + if (FAILED(hr)) + return false; + + ABI::Windows::UI::ViewManagement::UserInteractionMode mode = + ABI::Windows::UI::ViewManagement::UserInteractionMode_Mouse; + view_settings->get_UserInteractionMode(&mode); + return mode == ABI::Windows::UI::ViewManagement::UserInteractionMode_Touch; +} + } // namespace // Returns true if a physical keyboard is detected on Windows 8 and up. @@ -140,10 +224,11 @@ bool IsKeyboardPresentOnSlate(std::string* reason) { } } + // If it is a tablet device we assume that there is no keyboard attached. if (IsTabletDevice(reason)) { if (reason) *reason += "Tablet device.\n"; - return true; + return false; } else { if (reason) { *reason += "Not a tablet device"; @@ -390,6 +475,9 @@ bool IsTabletDevice(std::string* reason) { return false; } + if (IsWindows10TabletDevice()) + return true; + if (GetSystemMetrics(SM_MAXIMUMTOUCHES) == 0) { if (reason) { *reason += "Device does not support touch.\n"; @@ -413,8 +501,9 @@ bool IsTabletDevice(std::string* reason) { bool slate_power_profile = (role == PlatformRoleSlate); bool is_tablet = false; - + bool is_tablet_pc = false; if (mobile_power_profile || slate_power_profile) { + is_tablet_pc = !GetSystemMetrics(SM_TABLETPC); is_tablet = !GetSystemMetrics(SM_CONVERTIBLESLATEMODE); if (!is_tablet) { if (reason) { @@ -432,7 +521,7 @@ bool IsTabletDevice(std::string* reason) { if (reason) *reason += "Device role is not mobile or slate.\n"; } - return is_tablet; + return is_tablet && is_tablet_pc; } bool DisplayVirtualKeyboard() { diff --git a/chromium/base/win/windows_version.cc b/chromium/base/win/windows_version.cc index 35cdbb3538a..eb3f4993d2c 100644 --- a/chromium/base/win/windows_version.cc +++ b/chromium/base/win/windows_version.cc @@ -6,17 +6,80 @@ #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; + } + + return VERSION_PRE_XP; +} + +// 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 +98,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,34 +107,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) { - version_ = VERSION_WIN10; - } 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; @@ -145,6 +184,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/chromium/base/win/windows_version.h b/chromium/base/win/windows_version.h index c9bbd4f3eb7..7bc8b6fe560 100644 --- a/chromium/base/win/windows_version.h +++ b/chromium/base/win/windows_version.h @@ -21,16 +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_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 @@ -85,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_; } @@ -104,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/chromium/base/win/windows_version_unittest.cc b/chromium/base/win/windows_version_unittest.cc new file mode 100644 index 00000000000..f0d6d9660d7 --- /dev/null +++ b/chromium/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 |