fune/browser/components/shell/nsWindowsShellService.cpp
Csoregi Natalia ecd94d6986 Backed out 79 changesets (bug 1524687, bug 1524688) for crashes on mozilla::dom::ScreenOrientation::ScreenOrientation(nsPIDOMWindowInner *,nsScreen *). CLOSED TREE
Backed out changeset 68a001a42406 (bug 1524687)
Backed out changeset 328de611bcd3 (bug 1524688)
Backed out changeset 68cffca6927a (bug 1524687)
Backed out changeset 81dc12cc9257 (bug 1524688)
Backed out changeset c7c49f64048f (bug 1524688)
Backed out changeset fb23a0271da0 (bug 1524688)
Backed out changeset 0c1d1248e59e (bug 1524688)
Backed out changeset 9e9ec7de4160 (bug 1524688)
Backed out changeset de0b9993bd5d (bug 1524688)
Backed out changeset 92877cf4fe33 (bug 1524688)
Backed out changeset b4938f2ff8fd (bug 1524688)
Backed out changeset 230d2feaf941 (bug 1524688)
Backed out changeset 6c63bc240972 (bug 1524688)
Backed out changeset 0ad5465eace1 (bug 1524688)
Backed out changeset 1e75ce91029b (bug 1524688)
Backed out changeset 34a978503b1d (bug 1524688)
Backed out changeset 183602e8a30b (bug 1524688)
Backed out changeset 12a9135dc005 (bug 1524688)
Backed out changeset 978ef5dac9db (bug 1524688)
Backed out changeset 28105bf7bf6a (bug 1524688)
Backed out changeset a9fb74beaf2b (bug 1524688)
Backed out changeset fe106b369a72 (bug 1524688)
Backed out changeset e657e77d4271 (bug 1524688)
Backed out changeset 09f626870ad0 (bug 1524688)
Backed out changeset fe9b6695212e (bug 1524688)
Backed out changeset 995ea188bc31 (bug 1524688)
Backed out changeset 01c4d3edb1b0 (bug 1524688)
Backed out changeset 1bb7dfbb9f48 (bug 1524688)
Backed out changeset 56c61e0a1f45 (bug 1524688)
Backed out changeset c819943ff466 (bug 1524688)
Backed out changeset a1dd5cec066e (bug 1524688)
Backed out changeset 517838ee0c3c (bug 1524688)
Backed out changeset f509a5759fdf (bug 1524688)
Backed out changeset 56f5c8f0d708 (bug 1524688)
Backed out changeset 5746311ef859 (bug 1524688)
Backed out changeset df02f7d25212 (bug 1524688)
Backed out changeset c9846136d105 (bug 1524688)
Backed out changeset 2bd48db9cd0f (bug 1524688)
Backed out changeset ff120b4eeb79 (bug 1524688)
Backed out changeset fe583e7aae8d (bug 1524688)
Backed out changeset 18f156d6355a (bug 1524688)
Backed out changeset f4eaebbe2e0f (bug 1524688)
Backed out changeset bf6b18e23f69 (bug 1524688)
Backed out changeset dd89eb7e9b0d (bug 1524688)
Backed out changeset 4cbbb367ba0b (bug 1524688)
Backed out changeset 4ed0cf6be580 (bug 1524688)
Backed out changeset d8efb5ed62b1 (bug 1524688)
Backed out changeset ea347d57d73a (bug 1524688)
Backed out changeset 911689ef9f33 (bug 1524688)
Backed out changeset 28670fdc418d (bug 1524688)
Backed out changeset 38e1e42a0fb0 (bug 1524688)
Backed out changeset 35a5f031dd1e (bug 1524688)
Backed out changeset b586d55d76d5 (bug 1524688)
Backed out changeset 6dcacead1746 (bug 1524688)
Backed out changeset 9895239d8ac6 (bug 1524688)
Backed out changeset 25f982fd53bd (bug 1524688)
Backed out changeset 4fb0f0a59fe2 (bug 1524688)
Backed out changeset fdc6c4ed241a (bug 1524688)
Backed out changeset 5ce5986068f0 (bug 1524688)
Backed out changeset ab64ed7388ae (bug 1524688)
Backed out changeset 56607c5a301a (bug 1524688)
Backed out changeset 6b3684e7d8f9 (bug 1524688)
Backed out changeset ee28258a5724 (bug 1524688)
Backed out changeset 9201a7ea3c54 (bug 1524688)
Backed out changeset d5dca413e2da (bug 1524688)
Backed out changeset 68eb174a337b (bug 1524688)
Backed out changeset 625f71135038 (bug 1524687)
Backed out changeset 46e13c453538 (bug 1524687)
Backed out changeset 614be688767f (bug 1524687)
Backed out changeset 9c24919ac5c2 (bug 1524687)
Backed out changeset b9862758b98c (bug 1524687)
Backed out changeset 92d9e927deec (bug 1524687)
Backed out changeset f4ee175bc5bd (bug 1524687)
Backed out changeset 191afe83da2e (bug 1524687)
Backed out changeset c58caf41bb94 (bug 1524687)
Backed out changeset df95a56dae04 (bug 1524687)
Backed out changeset 10c69df4444d (bug 1524687)
Backed out changeset 219b84a58f50 (bug 1524687)
Backed out changeset e96e61bd282f (bug 1524687)

