Thu, 15 Jan 2015 15:59:08 +0100
Implement a real Private Browsing Mode condition by changing the API/ABI;
This solves Tor bug #9701, complying with disk avoidance documented in
https://www.torproject.org/projects/torbrowser/design/#disk-avoidance.
michael@0 | 1 | /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
michael@0 | 2 | /* This Source Code Form is subject to the terms of the Mozilla Public |
michael@0 | 3 | * License, v. 2.0. If a copy of the MPL was not distributed with this |
michael@0 | 4 | * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
michael@0 | 5 | |
michael@0 | 6 | #include "nsWinMetroUtils.h" |
michael@0 | 7 | #include "MetroUtils.h" |
michael@0 | 8 | #include "nsXULAppAPI.h" |
michael@0 | 9 | #include "FrameworkView.h" |
michael@0 | 10 | #include "MetroApp.h" |
michael@0 | 11 | #include "ToastNotificationHandler.h" |
michael@0 | 12 | #include "mozilla/Preferences.h" |
michael@0 | 13 | #include "mozilla/WindowsVersion.h" |
michael@0 | 14 | #include "nsIWindowsRegKey.h" |
michael@0 | 15 | #include "mozilla/widget/MetroD3DCheckHelper.h" |
michael@0 | 16 | |
michael@0 | 17 | #include <shldisp.h> |
michael@0 | 18 | #include <shellapi.h> |
michael@0 | 19 | #include <windows.ui.viewmanagement.h> |
michael@0 | 20 | #include <windows.ui.startscreen.h> |
michael@0 | 21 | |
michael@0 | 22 | using namespace ABI::Windows::Foundation; |
michael@0 | 23 | using namespace ABI::Windows::UI::StartScreen; |
michael@0 | 24 | using namespace ABI::Windows::UI::ViewManagement; |
michael@0 | 25 | using namespace Microsoft::WRL; |
michael@0 | 26 | using namespace Microsoft::WRL::Wrappers; |
michael@0 | 27 | using namespace mozilla::widget::winrt; |
michael@0 | 28 | |
michael@0 | 29 | namespace mozilla { |
michael@0 | 30 | namespace widget { |
michael@0 | 31 | namespace winrt { |
michael@0 | 32 | extern ComPtr<MetroApp> sMetroApp; |
michael@0 | 33 | extern nsTArray<nsString>* sSettingsArray; |
michael@0 | 34 | } } } |
michael@0 | 35 | |
michael@0 | 36 | namespace mozilla { |
michael@0 | 37 | namespace widget { |
michael@0 | 38 | |
michael@0 | 39 | bool nsWinMetroUtils::sUpdatePending = false; |
michael@0 | 40 | |
michael@0 | 41 | NS_IMPL_ISUPPORTS(nsWinMetroUtils, nsIWinMetroUtils) |
michael@0 | 42 | |
michael@0 | 43 | nsWinMetroUtils::nsWinMetroUtils() |
michael@0 | 44 | { |
michael@0 | 45 | } |
michael@0 | 46 | |
michael@0 | 47 | nsWinMetroUtils::~nsWinMetroUtils() |
michael@0 | 48 | { |
michael@0 | 49 | } |
michael@0 | 50 | |
michael@0 | 51 | /** |
michael@0 | 52 | * Pins a new tile to the Windows 8 start screen. |
michael@0 | 53 | * |
michael@0 | 54 | * @param aTileID An ID which can later be used to remove the tile |
michael@0 | 55 | * @param aShortName A short name for the tile |
michael@0 | 56 | * @param aDiplayName The name that will be displayed on the tile |
michael@0 | 57 | * @param aActivationArgs The arguments to pass to the browser upon |
michael@0 | 58 | * activation of the tile |
michael@0 | 59 | * @param aTileImage An image for the normal tile view |
michael@0 | 60 | * @param aSmallTileImage An image for the small tile view |
michael@0 | 61 | */ |
michael@0 | 62 | NS_IMETHODIMP |
michael@0 | 63 | nsWinMetroUtils::PinTileAsync(const nsAString &aTileID, |
michael@0 | 64 | const nsAString &aShortName, |
michael@0 | 65 | const nsAString &aDisplayName, |
michael@0 | 66 | const nsAString &aActivationArgs, |
michael@0 | 67 | const nsAString &aTileImage, |
michael@0 | 68 | const nsAString &aSmallTileImage) |
michael@0 | 69 | { |
michael@0 | 70 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 71 | NS_WARNING("PinTileAsync can't be called on the desktop."); |
michael@0 | 72 | return NS_ERROR_FAILURE; |
michael@0 | 73 | } |
michael@0 | 74 | HRESULT hr; |
michael@0 | 75 | |
michael@0 | 76 | HString logoStr, smallLogoStr, displayName, shortName; |
michael@0 | 77 | |
michael@0 | 78 | logoStr.Set(aTileImage.BeginReading()); |
michael@0 | 79 | smallLogoStr.Set(aSmallTileImage.BeginReading()); |
michael@0 | 80 | displayName.Set(aDisplayName.BeginReading()); |
michael@0 | 81 | shortName.Set(aShortName.BeginReading()); |
michael@0 | 82 | |
michael@0 | 83 | ComPtr<IUriRuntimeClass> logo, smallLogo; |
michael@0 | 84 | AssertRetHRESULT(MetroUtils::CreateUri(logoStr, logo), NS_ERROR_FAILURE); |
michael@0 | 85 | AssertRetHRESULT(MetroUtils::CreateUri(smallLogoStr, smallLogo), NS_ERROR_FAILURE); |
michael@0 | 86 | |
michael@0 | 87 | HString tileActivationArgumentsStr, tileIdStr; |
michael@0 | 88 | tileActivationArgumentsStr.Set(aActivationArgs.BeginReading()); |
michael@0 | 89 | tileIdStr.Set(aTileID.BeginReading()); |
michael@0 | 90 | |
michael@0 | 91 | ComPtr<ISecondaryTileFactory> tileFactory; |
michael@0 | 92 | ComPtr<ISecondaryTile> secondaryTile; |
michael@0 | 93 | hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(), |
michael@0 | 94 | tileFactory.GetAddressOf()); |
michael@0 | 95 | AssertRetHRESULT(hr, NS_ERROR_FAILURE); |
michael@0 | 96 | hr = tileFactory->CreateWithId(tileIdStr.Get(), secondaryTile.GetAddressOf()); |
michael@0 | 97 | AssertRetHRESULT(hr, NS_ERROR_FAILURE); |
michael@0 | 98 | |
michael@0 | 99 | secondaryTile->put_Logo(logo.Get()); |
michael@0 | 100 | secondaryTile->put_SmallLogo(smallLogo.Get()); |
michael@0 | 101 | secondaryTile->put_DisplayName(displayName.Get()); |
michael@0 | 102 | secondaryTile->put_ShortName(shortName.Get()); |
michael@0 | 103 | secondaryTile->put_Arguments(tileActivationArgumentsStr.Get()); |
michael@0 | 104 | secondaryTile->put_TileOptions(TileOptions::TileOptions_ShowNameOnLogo); |
michael@0 | 105 | |
michael@0 | 106 | // The tile is created and we can now attempt to pin the tile. |
michael@0 | 107 | ComPtr<IAsyncOperationCompletedHandler<bool>> callback(Callback<IAsyncOperationCompletedHandler<bool>>( |
michael@0 | 108 | sMetroApp.Get(), &MetroApp::OnAsyncTileCreated)); |
michael@0 | 109 | ComPtr<IAsyncOperation<bool>> operation; |
michael@0 | 110 | AssertRetHRESULT(secondaryTile->RequestCreateAsync(operation.GetAddressOf()), NS_ERROR_FAILURE); |
michael@0 | 111 | operation->put_Completed(callback.Get()); |
michael@0 | 112 | return NS_OK; |
michael@0 | 113 | } |
michael@0 | 114 | |
michael@0 | 115 | /** |
michael@0 | 116 | * Unpins a tile from the Windows 8 start screen. |
michael@0 | 117 | * |
michael@0 | 118 | * @param aTileID An existing ID which was previously pinned |
michael@0 | 119 | */ |
michael@0 | 120 | NS_IMETHODIMP |
michael@0 | 121 | nsWinMetroUtils::UnpinTileAsync(const nsAString &aTileID) |
michael@0 | 122 | { |
michael@0 | 123 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 124 | NS_WARNING("UnpinTileAsync can't be called on the desktop."); |
michael@0 | 125 | return NS_ERROR_FAILURE; |
michael@0 | 126 | } |
michael@0 | 127 | HRESULT hr; |
michael@0 | 128 | HString tileIdStr; |
michael@0 | 129 | tileIdStr.Set(aTileID.BeginReading()); |
michael@0 | 130 | |
michael@0 | 131 | ComPtr<ISecondaryTileFactory> tileFactory; |
michael@0 | 132 | ComPtr<ISecondaryTile> secondaryTile; |
michael@0 | 133 | hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(), |
michael@0 | 134 | tileFactory.GetAddressOf()); |
michael@0 | 135 | AssertRetHRESULT(hr, NS_ERROR_FAILURE); |
michael@0 | 136 | hr = tileFactory->CreateWithId(tileIdStr.Get(), secondaryTile.GetAddressOf()); |
michael@0 | 137 | AssertRetHRESULT(hr, NS_ERROR_FAILURE); |
michael@0 | 138 | |
michael@0 | 139 | // Attempt to unpin the tile |
michael@0 | 140 | ComPtr<IAsyncOperationCompletedHandler<bool>> callback(Callback<IAsyncOperationCompletedHandler<bool>>( |
michael@0 | 141 | sMetroApp.Get(), &MetroApp::OnAsyncTileCreated)); |
michael@0 | 142 | ComPtr<IAsyncOperation<bool>> operation; |
michael@0 | 143 | AssertRetHRESULT(secondaryTile->RequestDeleteAsync(operation.GetAddressOf()), NS_ERROR_FAILURE); |
michael@0 | 144 | operation->put_Completed(callback.Get()); |
michael@0 | 145 | return NS_OK; |
michael@0 | 146 | } |
michael@0 | 147 | |
michael@0 | 148 | /** |
michael@0 | 149 | * Determines if a tile is pinned to the Windows 8 start screen. |
michael@0 | 150 | * |
michael@0 | 151 | * @param aTileID An ID which may have been pinned with pinTileAsync |
michael@0 | 152 | * @param aIsPinned Out parameter for determining if the tile is pinned or not |
michael@0 | 153 | */ |
michael@0 | 154 | NS_IMETHODIMP |
michael@0 | 155 | nsWinMetroUtils::IsTilePinned(const nsAString &aTileID, bool *aIsPinned) |
michael@0 | 156 | { |
michael@0 | 157 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 158 | NS_WARNING("IsTilePinned can't be called on the desktop."); |
michael@0 | 159 | return NS_ERROR_FAILURE; |
michael@0 | 160 | } |
michael@0 | 161 | NS_ENSURE_ARG_POINTER(aIsPinned); |
michael@0 | 162 | |
michael@0 | 163 | HRESULT hr; |
michael@0 | 164 | HString tileIdStr; |
michael@0 | 165 | tileIdStr.Set(aTileID.BeginReading()); |
michael@0 | 166 | |
michael@0 | 167 | ComPtr<ISecondaryTileStatics> tileStatics; |
michael@0 | 168 | hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_UI_StartScreen_SecondaryTile).Get(), |
michael@0 | 169 | tileStatics.GetAddressOf()); |
michael@0 | 170 | AssertRetHRESULT(hr, NS_ERROR_FAILURE); |
michael@0 | 171 | boolean result = false; |
michael@0 | 172 | tileStatics->Exists(tileIdStr.Get(), &result); |
michael@0 | 173 | *aIsPinned = result; |
michael@0 | 174 | return NS_OK; |
michael@0 | 175 | } |
michael@0 | 176 | |
michael@0 | 177 | /** |
michael@0 | 178 | * Launches the specified application with the specified arguments and |
michael@0 | 179 | * switches to Desktop mode if in metro mode. |
michael@0 | 180 | */ |
michael@0 | 181 | NS_IMETHODIMP |
michael@0 | 182 | nsWinMetroUtils::LaunchInDesktop(const nsAString &aPath, const nsAString &aArguments) |
michael@0 | 183 | { |
michael@0 | 184 | SHELLEXECUTEINFOW sinfo; |
michael@0 | 185 | memset(&sinfo, 0, sizeof(SHELLEXECUTEINFOW)); |
michael@0 | 186 | sinfo.cbSize = sizeof(SHELLEXECUTEINFOW); |
michael@0 | 187 | // Per the Metro style enabled desktop browser, for some reason, |
michael@0 | 188 | // SEE_MASK_FLAG_LOG_USAGE is needed to change from immersive mode |
michael@0 | 189 | // to desktop. |
michael@0 | 190 | sinfo.fMask = SEE_MASK_FLAG_LOG_USAGE; |
michael@0 | 191 | sinfo.hwnd = nullptr; |
michael@0 | 192 | sinfo.lpFile = aPath.BeginReading(); |
michael@0 | 193 | sinfo.lpParameters = aArguments.BeginReading(); |
michael@0 | 194 | sinfo.lpVerb = L"open"; |
michael@0 | 195 | sinfo.nShow = SW_SHOWNORMAL; |
michael@0 | 196 | |
michael@0 | 197 | if (!ShellExecuteEx(&sinfo)) { |
michael@0 | 198 | return NS_ERROR_FAILURE; |
michael@0 | 199 | } |
michael@0 | 200 | return NS_OK; |
michael@0 | 201 | } |
michael@0 | 202 | |
michael@0 | 203 | NS_IMETHODIMP |
michael@0 | 204 | nsWinMetroUtils::ShowNativeToast(const nsAString &aTitle, |
michael@0 | 205 | const nsAString &aMessage, const nsAString &anImage, |
michael@0 | 206 | const nsAString &aCookie, const nsAString& aAppId) |
michael@0 | 207 | { |
michael@0 | 208 | ToastNotificationHandler* notification_handler = |
michael@0 | 209 | new ToastNotificationHandler; |
michael@0 | 210 | |
michael@0 | 211 | HSTRING title = HStringReference(aTitle.BeginReading()).Get(); |
michael@0 | 212 | HSTRING msg = HStringReference(aMessage.BeginReading()).Get(); |
michael@0 | 213 | |
michael@0 | 214 | bool ret; |
michael@0 | 215 | if (anImage.Length() > 0) { |
michael@0 | 216 | HSTRING imagePath = HStringReference(anImage.BeginReading()).Get(); |
michael@0 | 217 | ret = notification_handler->DisplayNotification(title, msg, imagePath, |
michael@0 | 218 | aCookie, |
michael@0 | 219 | aAppId); |
michael@0 | 220 | } else { |
michael@0 | 221 | ret = notification_handler->DisplayTextNotification(title, msg, aCookie, |
michael@0 | 222 | aAppId); |
michael@0 | 223 | } |
michael@0 | 224 | |
michael@0 | 225 | if (!ret) { |
michael@0 | 226 | delete notification_handler; |
michael@0 | 227 | return NS_ERROR_FAILURE; |
michael@0 | 228 | } |
michael@0 | 229 | |
michael@0 | 230 | return NS_OK; |
michael@0 | 231 | } |
michael@0 | 232 | |
michael@0 | 233 | NS_IMETHODIMP |
michael@0 | 234 | nsWinMetroUtils::ShowSettingsFlyout() |
michael@0 | 235 | { |
michael@0 | 236 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 237 | NS_WARNING("Settings flyout can't be shown on the desktop."); |
michael@0 | 238 | return NS_ERROR_FAILURE; |
michael@0 | 239 | } |
michael@0 | 240 | |
michael@0 | 241 | HRESULT hr = MetroUtils::ShowSettingsFlyout(); |
michael@0 | 242 | return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE; |
michael@0 | 243 | } |
michael@0 | 244 | |
michael@0 | 245 | NS_IMETHODIMP |
michael@0 | 246 | nsWinMetroUtils::GetImmersive(bool *aImersive) |
michael@0 | 247 | { |
michael@0 | 248 | *aImersive = |
michael@0 | 249 | XRE_GetWindowsEnvironment() == WindowsEnvironmentType_Metro; |
michael@0 | 250 | return NS_OK; |
michael@0 | 251 | } |
michael@0 | 252 | |
michael@0 | 253 | NS_IMETHODIMP |
michael@0 | 254 | nsWinMetroUtils::GetActivationURI(nsAString &aActivationURI) |
michael@0 | 255 | { |
michael@0 | 256 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 257 | return NS_ERROR_FAILURE; |
michael@0 | 258 | } |
michael@0 | 259 | FrameworkView::GetActivationURI(aActivationURI); |
michael@0 | 260 | return NS_OK; |
michael@0 | 261 | } |
michael@0 | 262 | |
michael@0 | 263 | NS_IMETHODIMP |
michael@0 | 264 | nsWinMetroUtils::GetPreviousExecutionState(int32_t *out) |
michael@0 | 265 | { |
michael@0 | 266 | if (XRE_GetWindowsEnvironment() != WindowsEnvironmentType_Metro) { |
michael@0 | 267 | return NS_ERROR_FAILURE; |
michael@0 | 268 | } |
michael@0 | 269 | *out = FrameworkView::GetPreviousExecutionState(); |
michael@0 | 270 | return NS_OK; |
michael@0 | 271 | } |
michael@0 | 272 | |
michael@0 | 273 | NS_IMETHODIMP |
michael@0 | 274 | nsWinMetroUtils::GetKeyboardVisible(bool *aImersive) |
michael@0 | 275 | { |
michael@0 | 276 | *aImersive = FrameworkView::IsKeyboardVisible(); |
michael@0 | 277 | return NS_OK; |
michael@0 | 278 | } |
michael@0 | 279 | |
michael@0 | 280 | NS_IMETHODIMP |
michael@0 | 281 | nsWinMetroUtils::GetKeyboardX(uint32_t *aX) |
michael@0 | 282 | { |
michael@0 | 283 | *aX = static_cast<uint32_t>(floor(FrameworkView::KeyboardVisibleRect().X)); |
michael@0 | 284 | return NS_OK; |
michael@0 | 285 | } |
michael@0 | 286 | |
michael@0 | 287 | NS_IMETHODIMP |
michael@0 | 288 | nsWinMetroUtils::GetKeyboardY(uint32_t *aY) |
michael@0 | 289 | { |
michael@0 | 290 | *aY = static_cast<uint32_t>(floor(FrameworkView::KeyboardVisibleRect().Y)); |
michael@0 | 291 | return NS_OK; |
michael@0 | 292 | } |
michael@0 | 293 | |
michael@0 | 294 | NS_IMETHODIMP |
michael@0 | 295 | nsWinMetroUtils::GetKeyboardWidth(uint32_t *aWidth) |
michael@0 | 296 | { |
michael@0 | 297 | *aWidth = static_cast<uint32_t>(ceil(FrameworkView::KeyboardVisibleRect().Width)); |
michael@0 | 298 | return NS_OK; |
michael@0 | 299 | } |
michael@0 | 300 | |
michael@0 | 301 | NS_IMETHODIMP |
michael@0 | 302 | nsWinMetroUtils::GetKeyboardHeight(uint32_t *aHeight) |
michael@0 | 303 | { |
michael@0 | 304 | *aHeight = static_cast<uint32_t>(ceil(FrameworkView::KeyboardVisibleRect().Height)); |
michael@0 | 305 | return NS_OK; |
michael@0 | 306 | } |
michael@0 | 307 | |
michael@0 | 308 | NS_IMETHODIMP |
michael@0 | 309 | nsWinMetroUtils::AddSettingsPanelEntry(const nsAString &aLabel, uint32_t *aId) |
michael@0 | 310 | { |
michael@0 | 311 | NS_ENSURE_ARG_POINTER(aId); |
michael@0 | 312 | if (!sSettingsArray) |
michael@0 | 313 | return NS_ERROR_UNEXPECTED; |
michael@0 | 314 | |
michael@0 | 315 | *aId = sSettingsArray->Length(); |
michael@0 | 316 | sSettingsArray->AppendElement(nsString(aLabel)); |
michael@0 | 317 | return NS_OK; |
michael@0 | 318 | } |
michael@0 | 319 | |
michael@0 | 320 | NS_IMETHODIMP |
michael@0 | 321 | nsWinMetroUtils::SwapMouseButton(bool aValue, bool *aOriginalValue) |
michael@0 | 322 | { |
michael@0 | 323 | *aOriginalValue = ::SwapMouseButton(aValue); |
michael@0 | 324 | return NS_OK; |
michael@0 | 325 | } |
michael@0 | 326 | |
michael@0 | 327 | NS_IMETHODIMP |
michael@0 | 328 | nsWinMetroUtils::GetUpdatePending(bool *aUpdatePending) |
michael@0 | 329 | { |
michael@0 | 330 | *aUpdatePending = sUpdatePending; |
michael@0 | 331 | return NS_OK; |
michael@0 | 332 | } |
michael@0 | 333 | |
michael@0 | 334 | NS_IMETHODIMP |
michael@0 | 335 | nsWinMetroUtils::SetUpdatePending(bool aUpdatePending) |
michael@0 | 336 | { |
michael@0 | 337 | sUpdatePending = aUpdatePending; |
michael@0 | 338 | return NS_OK; |
michael@0 | 339 | } |
michael@0 | 340 | |
michael@0 | 341 | NS_IMETHODIMP |
michael@0 | 342 | nsWinMetroUtils::GetForeground(bool* aForeground) |
michael@0 | 343 | { |
michael@0 | 344 | *aForeground = (::GetActiveWindow() == ::GetForegroundWindow()); |
michael@0 | 345 | return NS_OK; |
michael@0 | 346 | } |
michael@0 | 347 | |
michael@0 | 348 | NS_IMETHODIMP |
michael@0 | 349 | nsWinMetroUtils::GetSupported(bool *aSupported) |
michael@0 | 350 | { |
michael@0 | 351 | *aSupported = false; |
michael@0 | 352 | if (!IsWin8OrLater()) { |
michael@0 | 353 | return NS_OK; |
michael@0 | 354 | } |
michael@0 | 355 | |
michael@0 | 356 | // if last_used_feature_level_idx is set, we've previously created a |
michael@0 | 357 | // d3d device that's compatible. See gfxEindowsPlatform for details. |
michael@0 | 358 | if (Preferences::GetInt("gfx.direct3d.last_used_feature_level_idx", -1) != -1) { |
michael@0 | 359 | *aSupported = true; |
michael@0 | 360 | return NS_OK; |
michael@0 | 361 | } |
michael@0 | 362 | |
michael@0 | 363 | // if last_used_feature_level_idx isn't set, gfx hasn't attempted to create |
michael@0 | 364 | // a device yet. This could be a case where d2d is pref'd off or blacklisted |
michael@0 | 365 | // on desktop, or we tried to create a device and failed. This could also be |
michael@0 | 366 | // a first run case where we haven't created an accelerated top level window |
michael@0 | 367 | // yet. |
michael@0 | 368 | |
michael@0 | 369 | NS_NAMED_LITERAL_STRING(metroRegValueName, "MetroD3DAvailable"); |
michael@0 | 370 | NS_NAMED_LITERAL_STRING(metroRegValuePath, "Software\\Mozilla\\Firefox"); |
michael@0 | 371 | |
michael@0 | 372 | // Check to see if the ceh launched us, it also does this check and caches |
michael@0 | 373 | // a flag in the registry. |
michael@0 | 374 | nsresult rv; |
michael@0 | 375 | uint32_t value = 0; |
michael@0 | 376 | nsCOMPtr<nsIWindowsRegKey> regKey = |
michael@0 | 377 | do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv); |
michael@0 | 378 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 379 | rv = regKey->Open(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER, |
michael@0 | 380 | metroRegValuePath, |
michael@0 | 381 | nsIWindowsRegKey::ACCESS_ALL); |
michael@0 | 382 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 383 | rv = regKey->ReadIntValue(metroRegValueName, &value); |
michael@0 | 384 | if (NS_SUCCEEDED(rv)) { |
michael@0 | 385 | *aSupported = (bool)value; |
michael@0 | 386 | return NS_OK; |
michael@0 | 387 | } |
michael@0 | 388 | |
michael@0 | 389 | // If all else fails, do the check here. This call is costly but |
michael@0 | 390 | // we shouldn't hit this except in rare situations where the |
michael@0 | 391 | // ceh never launched the browser that's running. |
michael@0 | 392 | value = D3DFeatureLevelCheck(); |
michael@0 | 393 | regKey->WriteIntValue(metroRegValueName, value); |
michael@0 | 394 | *aSupported = (bool)value; |
michael@0 | 395 | return NS_OK; |
michael@0 | 396 | } |
michael@0 | 397 | } |
michael@0 | 398 | return NS_OK; |
michael@0 | 399 | } |
michael@0 | 400 | |
michael@0 | 401 | } // widget |
michael@0 | 402 | } // mozilla |