1// Copyright (c) 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#include "base/win/metro.h" 6 7#include "base/message_loop/message_loop.h" 8#include "base/strings/string_util.h" 9#include "base/win/scoped_comptr.h" 10#include "base/win/windows_version.h" 11 12namespace base { 13namespace win { 14 15namespace { 16bool g_should_tsf_aware_required = false; 17} 18 19HMODULE GetMetroModule() { 20 const HMODULE kUninitialized = reinterpret_cast<HMODULE>(1); 21 static HMODULE metro_module = kUninitialized; 22 23 if (metro_module == kUninitialized) { 24 // Initialize the cache, note that the initialization is idempotent 25 // under the assumption that metro_driver is never unloaded, so the 26 // race to this assignment is safe. 27 metro_module = GetModuleHandleA("metro_driver.dll"); 28 if (metro_module != NULL) { 29 // This must be a metro process if the metro_driver is loaded. 30 DCHECK(IsMetroProcess()); 31 } 32 } 33 34 DCHECK(metro_module != kUninitialized); 35 return metro_module; 36} 37 38bool IsMetroProcess() { 39 enum ImmersiveState { 40 kImmersiveUnknown, 41 kImmersiveTrue, 42 kImmersiveFalse 43 }; 44 // The immersive state of a process can never change. 45 // Look it up once and cache it here. 46 static ImmersiveState state = kImmersiveUnknown; 47 48 if (state == kImmersiveUnknown) { 49 if (IsProcessImmersive(::GetCurrentProcess())) { 50 state = kImmersiveTrue; 51 } else { 52 state = kImmersiveFalse; 53 } 54 } 55 DCHECK_NE(kImmersiveUnknown, state); 56 return state == kImmersiveTrue; 57} 58 59bool IsProcessImmersive(HANDLE process) { 60 typedef BOOL (WINAPI* IsImmersiveProcessFunc)(HANDLE process); 61 HMODULE user32 = ::GetModuleHandleA("user32.dll"); 62 DCHECK(user32 != NULL); 63 64 IsImmersiveProcessFunc is_immersive_process = 65 reinterpret_cast<IsImmersiveProcessFunc>( 66 ::GetProcAddress(user32, "IsImmersiveProcess")); 67 68 if (is_immersive_process) 69 return is_immersive_process(process) ? true: false; 70 return false; 71} 72 73bool IsTSFAwareRequired() { 74 // Although this function is equal to IsMetroProcess at this moment, 75 // Chrome for Win7 and Vista may support TSF in the future. 76 return g_should_tsf_aware_required || IsMetroProcess(); 77} 78 79void SetForceToUseTSF() { 80 g_should_tsf_aware_required = true; 81 82 // Since Windows 8 Metro mode disables CUAS (Cicero Unaware Application 83 // Support) via ImmDisableLegacyIME API, Chrome must be fully TSF-aware on 84 // Metro mode. For debugging purposes, explicitly call ImmDisableLegacyIME so 85 // that one can test TSF functionality even on Windows 8 desktop mode. Note 86 // that CUAS cannot be disabled on Windows Vista/7 where ImmDisableLegacyIME 87 // is not available. 88 typedef BOOL (* ImmDisableLegacyIMEFunc)(); 89 HMODULE imm32 = ::GetModuleHandleA("imm32.dll"); 90 if (imm32 == NULL) 91 return; 92 93 ImmDisableLegacyIMEFunc imm_disable_legacy_ime = 94 reinterpret_cast<ImmDisableLegacyIMEFunc>( 95 ::GetProcAddress(imm32, "ImmDisableLegacyIME")); 96 97 if (imm_disable_legacy_ime == NULL) { 98 // Unsupported API, just do nothing. 99 return; 100 } 101 102 if (!imm_disable_legacy_ime()) { 103 DVLOG(1) << "Failed to disable legacy IME."; 104 } 105} 106 107wchar_t* LocalAllocAndCopyString(const string16& src) { 108 size_t dest_size = (src.length() + 1) * sizeof(wchar_t); 109 wchar_t* dest = reinterpret_cast<wchar_t*>(LocalAlloc(LPTR, dest_size)); 110 base::wcslcpy(dest, src.c_str(), dest_size); 111 return dest; 112} 113 114bool IsParentalControlActivityLoggingOn() { 115 // Query this info on Windows Vista and above. 116 if (base::win::GetVersion() < base::win::VERSION_VISTA) 117 return false; 118 119 static bool parental_control_logging_required = false; 120 static bool parental_control_status_determined = false; 121 122 if (parental_control_status_determined) 123 return parental_control_logging_required; 124 125 parental_control_status_determined = true; 126 127 ScopedComPtr<IWindowsParentalControlsCore> parent_controls; 128 HRESULT hr = parent_controls.CreateInstance( 129 __uuidof(WindowsParentalControls)); 130 if (FAILED(hr)) 131 return false; 132 133 ScopedComPtr<IWPCSettings> settings; 134 hr = parent_controls->GetUserSettings(NULL, settings.Receive()); 135 if (FAILED(hr)) 136 return false; 137 138 unsigned long restrictions = 0; 139 settings->GetRestrictions(&restrictions); 140 141 parental_control_logging_required = 142 (restrictions & WPCFLAG_LOGGING_REQUIRED) == WPCFLAG_LOGGING_REQUIRED; 143 return parental_control_logging_required; 144} 145 146// Metro driver exports for getting the launch type, initial url, initial 147// search term, etc. 148extern "C" { 149typedef const wchar_t* (*GetInitialUrl)(); 150typedef const wchar_t* (*GetInitialSearchString)(); 151typedef base::win::MetroLaunchType (*GetLaunchType)( 152 base::win::MetroPreviousExecutionState* previous_state); 153} 154 155MetroLaunchType GetMetroLaunchParams(string16* params) { 156 HMODULE metro = base::win::GetMetroModule(); 157 if (!metro) 158 return base::win::METRO_LAUNCH_ERROR; 159 160 GetLaunchType get_launch_type = reinterpret_cast<GetLaunchType>( 161 ::GetProcAddress(metro, "GetLaunchType")); 162 DCHECK(get_launch_type); 163 164 base::win::MetroLaunchType launch_type = get_launch_type(NULL); 165 166 if ((launch_type == base::win::METRO_PROTOCOL) || 167 (launch_type == base::win::METRO_LAUNCH)) { 168 GetInitialUrl initial_metro_url = reinterpret_cast<GetInitialUrl>( 169 ::GetProcAddress(metro, "GetInitialUrl")); 170 DCHECK(initial_metro_url); 171 *params = initial_metro_url(); 172 } else if (launch_type == base::win::METRO_SEARCH) { 173 GetInitialSearchString initial_search_string = 174 reinterpret_cast<GetInitialSearchString>( 175 ::GetProcAddress(metro, "GetInitialSearchString")); 176 DCHECK(initial_search_string); 177 *params = initial_search_string(); 178 } 179 return launch_type; 180} 181 182} // namespace win 183} // namespace base 184