--HG--
rename : browser/components/migration/360seProfileMigrator.jsm => browser/components/migration/360seProfileMigrator.js
rename : browser/components/migration/ChromeProfileMigrator.jsm => browser/components/migration/ChromeProfileMigrator.js
rename : browser/components/migration/EdgeProfileMigrator.jsm => browser/components/migration/EdgeProfileMigrator.js
rename : browser/components/migration/FirefoxProfileMigrator.jsm => browser/components/migration/FirefoxProfileMigrator.js
rename : browser/components/migration/IEProfileMigrator.jsm => browser/components/migration/IEProfileMigrator.js
rename : browser/components/migration/ProfileMigrator.jsm => browser/components/migration/ProfileMigrator.js
rename : browser/components/migration/SafariProfileMigrator.jsm => browser/components/migration/SafariProfileMigrator.js
rename : browser/components/newtab/AboutNewTabService.jsm => browser/components/newtab/aboutNewTabService.js
rename : browser/components/BrowserContentHandler.jsm => browser/components/nsBrowserContentHandler.js
rename : browser/components/BrowserGlue.jsm => browser/components/nsBrowserGlue.js
rename : browser/components/payments/PaymentUIService.jsm => browser/components/payments/paymentUIService.js
rename : browser/components/protocolhandler/WebProtocolHandlerRegistrar.jsm => browser/components/protocolhandler/WebProtocolHandlerRegistrar.js
rename : devtools/startup/AboutDebuggingNewRegistration.jsm => devtools/startup/aboutdebugging-new-registration.js
rename : devtools/startup/AboutDebuggingRegistration.jsm => devtools/startup/aboutdebugging-registration.js
rename : devtools/startup/aboutdevtools/AboutDevToolsRegistration.jsm => devtools/startup/aboutdevtools/aboutdevtools-registration.js
rename : devtools/startup/AboutDevToolsToolboxRegistration.jsm => devtools/startup/aboutdevtoolstoolbox-registration.js
rename : devtools/startup/DevToolsStartup.jsm => devtools/startup/devtools-startup.js
rename : dom/base/ProcessSelector.jsm => dom/base/ProcessSelector.js
rename : dom/base/SlowScriptDebug.jsm => dom/base/SlowScriptDebug.js
rename : dom/base/ContentAreaDropListener.jsm => dom/base/contentAreaDropListener.js
rename : dom/browser-element/BrowserElementParent.jsm => dom/browser-element/BrowserElementParent.js
rename : dom/console/ConsoleAPIStorage.jsm => dom/console/ConsoleAPIStorage.js
rename : dom/html/HTMLMenuBuilder.jsm => dom/html/htmlMenuBuilder.js
rename : dom/media/PeerConnection.jsm => dom/media/PeerConnection.js
rename : dom/notification/NotificationStorage.jsm => dom/notification/NotificationStorage.js
rename : dom/presentation/PresentationDataChannelSessionTransport.jsm => dom/presentation/PresentationDataChannelSessionTransport.js
rename : dom/presentation/PresentationNetworkHelper.jsm => dom/presentation/PresentationNetworkHelper.js
rename : dom/presentation/provider/AndroidCastDeviceProvider.jsm => dom/presentation/provider/AndroidCastDeviceProvider.js
rename : dom/presentation/provider/PresentationControlService.jsm => dom/presentation/provider/PresentationControlService.js
rename : dom/push/Push.jsm => dom/push/Push.js
rename : dom/push/PushComponents.jsm => dom/push/PushComponents.js
rename : dom/system/NetworkGeolocationProvider.jsm => dom/system/NetworkGeolocationProvider.js
rename : layout/tools/recording/RecordingCmdLine.jsm => layout/tools/recording/recording-cmdline.js
rename : netwerk/dns/mdns/libmdns/DNSServiceDiscovery.jsm => netwerk/dns/mdns/libmdns/nsDNSServiceDiscovery.js
rename : netwerk/protocol/http/UAOverridesBootstrapper.jsm => netwerk/protocol/http/UAOverridesBootstrapper.js
rename : netwerk/protocol/http/WellKnownOpportunisticUtils.jsm => netwerk/protocol/http/WellKnownOpportunisticUtils.js
rename : services/fxaccounts/FxAccountsPush.jsm => services/fxaccounts/FxAccountsPush.js
rename : services/settings/RemoteSettingsComponents.jsm => services/settings/RemoteSettingsComponents.js
rename : services/sync/Weave.jsm => services/sync/Weave.js
rename : toolkit/components/asyncshutdown/nsAsyncShutdown.jsm => toolkit/components/asyncshutdown/nsAsyncShutdown.js
rename : toolkit/components/backgroundhangmonitor/BHRTelemetryService.jsm => toolkit/components/backgroundhangmonitor/BHRTelemetryService.js
rename : toolkit/components/captivedetect/CaptiveDetect.jsm => toolkit/components/captivedetect/captivedetect.js
rename : toolkit/components/cleardata/ClearDataService.jsm => toolkit/components/cleardata/ClearDataService.js
rename : toolkit/components/contentprefs/ContentPrefService2.jsm => toolkit/components/contentprefs/ContentPrefService2.js
rename : toolkit/components/crashes/CrashService.jsm => toolkit/components/crashes/CrashService.js
rename : toolkit/components/crashmonitor/nsCrashMonitor.jsm => toolkit/components/crashmonitor/nsCrashMonitor.js
rename : toolkit/components/downloads/DownloadLegacy.jsm => toolkit/components/downloads/DownloadLegacy.js
rename : toolkit/components/gfx/SanityTest.jsm => toolkit/components/gfx/SanityTest.js
rename : toolkit/components/mozintl/mozIntl.jsm => toolkit/components/mozintl/mozIntl.js
rename : toolkit/components/mozprotocol/MozProtocolHandler.jsm => toolkit/components/mozprotocol/mozProtocolHandler.js
rename : toolkit/components/normandy/ShieldContentProcess.jsm => toolkit/components/normandy/shield-content-process.js
rename : toolkit/components/DefaultCLH.jsm => toolkit/components/nsDefaultCLH.js
rename : toolkit/components/passwordmgr/LoginInfo.jsm => toolkit/components/passwordmgr/nsLoginInfo.js
rename : toolkit/components/passwordmgr/LoginManager.jsm => toolkit/components/passwordmgr/nsLoginManager.js
rename : toolkit/components/passwordmgr/LoginManagerPrompter.jsm => toolkit/components/passwordmgr/nsLoginManagerPrompter.js
rename : toolkit/components/places/ColorAnalyzer.jsm => toolkit/components/places/ColorAnalyzer.js
rename : toolkit/components/places/PageIconProtocolHandler.jsm => toolkit/components/places/PageIconProtocolHandler.js
rename : toolkit/components/places/PlacesCategoriesStarter.jsm => toolkit/components/places/PlacesCategoriesStarter.js
rename : toolkit/components/places/UnifiedComplete.jsm => toolkit/components/places/UnifiedComplete.js
rename : toolkit/components/places/PlacesExpiration.jsm => toolkit/components/places/nsPlacesExpiration.js
rename : toolkit/components/places/TaggingService.jsm => toolkit/components/places/nsTaggingService.js
rename : toolkit/components/processsingleton/ContentProcessSingleton.jsm => toolkit/components/processsingleton/ContentProcessSingleton.js
rename : toolkit/components/processsingleton/MainProcessSingleton.jsm => toolkit/components/processsingleton/MainProcessSingleton.js
rename : toolkit/components/prompts/src/Prompter.jsm => toolkit/components/prompts/src/nsPrompter.js
rename : toolkit/components/remotebrowserutils/RemoteWebNavigation.jsm => toolkit/components/remotebrowserutils/RemoteWebNavigation.js
rename : toolkit/components/satchel/FormHistoryStartup.jsm => toolkit/components/satchel/FormHistoryStartup.js
rename : toolkit/components/satchel/FormAutoComplete.jsm => toolkit/components/satchel/nsFormAutoComplete.js
rename : toolkit/components/satchel/InputListAutoComplete.jsm => toolkit/components/satchel/nsInputListAutoComplete.js
rename : toolkit/components/search/SearchService.jsm => toolkit/components/search/nsSearchService.js
rename : toolkit/components/search/SearchSuggestions.jsm => toolkit/components/search/nsSearchSuggestions.js
rename : toolkit/components/search/Sidebar.jsm => toolkit/components/search/nsSidebar.js
rename : toolkit/components/telemetry/TelemetryStartup.jsm => toolkit/components/telemetry/TelemetryStartup.js
rename : toolkit/components/terminator/TerminatorTelemetry.jsm => toolkit/components/terminator/nsTerminatorTelemetry.js
rename : toolkit/components/thumbnails/PageThumbsStorageService.jsm => toolkit/components/thumbnails/PageThumbsStorageService.js
rename : toolkit/components/timermanager/UpdateTimerManager.jsm => toolkit/components/timermanager/nsUpdateTimerManager.js
rename : toolkit/components/tooltiptext/TooltipTextProvider.jsm => toolkit/components/tooltiptext/TooltipTextProvider.js
rename : toolkit/components/url-classifier/UrlClassifierHashCompleter.jsm => toolkit/components/url-classifier/nsUrlClassifierHashCompleter.js
rename : toolkit/components/url-classifier/UrlClassifierLib.jsm => toolkit/components/url-classifier/nsUrlClassifierLib.js
rename : toolkit/components/url-classifier/UrlClassifierListManager.jsm => toolkit/components/url-classifier/nsUrlClassifierListManager.js
rename : toolkit/components/urlformatter/URLFormatter.jsm => toolkit/components/urlformatter/nsURLFormatter.js
rename : toolkit/components/utils/SimpleServices.jsm => toolkit/components/utils/simpleServices.js
rename : toolkit/components/xulstore/XULStore.jsm => toolkit/components/xulstore/XULStore.js
rename : toolkit/mozapps/downloads/HelperAppDlg.jsm => toolkit/mozapps/downloads/nsHelperAppDlg.js
rename : toolkit/mozapps/extensions/amContentHandler.jsm => toolkit/mozapps/extensions/amContentHandler.js
rename : toolkit/mozapps/extensions/amInstallTrigger.jsm => toolkit/mozapps/extensions/amInstallTrigger.js
rename : toolkit/mozapps/extensions/amWebAPI.jsm => toolkit/mozapps/extensions/amWebAPI.js
rename : toolkit/mozapps/handling/ContentDispatchChooser.jsm => toolkit/mozapps/handling/nsContentDispatchChooser.js
rename : toolkit/mozapps/update/UpdateService.jsm => toolkit/mozapps/update/nsUpdateService.js
rename : toolkit/mozapps/update/UpdateServiceStub.jsm => toolkit/mozapps/update/nsUpdateServiceStub.js
rename : uriloader/exthandler/WebHandlerApp.jsm => uriloader/exthandler/nsWebHandlerApp.js
2019-02-14 11:50:23 +02:00

