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 12 namespace base { 13 namespace win { 14 15 namespace { 16 bool g_should_tsf_aware_required = false; 17 } 18 19 HMODULE 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 38 bool 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 59 bool 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 73 bool IsTSFAwareRequired() { 74 #if defined(USE_AURA) 75 if (base::win::GetVersion() >= base::win::VERSION_WIN8) 76 return true; 77 #endif 78 // Although this function is equal to IsMetroProcess at this moment, 79 // Chrome for Win7 and Vista may support TSF in the future. 80 return g_should_tsf_aware_required || IsMetroProcess(); 81 } 82 83 void SetForceToUseTSF() { 84 g_should_tsf_aware_required = true; 85 86 // Since Windows 8 Metro mode disables CUAS (Cicero Unaware Application 87 // Support) via ImmDisableLegacyIME API, Chrome must be fully TSF-aware on 88 // Metro mode. For debugging purposes, explicitly call ImmDisableLegacyIME so 89 // that one can test TSF functionality even on Windows 8 desktop mode. Note 90 // that CUAS cannot be disabled on Windows Vista/7 where ImmDisableLegacyIME 91 // is not available. 92 typedef BOOL (* ImmDisableLegacyIMEFunc)(); 93 HMODULE imm32 = ::GetModuleHandleA("imm32.dll"); 94 if (imm32 == NULL) 95 return; 96 97 ImmDisableLegacyIMEFunc imm_disable_legacy_ime = 98 reinterpret_cast<ImmDisableLegacyIMEFunc>( 99 ::GetProcAddress(imm32, "ImmDisableLegacyIME")); 100 101 if (imm_disable_legacy_ime == NULL) { 102 // Unsupported API, just do nothing. 103 return; 104 } 105 106 if (!imm_disable_legacy_ime()) { 107 DVLOG(1) << "Failed to disable legacy IME."; 108 } 109 } 110 111 wchar_t* LocalAllocAndCopyString(const string16& src) { 112 size_t dest_size = (src.length() + 1) * sizeof(wchar_t); 113 wchar_t* dest = reinterpret_cast<wchar_t*>(LocalAlloc(LPTR, dest_size)); 114 base::wcslcpy(dest, src.c_str(), dest_size); 115 return dest; 116 } 117 118 bool IsParentalControlActivityLoggingOn() { 119 // Query this info on Windows Vista and above. 120 if (base::win::GetVersion() < base::win::VERSION_VISTA) 121 return false; 122 123 static bool parental_control_logging_required = false; 124 static bool parental_control_status_determined = false; 125 126 if (parental_control_status_determined) 127 return parental_control_logging_required; 128 129 parental_control_status_determined = true; 130 131 ScopedComPtr<IWindowsParentalControlsCore> parent_controls; 132 HRESULT hr = parent_controls.CreateInstance( 133 __uuidof(WindowsParentalControls)); 134 if (FAILED(hr)) 135 return false; 136 137 ScopedComPtr<IWPCSettings> settings; 138 hr = parent_controls->GetUserSettings(NULL, settings.Receive()); 139 if (FAILED(hr)) 140 return false; 141 142 unsigned long restrictions = 0; 143 settings->GetRestrictions(&restrictions); 144 145 parental_control_logging_required = 146 (restrictions & WPCFLAG_LOGGING_REQUIRED) == WPCFLAG_LOGGING_REQUIRED; 147 return parental_control_logging_required; 148 } 149 150 // Metro driver exports for getting the launch type, initial url, initial 151 // search term, etc. 152 extern "C" { 153 typedef const wchar_t* (*GetInitialUrl)(); 154 typedef const wchar_t* (*GetInitialSearchString)(); 155 typedef base::win::MetroLaunchType (*GetLaunchType)( 156 base::win::MetroPreviousExecutionState* previous_state); 157 } 158 159 MetroLaunchType GetMetroLaunchParams(string16* params) { 160 HMODULE metro = base::win::GetMetroModule(); 161 if (!metro) 162 return base::win::METRO_LAUNCH_ERROR; 163 164 GetLaunchType get_launch_type = reinterpret_cast<GetLaunchType>( 165 ::GetProcAddress(metro, "GetLaunchType")); 166 DCHECK(get_launch_type); 167 168 base::win::MetroLaunchType launch_type = get_launch_type(NULL); 169 170 if ((launch_type == base::win::METRO_PROTOCOL) || 171 (launch_type == base::win::METRO_LAUNCH)) { 172 GetInitialUrl initial_metro_url = reinterpret_cast<GetInitialUrl>( 173 ::GetProcAddress(metro, "GetInitialUrl")); 174 DCHECK(initial_metro_url); 175 *params = initial_metro_url(); 176 } else if (launch_type == base::win::METRO_SEARCH) { 177 GetInitialSearchString initial_search_string = 178 reinterpret_cast<GetInitialSearchString>( 179 ::GetProcAddress(metro, "GetInitialSearchString")); 180 DCHECK(initial_search_string); 181 *params = initial_search_string(); 182 } 183 return launch_type; 184 } 185 186 } // namespace win 187 } // namespace base 188