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.
5 #include "base/win/metro.h"
7 #include "base/message_loop.h"
8 #include "base/string_util.h"
9 #include "base/win/scoped_comptr.h"
10 #include "base/win/windows_version.h"
15 const char kActivateApplication
[] = "ActivateApplication";
17 HMODULE
GetMetroModule() {
18 const HMODULE kUninitialized
= reinterpret_cast<HMODULE
>(1);
19 static HMODULE metro_module
= kUninitialized
;
21 if (metro_module
== kUninitialized
) {
22 // Initialize the cache, note that the initialization is idempotent
23 // under the assumption that metro_driver is never unloaded, so the
24 // race to this assignment is safe.
25 metro_module
= GetModuleHandleA("metro_driver.dll");
26 if (metro_module
!= NULL
) {
27 // This must be a metro process if the metro_driver is loaded.
28 DCHECK(IsMetroProcess());
32 DCHECK(metro_module
!= kUninitialized
);
36 bool IsMetroProcess() {
42 typedef BOOL (WINAPI
* IsImmersiveProcessFunc
)(HANDLE process
);
44 // The immersive state of a process can never change.
45 // Look it up once and cache it here.
46 static ImmersiveState state
= kImmersiveUnknown
;
48 if (state
== kImmersiveUnknown
) {
49 // The lookup hasn't been done yet. Note that the code below here is
50 // idempotent, so it doesn't matter if it races to assignment on multiple
52 HMODULE user32
= ::GetModuleHandleA("user32.dll");
53 DCHECK(user32
!= NULL
);
55 IsImmersiveProcessFunc is_immersive_process
=
56 reinterpret_cast<IsImmersiveProcessFunc
>(
57 ::GetProcAddress(user32
, "IsImmersiveProcess"));
59 if (is_immersive_process
!= NULL
) {
60 if (is_immersive_process(::GetCurrentProcess())) {
61 state
= kImmersiveTrue
;
63 state
= kImmersiveFalse
;
66 // No "IsImmersiveProcess" export on user32.dll, so this is pre-Windows8
67 // and therefore not immersive.
68 state
= kImmersiveFalse
;
71 DCHECK_NE(kImmersiveUnknown
, state
);
73 return state
== kImmersiveTrue
;
76 bool IsTsfAwareRequired() {
77 // Although this function is equal to IsMetroProcess at this moment,
78 // Chrome for Win7 and Vista may support TSF in the future.
79 return IsMetroProcess();
82 wchar_t* LocalAllocAndCopyString(const string16
& src
) {
83 size_t dest_size
= (src
.length() + 1) * sizeof(wchar_t);
84 wchar_t* dest
= reinterpret_cast<wchar_t*>(LocalAlloc(LPTR
, dest_size
));
85 base::wcslcpy(dest
, src
.c_str(), dest_size
);
89 bool IsTouchEnabled() {
90 int value
= GetSystemMetrics(SM_DIGITIZER
);
91 return value
& (NID_READY
| NID_INTEGRATED_TOUCH
) ==
92 (NID_READY
| NID_INTEGRATED_TOUCH
);
95 bool IsParentalControlActivityLoggingOn() {
96 // Query this info on Windows Vista and above.
97 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
100 static bool parental_control_logging_required
= false;
101 static bool parental_control_status_determined
= false;
103 if (parental_control_status_determined
)
104 return parental_control_logging_required
;
106 parental_control_status_determined
= true;
108 ScopedComPtr
<IWindowsParentalControlsCore
> parent_controls
;
109 HRESULT hr
= parent_controls
.CreateInstance(
110 __uuidof(WindowsParentalControls
));
114 ScopedComPtr
<IWPCSettings
> settings
;
115 hr
= parent_controls
->GetUserSettings(NULL
, settings
.Receive());
119 unsigned long restrictions
= 0;
120 settings
->GetRestrictions(&restrictions
);
122 parental_control_logging_required
=
123 (restrictions
& WPCFLAG_LOGGING_REQUIRED
) == WPCFLAG_LOGGING_REQUIRED
;
124 return parental_control_logging_required
;
127 // Metro driver exports for getting the launch type, initial url, initial
130 typedef const wchar_t* (*GetInitialUrl
)();
131 typedef const wchar_t* (*GetInitialSearchString
)();
132 typedef base::win::MetroLaunchType (*GetLaunchType
)(
133 base::win::MetroPreviousExecutionState
* previous_state
);
136 MetroLaunchType
GetMetroLaunchParams(string16
* params
) {
137 HMODULE metro
= base::win::GetMetroModule();
139 return base::win::METRO_LAUNCH_ERROR
;
141 GetLaunchType get_launch_type
= reinterpret_cast<GetLaunchType
>(
142 ::GetProcAddress(metro
, "GetLaunchType"));
143 DCHECK(get_launch_type
);
145 base::win::MetroLaunchType launch_type
= get_launch_type(NULL
);
147 if ((launch_type
== base::win::METRO_PROTOCOL
) ||
148 (launch_type
== base::win::METRO_LAUNCH
)) {
149 GetInitialUrl initial_metro_url
= reinterpret_cast<GetInitialUrl
>(
150 ::GetProcAddress(metro
, "GetInitialUrl"));
151 DCHECK(initial_metro_url
);
152 *params
= initial_metro_url();
153 } else if (launch_type
== base::win::METRO_SEARCH
) {
154 GetInitialSearchString initial_search_string
=
155 reinterpret_cast<GetInitialSearchString
>(
156 ::GetProcAddress(metro
, "GetInitialSearchString"));
157 DCHECK(initial_search_string
);
158 *params
= initial_search_string();