708 lines
21 KiB
C++

/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsWindowsShellService.h"
#include "BinaryPath.h"
#include "city.h"
#include "imgIContainer.h"
#include "imgIRequest.h"
#include "mozilla/RefPtr.h"
#include "nsIContent.h"
#include "nsIImageLoadingContent.h"
#include "nsIPrefService.h"
#include "nsIPrefLocalizedString.h"
#include "nsIServiceManager.h"
#include "nsIStringBundle.h"
#include "nsNetUtil.h"
#include "nsServiceManagerUtils.h"
#include "nsShellService.h"
#include "nsIProcess.h"
#include "nsICategoryManager.h"
#include "nsBrowserCompsCID.h"
#include "nsDirectoryServiceUtils.h"
#include "nsAppDirectoryServiceDefs.h"
#include "nsDirectoryServiceDefs.h"
#include "nsIWindowsRegKey.h"
#include "nsUnicharUtils.h"
#include "nsIURLFormatter.h"
#include "nsXULAppAPI.h"
#include "mozilla/WindowsVersion.h"
#include "mozilla/dom/Element.h"
#include "windows.h"
#include "shellapi.h"
#ifdef _WIN32_WINNT
# undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600
#define INITGUID
#undef NTDDI_VERSION
#define NTDDI_VERSION NTDDI_WIN8
// Needed for access to IApplicationActivationManager
#include <shlobj.h>
#include "WinUtils.h"
#include <mbstring.h>
#include <shlwapi.h>
#include <lm.h>
#undef ACCESS_READ
#ifndef MAX_BUF
# define MAX_BUF 4096
#endif
#define REG_SUCCEEDED(val) (val == ERROR_SUCCESS)
#define REG_FAILED(val) (val != ERROR_SUCCESS)
#define APP_REG_NAME_BASE L"Firefox-"
using mozilla::IsWin8OrLater;
using namespace mozilla;
using namespace mozilla::widget;
NS_IMPL_ISUPPORTS(nsWindowsShellService, nsIToolkitShellService,
nsIShellService)
static nsresult OpenKeyForReading(HKEY aKeyRoot, const nsAString& aKeyName,
HKEY* aKey) {
const nsString& flatName = PromiseFlatString(aKeyName);
DWORD res = ::RegOpenKeyExW(aKeyRoot, flatName.get(), 0, KEY_READ, aKey);
switch (res) {
case ERROR_SUCCESS:
break;
case ERROR_ACCESS_DENIED:
return NS_ERROR_FILE_ACCESS_DENIED;
case ERROR_FILE_NOT_FOUND:
return NS_ERROR_NOT_AVAILABLE;
}
return NS_OK;
}
nsresult GetHelperPath(nsAutoString& aPath) {
nsresult rv;
nsCOMPtr<nsIProperties> directoryService =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> appHelper;
rv = directoryService->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
getter_AddRefs(appHelper));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->SetNativeLeafName(NS_LITERAL_CSTRING("uninstall"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->AppendNative(NS_LITERAL_CSTRING("helper.exe"));
NS_ENSURE_SUCCESS(rv, rv);
rv = appHelper->GetPath(aPath);
aPath.Insert(L'"', 0);
aPath.Append(L'"');
return rv;
}
nsresult LaunchHelper(nsAutoString& aPath) {
STARTUPINFOW si = {sizeof(si), 0};
PROCESS_INFORMATION pi = {0};
if (!CreateProcessW(nullptr, (LPWSTR)aPath.get(), nullptr, nullptr, FALSE, 0,
nullptr, nullptr, &si, &pi)) {
return NS_ERROR_FAILURE;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return NS_OK;
}
static bool IsPathDefaultForClass(
const RefPtr<IApplicationAssociationRegistration>& pAAR, wchar_t* exePath,
LPCWSTR aClassName) {
// Make sure the Prog ID matches what we have
LPWSTR registeredApp;
bool isProtocol = *aClassName != L'.';
ASSOCIATIONTYPE queryType = isProtocol ? AT_URLPROTOCOL : AT_FILEEXTENSION;
HRESULT hr = pAAR->QueryCurrentDefault(aClassName, queryType, AL_EFFECTIVE,
&registeredApp);
if (FAILED(hr)) {
return false;
}
LPCWSTR progID = isProtocol ? L"FirefoxURL" : L"FirefoxHTML";
bool isDefault = !wcsnicmp(registeredApp, progID, wcslen(progID));
nsAutoString regAppName(registeredApp);
CoTaskMemFree(registeredApp);
if (isDefault) {
// Make sure the application path for this progID is this installation.
regAppName.AppendLiteral("\\shell\\open\\command");
HKEY theKey;
nsresult rv = OpenKeyForReading(HKEY_CLASSES_ROOT, regAppName, &theKey);
if (NS_FAILED(rv)) {
return false;
}
wchar_t cmdFromReg[MAX_BUF] = L"";
DWORD len = sizeof(cmdFromReg);
DWORD res = ::RegQueryValueExW(theKey, nullptr, nullptr, nullptr,
(LPBYTE)cmdFromReg, &len);
::RegCloseKey(theKey);
if (REG_FAILED(res)) {
return false;
}
wchar_t fullCmd[MAX_BUF] = L"";
_snwprintf(fullCmd, MAX_BUF, L"\"%s\" -osint -url \"%%1\"", exePath);
isDefault = _wcsicmp(fullCmd, cmdFromReg) == 0;
}
return isDefault;
}
static nsresult GetAppRegName(nsAutoString& aAppRegName) {
nsresult rv;
nsCOMPtr<nsIProperties> dirSvc =
do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID, &rv);
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> exeFile;
rv = dirSvc->Get(XRE_EXECUTABLE_FILE, NS_GET_IID(nsIFile),
getter_AddRefs(exeFile));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIFile> appDir;
rv = exeFile->GetParent(getter_AddRefs(appDir));
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString appDirStr;
rv = appDir->GetPath(appDirStr);
NS_ENSURE_SUCCESS(rv, rv);
aAppRegName = APP_REG_NAME_BASE;
uint64_t hash =
CityHash64(static_cast<const char*>(appDirStr.get()),
appDirStr.Length() * sizeof(nsAutoString::char_type));
aAppRegName.AppendInt((int)(hash >> 32), 16);
aAppRegName.AppendInt((int)hash, 16);
return rv;
}
NS_IMETHODIMP
nsWindowsShellService::IsDefaultBrowser(bool aForAllTypes,
bool* aIsDefaultBrowser) {
*aIsDefaultBrowser = false;
RefPtr<IApplicationAssociationRegistration> pAAR;
HRESULT hr = CoCreateInstance(
CLSID_ApplicationAssociationRegistration, nullptr, CLSCTX_INPROC,
IID_IApplicationAssociationRegistration, getter_AddRefs(pAAR));
if (FAILED(hr)) {
return NS_OK;
}
wchar_t exePath[MAXPATHLEN] = L"";
nsresult rv = BinaryPath::GetLong(exePath);
if (NS_FAILED(rv)) {
return NS_OK;
}
*aIsDefaultBrowser = IsPathDefaultForClass(pAAR, exePath, L"http");
if (*aIsDefaultBrowser && aForAllTypes) {
*aIsDefaultBrowser = IsPathDefaultForClass(pAAR, exePath, L".html");
}
return NS_OK;
}
nsresult nsWindowsShellService::LaunchControlPanelDefaultsSelectionUI() {
IApplicationAssociationRegistrationUI* pAARUI;
HRESULT hr = CoCreateInstance(
CLSID_ApplicationAssociationRegistrationUI, NULL, CLSCTX_INPROC,
IID_IApplicationAssociationRegistrationUI, (void**)&pAARUI);
if (SUCCEEDED(hr)) {
nsAutoString appRegName;
GetAppRegName(appRegName);
hr = pAARUI->LaunchAdvancedAssociationUI(appRegName.get());
pAARUI->Release();
}
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
}
nsresult nsWindowsShellService::LaunchControlPanelDefaultPrograms() {
// Build the path control.exe path safely
WCHAR controlEXEPath[MAX_PATH + 1] = {'\0'};
if (!GetSystemDirectoryW(controlEXEPath, MAX_PATH)) {
return NS_ERROR_FAILURE;
}
LPCWSTR controlEXE = L"control.exe";
if (wcslen(controlEXEPath) + wcslen(controlEXE) >= MAX_PATH) {
return NS_ERROR_FAILURE;
}
if (!PathAppendW(controlEXEPath, controlEXE)) {
return NS_ERROR_FAILURE;
}
nsAutoString params(NS_LITERAL_STRING(
"control.exe /name Microsoft.DefaultPrograms "
"/page pageDefaultProgram\\pageAdvancedSettings?pszAppName="));
nsAutoString appRegName;
GetAppRegName(appRegName);
params.Append(appRegName);
STARTUPINFOW si = {sizeof(si), 0};
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_SHOWDEFAULT;
PROCESS_INFORMATION pi = {0};
if (!CreateProcessW(controlEXEPath, static_cast<LPWSTR>(params.get()),
nullptr, nullptr, FALSE, 0, nullptr, nullptr, &si, &pi)) {
return NS_ERROR_FAILURE;
}
CloseHandle(pi.hProcess);
CloseHandle(pi.hThread);
return NS_OK;
}
static bool IsWindowsLogonConnected() {
WCHAR userName[UNLEN + 1];
DWORD size = ArrayLength(userName);
if (!GetUserNameW(userName, &size)) {
return false;
}
LPUSER_INFO_24 info;
if (NetUserGetInfo(nullptr, userName, 24, (LPBYTE*)&info) != NERR_Success) {
return false;
}
bool connected = info->usri24_internet_identity;
NetApiBufferFree(info);
return connected;
}
static bool SettingsAppBelievesConnected() {
nsresult rv;
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
if (NS_FAILED(rv)) {
return false;
}
rv = regKey->Open(
nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
NS_LITERAL_STRING("SOFTWARE\\Microsoft\\Windows\\Shell\\Associations"),
nsIWindowsRegKey::ACCESS_READ);
if (NS_FAILED(rv)) {
return false;
}
uint32_t value;
rv = regKey->ReadIntValue(NS_LITERAL_STRING("IsConnectedAtLogon"), &value);
if (NS_FAILED(rv)) {
return false;
}
return !!value;
}
nsresult nsWindowsShellService::LaunchModernSettingsDialogDefaultApps() {
if (!IsWindowsBuildOrLater(14965) && !IsWindowsLogonConnected() &&
SettingsAppBelievesConnected()) {
// Use the classic Control Panel to work around a bug of older
// builds of Windows 10.
return LaunchControlPanelDefaultPrograms();
}
IApplicationActivationManager* pActivator;
HRESULT hr = CoCreateInstance(
CLSID_ApplicationActivationManager, nullptr, CLSCTX_INPROC,
IID_IApplicationActivationManager, (void**)&pActivator);
if (SUCCEEDED(hr)) {
DWORD pid;
hr = pActivator->ActivateApplication(
L"windows.immersivecontrolpanel_cw5n1h2txyewy"
L"!microsoft.windows.immersivecontrolpanel",
L"page=SettingsPageAppsDefaults", AO_NONE, &pid);
if (SUCCEEDED(hr)) {
// Do not check error because we could at least open
// the "Default apps" setting.
pActivator->ActivateApplication(
L"windows.immersivecontrolpanel_cw5n1h2txyewy"
L"!microsoft.windows.immersivecontrolpanel",
L"page=SettingsPageAppsDefaults"
L"&target=SystemSettings_DefaultApps_Browser",
AO_NONE, &pid);
}
pActivator->Release();
return SUCCEEDED(hr) ? NS_OK : NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult nsWindowsShellService::InvokeHTTPOpenAsVerb() {
nsCOMPtr<nsIURLFormatter> formatter(
do_GetService("@mozilla.org/toolkit/URLFormatterService;1"));
if (!formatter) {
return NS_ERROR_UNEXPECTED;
}
nsString urlStr;
nsresult rv = formatter->FormatURLPref(
NS_LITERAL_STRING("app.support.baseURL"), urlStr);
if (NS_FAILED(rv)) {
return rv;
}
if (!StringBeginsWith(urlStr, NS_LITERAL_STRING("https://"))) {
return NS_ERROR_FAILURE;
}
urlStr.AppendLiteral("win10-default-browser");
SHELLEXECUTEINFOW seinfo = {sizeof(SHELLEXECUTEINFOW)};
seinfo.lpVerb = L"openas";
seinfo.lpFile = urlStr.get();
seinfo.nShow = SW_SHOWNORMAL;
if (!ShellExecuteExW(&seinfo)) {
return NS_ERROR_FAILURE;
}
return NS_OK;
}
nsresult nsWindowsShellService::LaunchHTTPHandlerPane() {
OPENASINFO info;
info.pcszFile = L"http";
info.pcszClass = nullptr;
info.oaifInFlags =
OAIF_FORCE_REGISTRATION | OAIF_URL_PROTOCOL | OAIF_REGISTER_EXT;
HRESULT hr = SHOpenWithDialog(nullptr, &info);
if (SUCCEEDED(hr) || (hr == HRESULT_FROM_WIN32(ERROR_CANCELLED))) {
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsWindowsShellService::SetDefaultBrowser(bool aClaimAllTypes,
bool aForAllUsers) {
nsAutoString appHelperPath;
if (NS_FAILED(GetHelperPath(appHelperPath))) return NS_ERROR_FAILURE;
if (aForAllUsers) {
appHelperPath.AppendLiteral(" /SetAsDefaultAppGlobal");
} else {
appHelperPath.AppendLiteral(" /SetAsDefaultAppUser");
}
nsresult rv = LaunchHelper(appHelperPath);
if (NS_SUCCEEDED(rv) && IsWin8OrLater()) {
if (aClaimAllTypes) {
if (IsWin10OrLater()) {
rv = LaunchModernSettingsDialogDefaultApps();
} else {
rv = LaunchControlPanelDefaultsSelectionUI();
}
// The above call should never really fail, but just in case
// fall back to showing the HTTP association screen only.
if (NS_FAILED(rv)) {
if (IsWin10OrLater()) {
rv = InvokeHTTPOpenAsVerb();
} else {
rv = LaunchHTTPHandlerPane();
}
}
} else {
// Windows 10 blocks attempts to load the
// HTTP Handler association dialog.
if (IsWin10OrLater()) {
rv = LaunchModernSettingsDialogDefaultApps();
} else {
rv = LaunchHTTPHandlerPane();
}
// The above call should never really fail, but just in case
// fall back to showing control panel for all defaults
if (NS_FAILED(rv)) {
rv = LaunchControlPanelDefaultsSelectionUI();
}
}
}
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
if (prefs) {
(void)prefs->SetBoolPref(PREF_CHECKDEFAULTBROWSER, true);
// Reset the number of times the dialog should be shown
// before it is silenced.
(void)prefs->SetIntPref(PREF_DEFAULTBROWSERCHECKCOUNT, 0);
}
return rv;
}
NS_IMETHODIMP
nsWindowsShellService::SetDesktopBackground(dom::Element* aElement,
int32_t aPosition,
const nsACString& aImageName) {
if (!aElement || !aElement->IsHTMLElement(nsGkAtoms::img)) {
// XXX write background loading stuff!
return NS_ERROR_NOT_AVAILABLE;
}
nsresult rv;
nsCOMPtr<nsIImageLoadingContent> imageContent =
do_QueryInterface(aElement, &rv);
if (!imageContent) return rv;
// get the image container
nsCOMPtr<imgIRequest> request;
rv = imageContent->GetRequest(nsIImageLoadingContent::CURRENT_REQUEST,
getter_AddRefs(request));
if (!request) return rv;
nsCOMPtr<imgIContainer> container;
rv = request->GetImage(getter_AddRefs(container));
if (!container) return NS_ERROR_FAILURE;
// get the file name from localized strings
nsCOMPtr<nsIStringBundleService> bundleService(
do_GetService(NS_STRINGBUNDLE_CONTRACTID, &rv));
NS_ENSURE_SUCCESS(rv, rv);
nsCOMPtr<nsIStringBundle> shellBundle;
rv = bundleService->CreateBundle(SHELLSERVICE_PROPERTIES,
getter_AddRefs(shellBundle));
NS_ENSURE_SUCCESS(rv, rv);
// e.g. "Desktop Background.bmp"
nsAutoString fileLeafName;
rv = shellBundle->GetStringFromName("desktopBackgroundLeafNameWin",
fileLeafName);
NS_ENSURE_SUCCESS(rv, rv);
// get the profile root directory
nsCOMPtr<nsIFile> file;
rv = NS_GetSpecialDirectory(NS_APP_APPLICATION_REGISTRY_DIR,
getter_AddRefs(file));
NS_ENSURE_SUCCESS(rv, rv);
// eventually, the path is "%APPDATA%\Mozilla\Firefox\Desktop Background.bmp"
rv = file->Append(fileLeafName);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString path;
rv = file->GetPath(path);
NS_ENSURE_SUCCESS(rv, rv);
// write the bitmap to a file in the profile directory
rv = WinUtils::WriteBitmap(file, container);
// if the file was written successfully, set it as the system wallpaper
if (NS_SUCCEEDED(rv)) {
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
NS_LITERAL_STRING("Control Panel\\Desktop"),
nsIWindowsRegKey::ACCESS_SET_VALUE);
NS_ENSURE_SUCCESS(rv, rv);
nsAutoString tile;
nsAutoString style;
switch (aPosition) {
case BACKGROUND_TILE:
style.Assign('0');
tile.Assign('1');
break;
case BACKGROUND_CENTER:
style.Assign('0');
tile.Assign('0');
break;
case BACKGROUND_STRETCH:
style.Assign('2');
tile.Assign('0');
break;
case BACKGROUND_FILL:
style.AssignLiteral("10");
tile.Assign('0');
break;
case BACKGROUND_FIT:
style.Assign('6');
tile.Assign('0');
break;
}
rv = regKey->WriteStringValue(NS_LITERAL_STRING("TileWallpaper"), tile);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->WriteStringValue(NS_LITERAL_STRING("WallpaperStyle"), style);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->Close();
NS_ENSURE_SUCCESS(rv, rv);
::SystemParametersInfoW(SPI_SETDESKWALLPAPER, 0, (PVOID)path.get(),
SPIF_UPDATEINIFILE | SPIF_SENDCHANGE);
}
return rv;
}
NS_IMETHODIMP
nsWindowsShellService::OpenApplication(int32_t aApplication) {
nsAutoString application;
switch (aApplication) {
case nsIShellService::APPLICATION_MAIL:
application.AssignLiteral("Mail");
break;
case nsIShellService::APPLICATION_NEWS:
application.AssignLiteral("News");
break;
}
// The Default Client section of the Windows Registry looks like this:
//
// Clients\aClient\
// e.g. aClient = "Mail"...
// \Mail\(default) = Client Subkey Name
// \Client Subkey Name
// \Client Subkey Name\shell\open\command\
// \Client Subkey Name\shell\open\command\(default) = path to exe
//
// Find the default application for this class.
HKEY theKey;
nsresult rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
if (NS_FAILED(rv)) return rv;
wchar_t buf[MAX_BUF];
DWORD type, len = sizeof buf;
DWORD res = ::RegQueryValueExW(theKey, EmptyString().get(), 0, &type,
(LPBYTE)&buf, &len);
if (REG_FAILED(res) || !*buf) return NS_OK;
// Close the key we opened.
::RegCloseKey(theKey);
// Find the "open" command
application.Append('\\');
application.Append(buf);
application.AppendLiteral("\\shell\\open\\command");
rv = OpenKeyForReading(HKEY_CLASSES_ROOT, application, &theKey);
if (NS_FAILED(rv)) return rv;
::ZeroMemory(buf, sizeof(buf));
len = sizeof buf;
res = ::RegQueryValueExW(theKey, EmptyString().get(), 0, &type, (LPBYTE)&buf,
&len);
if (REG_FAILED(res) || !*buf) return NS_ERROR_FAILURE;
// Close the key we opened.
::RegCloseKey(theKey);
// Look for any embedded environment variables and substitute their
// values, as |::CreateProcessW| is unable to do this.
nsAutoString path(buf);
int32_t end = path.Length();
int32_t cursor = 0, temp = 0;
::ZeroMemory(buf, sizeof(buf));
do {
cursor = path.FindChar('%', cursor);
if (cursor < 0) break;
temp = path.FindChar('%', cursor + 1);
++cursor;
::ZeroMemory(&buf, sizeof(buf));
::GetEnvironmentVariableW(
nsAutoString(Substring(path, cursor, temp - cursor)).get(), buf,
sizeof(buf));
// "+ 2" is to subtract the extra characters used to delimit the environment
// variable ('%').
path.Replace((cursor - 1), temp - cursor + 2, nsDependentString(buf));
++cursor;
} while (cursor < end);
STARTUPINFOW si;
PROCESS_INFORMATION pi;
::ZeroMemory(&si, sizeof(STARTUPINFOW));
::ZeroMemory(&pi, sizeof(PROCESS_INFORMATION));
BOOL success = ::CreateProcessW(nullptr, (LPWSTR)path.get(), nullptr, nullptr,
FALSE, 0, nullptr, nullptr, &si, &pi);
if (!success) return NS_ERROR_FAILURE;
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::GetDesktopBackgroundColor(uint32_t* aColor) {
uint32_t color = ::GetSysColor(COLOR_DESKTOP);
*aColor =
(GetRValue(color) << 16) | (GetGValue(color) << 8) | GetBValue(color);
return NS_OK;
}
NS_IMETHODIMP
nsWindowsShellService::SetDesktopBackgroundColor(uint32_t aColor) {
int aParameters[2] = {COLOR_BACKGROUND, COLOR_DESKTOP};
BYTE r = (aColor >> 16);
BYTE g = (aColor << 16) >> 24;
BYTE b = (aColor << 24) >> 24;
COLORREF colors[2] = {RGB(r, g, b), RGB(r, g, b)};
::SetSysColors(sizeof(aParameters) / sizeof(int), aParameters, colors);
nsresult rv;
nsCOMPtr<nsIWindowsRegKey> regKey =
do_CreateInstance("@mozilla.org/windows-registry-key;1", &rv);
NS_ENSURE_SUCCESS(rv, rv);
rv = regKey->Create(nsIWindowsRegKey::ROOT_KEY_CURRENT_USER,
NS_LITERAL_STRING("Control Panel\\Colors"),
nsIWindowsRegKey::ACCESS_SET_VALUE);
NS_ENSURE_SUCCESS(rv, rv);
wchar_t rgb[12];
_snwprintf(rgb, 12, L"%u %u %u", r, g, b);
rv = regKey->WriteStringValue(NS_LITERAL_STRING("Background"),
nsDependentString(rgb));
NS_ENSURE_SUCCESS(rv, rv);
return regKey->Close();
}
nsWindowsShellService::nsWindowsShellService() {}
nsWindowsShellService::~nsWindowsShellService() {}
NS_IMETHODIMP
nsWindowsShellService::OpenApplicationWithURI(nsIFile* aApplication,
const nsACString& aURI) {
nsresult rv;
nsCOMPtr<nsIProcess> process =
do_CreateInstance("@mozilla.org/process/util;1", &rv);
if (NS_FAILED(rv)) return rv;
rv = process->Init(aApplication);
if (NS_FAILED(rv)) return rv;
const nsCString spec(aURI);
const char* specStr = spec.get();
return process->Run(false, &specStr, 1);
}